> ## Documentation Index
> Fetch the complete documentation index at: https://phidatainc-studio-tools-doc.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect MCP servers

> Plug any MCP server into Scout as a context provider.

Anything with an [MCP server](https://modelcontextprotocol.io) plugs into Scout: Linear, GitHub, Notion, Postgres, Stripe, internal tools. Each server becomes one `MCPContextProvider`, exposes a `query_mcp_<slug>` tool on Scout, and runs behind a dedicated sub-agent so tool-name collisions across servers stay isolated.

The full reference, including transport details and the Node-in-Docker gotcha, lives in the Scout repo: [MCP\_CONNECT.md](https://github.com/agno-agi/scout/blob/main/docs/MCP_CONNECT.md).

## Wire up a server

Add an `MCPContextProvider` entry to `_create_mcp_providers()` in [`scout/contexts.py`](https://github.com/agno-agi/scout/blob/main/scout/contexts.py). Secrets come from the process env via `getenv(...)`.

<Tabs>
  <Tab title="stdio (local subprocess)">
    ```python theme={null}
    MCPContextProvider(
        server_name="linear",
        transport="stdio",
        command="npx",
        args=["-y", "@linear/mcp"],
        env={"LINEAR_API_KEY": getenv("LINEAR_API_KEY", "")},
        model=default_model(),
    )
    ```
  </Tab>

  <Tab title="streamable-http">
    ```python theme={null}
    MCPContextProvider(
        server_name="github",
        transport="streamable-http",
        url="https://mcp.github.com/mcp",
        headers={"Authorization": f"Bearer {getenv('GITHUB_TOKEN', '')}"},
        model=default_model(),
    )
    ```
  </Tab>

  <Tab title="sse">
    ```python theme={null}
    MCPContextProvider(
        server_name="notion",
        transport="sse",
        url="https://mcp.notion.so/sse",
        model=default_model(),
    )
    ```
  </Tab>
</Tabs>

Add the secret to `.env`, restart Scout, and the new tool shows up:

```bash theme={null}
curl -sS http://localhost:8000/contexts | jq '.[] | select(.id | startswith("mcp_"))'
# { "id": "mcp_linear", "name": "linear", "ok": true, "detail": "mcp: linear (12 tools)" }
```

## Constructor parameters

| Parameter         | Required for                    | Description                                                                         |
| ----------------- | ------------------------------- | ----------------------------------------------------------------------------------- |
| `server_name`     | all                             | Derives `id=mcp_<server_name>` and tool name `query_mcp_<server_name>`.             |
| `transport`       | all                             | One of `"stdio"`, `"sse"`, `"streamable-http"`.                                     |
| `command`         | stdio                           | Executable on `PATH` (`npx`, `uvx`, `python`, ...).                                 |
| `args`            | stdio (optional)                | CLI args as `list[str]`.                                                            |
| `env`             | stdio (optional)                | Env vars passed to the child process.                                               |
| `url`             | sse, streamable-http            | Server URL.                                                                         |
| `headers`         | sse, streamable-http (optional) | HTTP headers.                                                                       |
| `timeout_seconds` | optional                        | Bounds initial connect and each MCP read. Default 30.                               |
| `mode`            | optional                        | `ContextMode.default` (sub-agent wrap) or `ContextMode.tools` (flatten onto Scout). |

## When to pick `mode=tools` vs `mode=default`

| Mode      | What happens                                                           | Right when                                                                                                               |
| --------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `default` | Scout → sub-agent → MCP. Two extra LLM hops, full namespace isolation. | The server has many tools, cryptic names, or names that collide with another MCP server (e.g. `search`, `create_issue`). |
| `tools`   | Server's tools surface directly on Scout. No extra hops.               | The server has few, distinctively-named tools (e.g. `get_current_time`). Scout can route without help.                   |

`asetup()` connects on startup regardless of mode. That's required for `tools` mode to discover the server's functions, and it keeps the MCP SDK's anyio cancel scope on the same task that `aclose()` will exit on.

## Node-based servers in Docker

`command` must be on `PATH` inside Scout's runtime. The ship image bundles Python (`uv`, `uvx`, `python`), so Python MCP servers like `uvx --from mcp-server-time mcp-server-time` work out of the box. **Node-based servers (`npx @something/mcp`) need Node installed in your deploy image.** Add `RUN apt-get install -y nodejs npm` to the `Dockerfile` before shipping.

## Build your own provider

If your source isn't covered by an MCP server, write a `ContextProvider` directly. Four methods: `status`, `astatus`, `query`, `aquery`. Override `aupdate` if the source supports writes.

The [`agno.context.web.provider`](https://github.com/agno-agi/agno/blob/main/libs/agno/agno/context/web/provider.py) module is a complete reference implementation.

## Troubleshooting

| Symptom                                          | Likely cause                                                                                                                                                                    |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `/contexts/mcp_<slug>/status` returns `ok=false` | Server unreachable, or `initialize()` errored. For stdio: check `command` is on `PATH` inside the container. For HTTP: curl the URL to confirm it's live and your headers auth. |
| Tool calls fail but status is OK                 | The server declared a tool it doesn't actually implement. Check `MCPContextProvider` logs.                                                                                      |
| Tool list looks stale                            | Cached at connect time. Restart Scout to re-discover.                                                                                                                           |

For more, see [MCP\_CONNECT.md](https://github.com/agno-agi/scout/blob/main/docs/MCP_CONNECT.md).

## Next

[Deploy Scout to Railway →](/tutorials/scout/deploy-to-railway)
