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

# Connect MCP servers

> Add a remote MCP server's tools to an agent, authenticate it with a vault credential, and test the connection before a session depends on it.

An MCP server is a remote service that offers tools over the Model Context Protocol. When you add one to an agent, each session connects to the server, discovers its tools, and lets the agent call them. Calls are made outside the sandbox, so the server's token never enters the sandbox or the model's context.

This page covers agents calling out to MCP servers. To connect your coding assistant to these docs or to the Managed Agents MCP endpoint, see [Use with AI coding agents](/recursion/ai-coding-agents).

<Note>
  Changing an agent or testing a server needs the organization developer or admin role. Testing a server needs the create permission, so the organization user role can't run a test. See [Organizations and roles](/recursion/organizations-and-roles). The server must use the Streamable HTTP transport at a public `http` or `https` URL. Servers on private, loopback, or link-local addresses are refused. Local servers that run over stdio aren't supported. If the server needs a token, have it ready; the token goes in a vault.
</Note>

<Tip>
  If the service is one of the 164+ apps in [Integrations](/recursion/integrations), you can connect it there instead and choose its tools, without handling a token.
</Tip>

<Accordion title="About the Managed Agents MCP endpoint">
  On the Managed Agents MCP endpoint, operation arguments name path parameters in camelCase, such as `vaultId`, while request bodies keep their snake\_case fields, such as `vault_id`. Create skills with scripts, and read a skill version's content, in the console or with the REST API.
</Accordion>

## Add an MCP server to an agent

Each server entry has a `name` and a `url`. MCP servers belong to the agent version, so adding one creates a new version. Running sessions keep the tools they started with.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Agents** and open the agent.
    2. On **Configuration**, find **Tools** and click **Add MCP server**.
    3. Enter a **Server name**, then choose a server from the list or type its **Server URL**. The list suggests common servers, such as GitHub, Notion, Linear, Sentry, Context7, and Slack, and says what kind of token each needs.
    4. Click **Save new version**.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/agents/5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55/versions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "base_agent_version_id": "c1a94e07-2f6b-4d18-b3a5-0e7d8c6f4a21",
        "name": "Release coordinator",
        "model": "<model-id>",
        "system": "Track the release and report blocked work.",
        "mcp_servers": [{"name": "project-tracker", "url": "https://mcp.example.com/mcp"}],
        "default_vault_ids": ["26d4b1a8-73c9-4f60-8a15-9e2c7b5d4f31"]
      }'
    ```
  </Tab>
</Tabs>

The response is the agent at its new version:

```json theme={"theme":"css-variables"}
{
  "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
  "latest_agent_version_id": "7a4e1c95-6d2f-4380-b915-3e7a0c6f2d84",
  "mcp_servers": [{ "name": "project-tracker", "url": "https://mcp.example.com/mcp" }],
  "default_vault_ids": ["26d4b1a8-73c9-4f60-8a15-9e2c7b5d4f31"]
}
```

If the server `project-tracker` offers `list_issues`, the agent sees `project-tracker__list_issues`. The prefix keeps two servers from clashing. A new version replaces the whole definition, so send `skills`, tool settings, vault defaults, and every other field you want to keep. See [Agents](/recursion/agents). Next, [authenticate the server](#authenticate-the-server).

<Accordion title="Server entry fields">
  | Field | Description |
  | - | - |
  | `name` | The label the server's tools are grouped under. Characters other than letters, digits, `_`, and `-` become `-` in tool names. |
  | `url` | The server's full Streamable HTTP endpoint, `http` or `https`, with no user name or password in it. Use `https` whenever a token is sent. |
</Accordion>

## Authenticate the server

Store the server's token in a [vault](/recursion/vaults) as a **Token for an MCP server** (`bearer_token`) whose server URL matches the agent's `url`. Then grant the vault to the agent with `default_vault_ids`, or to a session with `vault_ids`. If you narrow grants with credential refs, include this credential.

Tokens that you paste are stored as-is and aren't refreshed. If the server issues short-lived OAuth access tokens, [rotate the credential](/recursion/vaults#rotate-a-credential) before it expires.

<Warning>
  **A granted token also adds its server.** A token for an MCP server in a granted vault adds its server's tools to the session even if the agent doesn't list that server. Those tools get a generated `vault-...` prefix. To keep a server out of a session, don't grant the vault that holds its token, or leave the credential out of the credential refs.
</Warning>

<Accordion title="How matching works">
  * URLs match after lowercasing the scheme and host, dropping a default port (`:443` or `:80`), and ignoring a trailing slash. A different path, subdomain, or port is a different server, so the token isn't sent there.
  * The token is sent as `Authorization: Bearer <token>` by default. If the credential sets `secret_name` (API only), the token is sent as-is in a header with that name instead, for servers that read a header such as `X-Api-Key`.
  * If two granted vaults hold a token for the same server, the vault listed first in the session's grants wins.
  * If no token matches, the session connects without one. That works for public servers and fails for servers that need authorization.
</Accordion>

## Test a server before you use it

`probeMcpServer` makes one live connection using the same URL matching and vault lookup as a session. It creates and changes nothing, but it needs the Developer or Admin role, like creating resources. See [Organizations and roles](/recursion/organizations-and-roles). Omit `vault_ids` to test without a token.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Credential vaults** and open the vault.
    2. Expand the server's **Token for an MCP server** row. It shows whether the server is reachable and how many tools it offers.
    3. Click **Test again** to run a new test.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/mcp/probe' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{
        "server_url": "https://mcp.example.com/mcp",
        "vault_ids": ["26d4b1a8-73c9-4f60-8a15-9e2c7b5d4f31"]
      }'
    ```
  </Tab>
