> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vidocsecurity.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP

> Connect your coding agent to Vidoc to read security findings and change issue status.

The Vidoc Model Context Protocol (MCP) server lets a coding agent read security findings and pull request results. The agent can get a fix prompt and change the status of an issue.

The server reads the scan results stored in Vidoc. To start a scan, use the [CLI](/cli/scanning), the [REST API](/api/scanning), or the web app.

## How it works

Your MCP client connects to the Vidoc API at `/mcp` with **Streamable HTTP**. It sends a user API key in the `Authorization: Bearer <key>` header. The server checks your project access and role on each request.

* Each connection has access to one project: the project of the key. For another project, create another key and add a server with a different name.
* The server lists only the tools that your role permits.
* Findings include validated true positives. False positives and findings that still need validation do not appear. Experiment pull requests do not appear.
* The agent changes files in your local repository through its editor. The MCP server can change only the status of an issue in Vidoc.

## Set up the connection

### 1. Create a user API key

1. Open [app.vidoc.dev](https://app.vidoc.dev) or your custom deployment URL.
2. Select the project that has the repositories you want to read.
3. Open **Project switcher > API keys** and select **Create new key**.
4. Enter a name, such as `MCP local development`, and select an expiry.
5. Create and copy the key. Refer to [API Keys](/settings/api-keys) for key management.

MCP accepts only keys that belong to a user. System, GitHub, and legacy tokens get `403 MCP accepts user tokens only`. A `read_only` member cannot create a key. The roles `developer`, `security_engineer`, and `admin` can create keys and change issue status.

<Note>
  The default expiry is **1 month**. For a connection that you use over a longer period, select **6 months** or **1 year** and plan to replace the key before it expires. The `whoami` tool reports the expiry date.
</Note>

Set the key in the environment of your MCP client:

```bash theme={null}
export VIDOC_TOKEN="<your-user-api-key>"
```

### 2. Select the API URL

Set `VIDOC_API_URL` without a trailing slash or `/v1`. Use the API address, not the web app address.

<Tabs>
  <Tab title="Vidoc Cloud">
    ```bash theme={null}
    export VIDOC_API_URL="https://api.vidoc.dev"
    ```
  </Tab>

  <Tab title="Self-hosted">
    Use the API address from your admin:

    ```bash theme={null}
    export VIDOC_API_URL="https://api.example.com"
    ```

    Use a key from this installation. Send it only to your installation's API.
  </Tab>
</Tabs>

The MCP URL is `${VIDOC_API_URL}/mcp`. It does not include `/v1`.

<Note>
  **Self-hosted:** your operators must enable MCP on the API with `MCP_ENABLED=true`. The flag is off by default. If it is off, `POST /mcp` returns `404`. Ask your operators to check the flag and the route in the supplied release runbook.
</Note>

### 3. Configure your client

<Tabs>
  <Tab title="Claude Code">
    For one local connection, run this command from your repository:

    ```bash theme={null}
    claude mcp add --transport http vidoc "${VIDOC_API_URL:?Set VIDOC_API_URL}/mcp" \
      --header "Authorization: Bearer ${VIDOC_TOKEN:?Set VIDOC_TOKEN}"
    ```

    This command stores the key in your local Claude Code configuration. To share the configuration with your team, use environment variables in `.mcp.json` at the root of the repository instead:

    ```json theme={null}
    {
      "mcpServers": {
        "vidoc": {
          "type": "http",
          "url": "${VIDOC_API_URL}/mcp",
          "headers": {
            "Authorization": "Bearer ${VIDOC_TOKEN}"
          }
        }
      }
    }
    ```

    Start Claude Code from the shell where you exported both variables. Run `/mcp` in Claude Code to check the connection. Approve the project server when Claude Code asks.

    Refer to the [Claude Code MCP documentation](https://code.claude.com/docs/en/mcp) for client configuration.
  </Tab>

  <Tab title="Cursor">
    Add this configuration to `.cursor/mcp.json` in your repository:

    ```json theme={null}
    {
      "mcpServers": {
        "vidoc": {
          "url": "${env:VIDOC_API_URL}/mcp",
          "headers": {
            "Authorization": "Bearer ${env:VIDOC_TOKEN}"
          }
        }
      }
    }
    ```

    Make both variables available to the Cursor process before you start it. An export in a terminal does not update the environment of a Cursor process that is already open. Enable the `vidoc` server in Cursor's MCP settings.

    Refer to the [Cursor MCP documentation](https://cursor.com/docs/mcp) for client configuration and environment variables.
  </Tab>

  <Tab title="MCP Inspector">
    Run:

    ```bash theme={null}
    npx @modelcontextprotocol/inspector
    ```

    In the Inspector, select **Streamable HTTP**. Enter your API address with `/mcp`, for example `https://api.vidoc.dev/mcp` for Vidoc Cloud. Add the header `Authorization: Bearer <your-user-api-key>`, then connect.
  </Tab>
</Tabs>

Keep the key out of shared configuration files. The Claude Code and Cursor JSON examples contain variable references, so you can commit them without the key.

### 4. Check the connection

Ask your agent:

```text theme={null}
Call Vidoc whoami and tell me which project this connection can access.
```

The result reports the user, organization, project, role, and key expiry. Check the project before you ask the agent to read or change an issue.

### 5. Read or fix an issue

Open the repository in your client and ask:

```text theme={null}
Fix the most severe Vidoc issue in this repository.
```

The agent uses these steps:

1. Call `whoami` to check the project.
2. Call `list_codebases`. Match the local Git remote with the `scmRepoSlug` or `url` of a repository and get its `codebaseId`.
3. Call `list_issues` with that `codebaseId`. The list has the most severe issues first.
4. Call `get_issue` for the finding details or `get_fix_prompt` for a fix prompt.
5. Change the local code and check the fix. Then call `update_issue_status` with `closed`.

For a pull request, ask:

```text theme={null}
What did Vidoc find in pull request #412 in this repository?
```

The agent gets the `codebaseId` with `list_codebases`, then calls `get_pull_request_issues` with `pullRequest: "#412"`. If you do not know the number, ask it to search with `list_pull_requests` first.

## Available tools

| Tool | Use |
| - | - |
| `whoami` | Read the connection's user, organization, project, role, and key expiry. |
| `list_codebases` | List project repositories, their open issue counts on the default branch, and the last scan time. |
| `list_branches` | List the known branches of a repository. Requires `codebaseId`. |
| `list_issues` | List validated findings. Filter with `codebaseId`, `branch`, `status`, `path`, or `severities`. A `branch` filter requires `codebaseId`. |
| `get_issue` | Read one finding with its validation reason, status reason, and source snippet. Requires `instanceId`. The snippet has at most 60 lines. |
| `get_fix_prompt` | Get a prompt with the finding and code to fix. Requires `instanceId`. |
| `list_pull_requests` | List scanned pull requests. Filter with `codebaseId`, `search`, or `hasIssues`. The search matches the title, number, branch, or author. |
| `get_pull_request_issues` | Read the findings of one pull request. Requires `codebaseId` and `pullRequest`. The reference can be a number string, `#number`, or a `pullRequestId` from `list_pull_requests`. |
| `update_issue_status` | Set one finding to `open`, `closed`, or `ignored`. Requires `instanceId` and `status`; `ignored` also requires `reason`. |

The read tools need `issue:view`. The status tool needs `issue:update_status` and is hidden from a `read_only` connection.

### Filters and result fields

* `list_issues` uses the default branch when you omit `branch`. Without `codebaseId`, it reads the default branches of all project repositories.
* The issue lists default to `status: "open"`. They also accept `ignored`, `fixed`, `closed`, and `all`. The `closed` filter includes findings that a scan marked `fixed`.
* `list_issues`, `list_pull_requests`, and `get_pull_request_issues` return 20 rows by default and at most 50 rows. Use `nextOffset` as the next `offset` until it is `null`.
* `list_codebases` and `list_branches` return all their rows.
* `hiddenByPolicy` reports findings hidden by the triage policy, such as duplicates or deferred findings. Pass `codebaseId` to get the triaged list of one repository. In a project with more than 50 triaged branches, a list without `codebaseId` returns the raw list.
* The tool fields `line`, `rangeStart`, and `rangeEnd` count from zero. Add 1 for editor line numbers. Line numbers inside a fix prompt already count from 1.
* If `snippetTruncated` is `true`, `get_issue` cut the source snippet. Read the local file for more context.

### Status changes

`update_issue_status` records your user as the author of the change. It can change only a finding that the connection can read.

Use `closed` after you fix the code. The tool does not accept `fixed`: a scan sets that status when it confirms that the finding is gone.

To ignore a finding, provide a reason of at least 5 characters. The reason starts a [learning](/web-app/memory) that affects how later scans judge similar code. The tool tells the agent to get your approval before it ignores a finding.

If the learning cannot start, the tool can report an error after the status has changed. Read the issue again before you retry an ignored status change.

## Troubleshooting

| Symptom | Check or action |
| - | - |
| `404` on `POST /mcp` | Check the API address and the `/mcp` path. The path has no `/v1`. Ask your operators to check `MCP_ENABLED=true` and route access. |
| `401 Token is missing` | Send `Authorization: Bearer <key>`. MCP does not read the REST header `x-vidoc-token`. Check that the client can read `VIDOC_TOKEN`. |
| `401 Invalid or expired token` | Check the key's expiry and installation. The key may be expired or deleted, or its project may be deleted. Create a new user key if needed. |
| `403 MCP accepts user tokens only` | Create a key in the project's API keys page. Do not use a system, GitHub, or legacy token. |
| `403 You do not have access to this project` | The key's user no longer has access to the project. Ask your admin to check membership. |
| `405` on `GET` or `DELETE` | Expected. The endpoint is stateless and accepts only `POST`. Opening the URL in a browser does not test the connection. |
| `406 Not Acceptable` | An HTTP script must send `Accept: application/json, text/event-stream`. MCP clients send it automatically. |
| The client cannot connect | Select Streamable HTTP. Check the API URL, network access, and client environment variables. |
| No findings | Check the project with `whoami`, the repository with `list_codebases`, and the branch with `list_branches`. Findings that still need validation and false positives do not appear. |

## Related pages

<CardGroup cols={2}>
  <Card title="API Keys" icon="key" href="/settings/api-keys">
    Create and replace user API keys.
  </Card>

  <Card title="Findings" icon="bug" href="/web-app/findings">
    Read and manage findings in the web app.
  </Card>

  <Card title="API Authentication" icon="code" href="/api/authentication">
    Configure REST API access.
  </Card>

  <Card title="CLI Scanning" icon="terminal" href="/cli/scanning">
    Scan code from your terminal.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.