# MCP Servers Pi connects to [Model Context Protocol](https://modelcontextprotocol.io) servers over stdio or streamable HTTP and makes their tools available to the model. ## Configure servers Add servers to `~/.pi/agent/mcp.json`, or to `.pi/mcp.json` in a project. The format matches other MCP clients, so existing `mcpServers` entries can be copied over: ```json { "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "."] }, "docs": { "url": "https://example.com/mcp", "headers": { "Authorization": "Bearer ${DOCS_TOKEN}" }, "exposure": "direct" } } } ``` - stdio servers take `command`, `args`, `env`, and `cwd`. Relative `cwd` resolves against the session directory. A leading `~/` in `command`, an argument, or `cwd` names the home directory. - HTTP servers take `url`, `headers`, and `oauth` (see [Sign in with OAuth](#sign-in-with-oauth)). The legacy SSE transport is not supported. - `env` and `headers` values can reference environment variables (`${NAME}`) or commands (`!command`), like provider API keys. - `timeout` sets the per-request timeout in seconds (default 60). Progress notifications from the server reset it. - `enabled: false` keeps an entry without connecting to it. Project entries replace global entries with the same name. A project `mcp.json` is only read after the project is trusted, because stdio servers run commands. `pi mcp add` and `pi mcp remove` edit the file from a shell (see [MCP commands](cli.md#mcp-commands)): ```bash pi mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem . pi mcp add docs --url https://example.com/mcp --bearer-token-env-var DOCS_TOKEN --exposure direct pi mcp add -l tools --env API_KEY='${TOOLS_KEY}' -- uvx tools-mcp pi mcp remove docs ``` Rules that are easy to get wrong: - Server names may only contain letters, digits, `_`, and `-`. Tools are named `mcp____`. - `type` is optional: a `command` makes a stdio server and a `url` a streamable HTTP server. When present, it must be `stdio`, `http`, or `streamable-http`. `sse` is rejected; most servers that document an SSE endpoint also serve streamable HTTP, often at `/mcp` instead of `/sse`. - `command` is a single executable and `args` its arguments, not one shell string. - Keep secrets out of the file: use `${NAME}` for environment variables, as in `"Authorization": "Bearer ${GITHUB_TOKEN}"`, or `!command` to run a command. A command must make up the whole value, so it has to print the header value itself: `"Authorization": "!echo Bearer $(gh auth token)"`. - Invalid entries are skipped and reported; the other servers still connect. ## Set up servers When asked to add an MCP server, the agent should: 1. Add simple servers with `pi mcp add` (add `-l` for the project file), or edit `mcp.json` directly for settings the command does not cover. Put personal servers and servers with credentials in `~/.pi/agent/mcp.json`. Use the project `.pi/mcp.json` only for servers the project itself needs, and only in trusted projects. 2. Convert entries written for other clients: - Claude Desktop, Claude Code, and Cursor use the same `mcpServers` shape; copy the entry. - VS Code uses a top-level `servers` object and `inputs` prompts; move the entry under `mcpServers` and replace `${input:...}` with `${NAME}` environment variables. - Codex uses TOML (`[mcp_servers.]` with `command`, `args`, `env`, or `url`); write the same fields as JSON. - opencode uses `"type": "local"` with `command` as an array (split it into `command` and `args`), `"type": "remote"` for URLs, `environment` for `env`, and `{env:NAME}` for `${NAME}`. 3. Run `pi mcp list` to check the entry. It connects to every enabled server and prints the state, the tools, and errors such as the stderr of a stdio server that failed to start. It exits with 1 while anything is wrong. 4. For a server that needs a sign-in, run `pi mcp login `. It opens the authorization page in the user's browser and waits until the user approves access; tell the user to approve it. A running session uses the new credentials on its next turn. 5. Tell the user to run `/reload` (or start a new session) so the running session connects to added or changed servers. Pi connects when a session starts. The first prompt waits up to 10 seconds for startup connections; the tools of servers that take longer become available once they connect. HTTP connections that fail with a network error or a transient status (408, 429, 5xx) are retried twice. A server that drops its connection shows as disconnected and is reconnected on the next call. When a server announces that its tool list changed, new tools are added and withdrawn tools become unreachable until the server offers them again. Config errors, servers that failed to connect, and servers that need a sign-in are reported once after startup. Log messages servers send with MCP logging notifications are appended to `~/.pi/agent/mcp.log` as `