</Tabs>

```json theme={"theme":"css-variables"}
{
  "ok": true,
  "reachable": true,
  "credential_matched": true,
  "deployment_authorized": false,
  "protocol_version": "2025-06-18",
  "server_name": "project-tracker",
  "tools": [
    { "name": "list_issues", "description": "List issues and their current status." }
  ]
}
```

A failed test still returns `200`. Read the body:

| Result | Meaning |
| - | - |
| `ok: true` | The server works with this token. |
| `ok: false`, `reachable: true`, no `protocol_version` | The server refused the token with `401` or `403`. It may be wrong or expired; check or rotate it. |
| `ok: false`, `reachable: true`, `protocol_version` set | The connection worked, but listing tools failed. Read `error`. |
| `ok: false`, `reachable: false`, `credential_matched: true` | A token was sent, and the server couldn't be reached or failed. Read `error`. |
| `ok: false`, `credential_matched: false` | No token was sent. Check the credential's server URL and the vaults you named. |

**What success means:** a passing test proves the server is reachable and that the token lets you list tools. It doesn't prove that every tool call will succeed; permissions, arguments, and the server's own state still matter.

<Accordion title="Every test response field">
  | Field | Meaning |
  | - | - |
  | `ok` | The server completed the handshake and returned its tool list. |
  | `reachable` | The server answered. Either the handshake succeeded, even if listing tools then failed, or the server refused the token with `401` or `403`; in that case `protocol_version` is absent. |
  | `credential_matched` | A token from the named vaults was attached. `false` means the test ran without a token. |
  | `credential_unopenable` | A token matched the URL but couldn't be used, so none was sent. `material_missing` means the credential has no stored value; re-enter it. `external_reference` means its value is held outside Recursion; re-enter it as a value. |
  | `deployment_authorized` | Always `false` for servers you add in Recursion. You can ignore it. |
  | `server_name` | What the server called itself. Use it to confirm you reached the right service. |
  | `protocol_version` | The Model Context Protocol version the test used. |
  | `tools` | The tools offered on this attempt, as the agent would see them before the name prefix. |
  | `error` | Why the test failed. Never contains the token. |

  A test gives up after 15 seconds. A server on a private, loopback, or link-local address is refused before anything is sent, so the test returns `reachable: false` with the reason in `error`.
</Accordion>

## How a session uses an MCP server

