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

# Odin MCP Server

> Give Cursor and other coding agents safe, GitHub-first remediation context

The Odin MCP server connects your coding agent to your organisation's security data. Ask Cursor, Claude, Codex, or another [Model Context Protocol](https://modelcontextprotocol.io) client about a finding such as `ODI-12`, inspect its remediation guidance, create the code change and pull request yourself, then ask Odin to link the existing pull request and report the retest.

Odin is organisation-scoped and GitHub-first. It provides context and workflow operations; it never creates commits, pushes branches, or creates pull requests.

The server is published on npm as [`@borgresearch/odin-mcp`](https://www.npmjs.com/package/@borgresearch/odin-mcp). It runs locally as a subprocess of your client, talks to the public Odin API, and authenticates with an [API key](/platform/api-keys).

<Info>
  You need Node.js 24 or newer on your `PATH`. A **Read only** key is enough to discover findings, read remediation context, and inspect retest history. Choose **Read & Write** when the agent must update a status or link an existing pull request.
</Info>

<Info>
  To update an existing setup, change the package in your client config to `@borgresearch/odin-mcp@latest` and restart the client. For a global install, run `npm install -g @borgresearch/odin-mcp@latest`.
</Info>

## Setting up

<Steps>
  <Step title="Create an API key">
    Go to **Management > API Keys** and create a key. The dialog defaults to **Read & Write** for the remediation workflow, but **Read only** remains available when the agent should only inspect data. The full key is shown once, so copy it before closing the dialog.
  </Step>

  <Step title="Add the server to your client">
    Expand **Setup guide: connect an AI agent** on the API Keys page and copy the snippet for your client. If you've just created a key, the snippet already has it filled in.
  </Step>

  <Step title="Restart the client">
    Most clients only read their MCP configuration at startup. After restarting, check the client's list of MCP servers for `odin` and confirm it reports nine tools.
  </Step>

  <Step title="Ask about a finding">
    Try: *"Explain `ODI-12`, show me the suggested branch, and tell me what I need to do before opening a PR."*
  </Step>
</Steps>

## Client configuration

Replace `odin_...` with your own key in each snippet.

<AccordionGroup>
  <Accordion title="Cursor">
    Add to your project's `.cursor/mcp.json`, or open **Settings › MCP** and add a new server.

    ```json theme={null}
    {
      "mcpServers": {
        "odin": {
          "command": "npx",
          "args": ["-y", "@borgresearch/odin-mcp@latest"],
          "env": {
            "ODIN_API_KEY": "odin_..."
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Claude Desktop">
    Add to `claude_desktop_config.json`, then restart Claude Desktop.

    ```json theme={null}
    {
      "mcpServers": {
        "odin": {
          "command": "npx",
          "args": ["-y", "@borgresearch/odin-mcp@latest"],
          "env": {
            "ODIN_API_KEY": "odin_..."
          }
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Claude Code">
    ```bash theme={null}
    claude mcp add --transport stdio --env ODIN_API_KEY=odin_... odin -- npx -y @borgresearch/odin-mcp@latest
    ```
  </Accordion>

  <Accordion title="Codex">
    Add to `~/.codex/config.toml`, then restart Codex.

    ```toml theme={null}
    [mcp_servers.odin]
    command = "npx"
    args = ["-y", "@borgresearch/odin-mcp@latest"]
    env = { ODIN_API_KEY = "odin_..." }
    ```
  </Accordion>

  <Accordion title="Windsurf, VS Code Copilot, Cline, and others">
    Point the client at `npx -y @borgresearch/odin-mcp@latest` and pass `ODIN_API_KEY` in its environment. See the [package README](https://www.npmjs.com/package/@borgresearch/odin-mcp) for client-specific paths.
  </Accordion>
</AccordionGroup>

## Tools

Every tool returns a readable Markdown summary and a structured payload. Human identifiers are organisation-local; `ODI-12` is preferred, while the internal ID remains available for chaining.

| Tool                        | Permission   | What it does                                                                                                                    |
| --------------------------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `list_findings`             | Read         | Lists findings with pagination, current status, severity, repository, and identifier/title search                               |
| `get_finding`               | Read         | Returns bounded remediation context, revision content, suggested branch, linked PRs, workflow blockers, and latest retest state |
| `update_finding_status`     | Read & Write | Moves a finding to Mitigating, Open for Retest, or Acknowledged                                                                 |
| `link_finding_pull_request` | Read & Write | Links one existing accessible GitHub PR; it does not create or change the PR                                                    |
| `get_finding_retests`       | Read         | Reads retest history without triggering a retest or spending credits                                                            |
| `list_pentests`             | Read         | Lists pentests for the organisation                                                                                             |
| `get_pentest`               | Read         | Fetches a pentest's status, schedule, and scope                                                                                 |
| `list_assets`               | Read         | Lists attack-surface assets with filters and pagination                                                                         |
| `get_asset`                 | Read         | Fetches an asset and the findings that reference it                                                                             |

### Finding references

Use the human identifier shown in Odin:

```text theme={null}
ODI-12
```

The prefix is an alias, not a global namespace. Odin resolves the numeric suffix only inside the organisation belonging to the API key and always returns the finding's canonical stored identifier. A reference from another organisation is not revealed through an error. Internal finding IDs are supported when chaining results between tools.

### Remediation flow

1. Ask `get_finding` about `ODI-12`.
2. Read the remediation, code reference, workflow blockers, and `suggestedBranch` (for example, `fix/odi-12-sql-injection-in-login-form`).
3. In Cursor or your normal development environment, create that branch, make and test the change, commit it, push it, and open the GitHub PR yourself.
4. Explicitly ask the agent to use `link_finding_pull_request` with the existing PR URL. Odin verifies the PR through your organisation's GitHub App installation and stores authoritative metadata. Linking the same PR again is safe and idempotent.
5. When the linked PR merges, GitHub webhook processing may queue an automatic retest if the organisation's GitHub and retest prerequisites are ready. Use `get_finding_retests` to distinguish no history, queued/running, completed, skipped, and failed runs.

Odin does not infer permission from a matching PR and agents should not mutate a finding merely because a URL or identifier looks correct. Ask before linking a PR or changing status.

### Updating a finding's status

`update_finding_status` needs an API key with **Read & Write** permission. Cookie-authenticated dashboard requests also need a member role or higher:

| Status            | Use it when                       |
| ----------------- | --------------------------------- |
| `MITIGATING`      | You have started work on the fix  |
| `OPEN_FOR_RETEST` | The fix is ready for verification |
| `ACKNOWLEDGED`    | You accept the risk for now       |

`NEEDS_REVISION` and `FIXED_AND_RETESTED` are set by Borg's retest process and are not client-writable.

### Retests

`get_finding_retests` is read-only. It never calls the manual retest endpoint, queues work, or spends credits. A completed retest exposes its sanitised verdict and status action without billing fields. Automatic retests are merge/webhook-driven; see [Automatic Retests](/platform/automatic-retests).

## Permissions and scoping

Every call is scoped to the single organisation that owns the API key. If you belong to several organisations, create one key per organisation and register each as a separate MCP server, such as `odin-acme` and `odin-internal`.

* **Read only**: discovery, finding remediation context, linked-PR discovery, and retest reads.
* **Read & Write**: all Read-only actions plus status changes and linking an existing accessible GitHub PR.
* **Member role**: required for status changes and PR-link mutations from a cookie-authenticated dashboard request. MCP API-key calls are authorised by the key's Read & Write permission.

The API key does not grant repository access beyond the organisation's configured GitHub App installation. A PR in an inaccessible repository is rejected without creating a link.

## Rate limits

Each key is limited to 100 requests per minute. `429` responses include retry guidance.

## Troubleshooting

<AccordionGroup>
  <Accordion title="ODIN_API_KEY is not set or invalid">
    Check the key under **Management > API Keys**, confirm the client config sets `ODIN_API_KEY`, and restart the client. Most clients only reload MCP configuration at startup.
  </Accordion>

  <Accordion title="API key does not have write permission">
    The agent attempted a status change or PR link with a Read-only key. Create a new **Read & Write** key; permissions on an existing key are not silently upgraded.
  </Accordion>

  <Accordion title="Finding not found">
    Confirm the human identifier, and remember that identifiers and API keys are organisation-scoped. A different organisation's finding is intentionally indistinguishable from an unknown finding.
  </Accordion>

  <Accordion title="Retest history is unavailable">
    The organisation's retest automation capability is gated or not configured. This does not allow the MCP to trigger a manual retest; check the GitHub and automatic-retest settings.
  </Accordion>

  <Accordion title="The server starts but no tools appear">
    Check the client's MCP logs and restart it after changing configuration. The server needs Node.js 24 or newer.
  </Accordion>
</AccordionGroup>

<CardGroup cols={2}>
  <Card title="API Keys" icon="key" href="/platform/api-keys">
    Create, scope, and revoke the keys the server authenticates with
  </Card>

  <Card title="Automatic Retests" icon="circle-check" href="/platform/automatic-retests">
    Understand merge-driven verification and retest outcomes
  </Card>
</CardGroup>