```mermaid theme={"theme":"css-variables"}
---
config:
  sequence:
    width: 110
    actorMargin: 40
---
sequenceDiagram
  participant S as Session
  participant M as MCP server
  participant A as Agent
  S->>M: Connect with token
  M-->>S: Tools
  S->>A: Offer tools
  A->>M: Call a tool
  M-->>A: Result
```

1. When a session starts, it reads the MCP servers on its agent version.
2. For each server, it looks for a **Token for an MCP server** in the session's granted vaults whose server URL matches.
3. It connects, lists the server's tools, and fixes that list and the tool schemas for the whole session.
4. The agent calls a tool as `<server name>__<tool name>`. The token is attached to every call outside the sandbox.

Tools, prompts, and resources: sessions use the server's tools. Text and images that a tool returns are passed to the agent. Server prompts and standalone resources aren't offered, and resource links in a result aren't fetched.

## Choose which tools an agent gets

A session receives every tool the server lists for its token. You can't hide individual tools of a server. To limit what an agent can do, give it a token whose scopes allow only what it needs, or point it at a server that offers fewer tools.

## What happens when a server fails

* **At session start:** an unreachable server or rejected token doesn't stop the session. Other servers still load, and the session's events record a warning naming the servers: `mcp_auth_rejected` when a server refused the token, and `mcp_discovery_failed` for any other failure. Fix the token, or the URL or server, then start a new session. Running sessions don't rediscover tools.
* **During a call:** each request to the server has a 60-second timeout, and a response can be at most 8 MiB. A failed call returns an error to the agent as the tool result, and the agent can decide what to do next.

## What can go wrong

The most common problems:

* **A session has an `mcp_auth_rejected` warning.** The server refused the token with `401` or `403`. Check or rotate the token in the vault, then start a new session.
* **A session has an `mcp_discovery_failed` warning.** The server was unreachable, failed the handshake, or is on a private address. Run a test with the same URL and vault, fix the cause, and start a new session.
* **Unexpected `vault-...` tools appear.** A granted vault holds a token for an MCP server the agent doesn't list. Remove the credential from the session's grants, or add the server to the agent with a name you choose.

<Accordion title="Every MCP server problem">
  | Symptom or code | Cause | Fix |
  | - | - | - |
  | `400 invalid_request` on `server_url` | The URL is missing, isn't `http` or `https`, has no host, or includes a user name or password. | Use the server's full endpoint URL, and put the token in a vault. |
  | `404 not_found` from a test | A vault in `vault_ids` doesn't exist in your organization. | Check the vault id. |
  | `403 forbidden` from a test | Your role doesn't have the create permission, which a test needs. | See [Organizations and roles](/recursion/organizations-and-roles). Use an account or key with the developer or admin role. |
  | A session has an `mcp_auth_rejected` warning | The server refused the token with `401` or `403`. | Check or rotate the token in the vault, then start a new session. |
  | A session has an `mcp_discovery_failed` warning | The server was unreachable, failed the handshake, or is on a private address. | Run a test with the same URL and vault, fix the cause, and start a new session. |
  | The server's tools are missing without a warning | The server isn't on the agent version the session used, or the session started before you saved it. | Check the session's agent version and start a new session. |
  | Unexpected `vault-...` tools appear | A granted vault holds a token for an MCP server the agent doesn't list. | Remove the credential from the session's grants, or add the server to the agent with a name you choose. |
  | Tools worked yesterday and now fail with 401 | A short-lived access token expired. | Rotate the credential. |
  | A tool call times out | The server took longer than 60 seconds. | Make the tool faster, or have it return a job id the agent can check later. |
</Accordion>

For all error codes, see [Errors](/recursion/errors). For limits, see [Limits](/recursion/limits).

## Next steps

<CardGroup cols={2}>
  <Card title="Vaults and credentials" href="/recursion/vaults">
    Store tokens for MCP servers and control which sessions receive them.
  </Card>

  <Card title="Agents" href="/recursion/agents">
    Publish a new agent version with its MCP servers attached.
  </Card>

  <Card title="Tools" href="/recursion/tools">
    See the built-in tools every session can use.
  </Card>

  <Card title="Events" href="/recursion/events">
    Read discovery warnings and MCP tool calls in the session timeline.
  </Card>
</CardGroup>
