# MCP stdio and HTTP tools
[Feature docs index](README.md) · [Repository README](../../README.md)
## Purpose
Configure Model Context Protocol (MCP) tool servers so their tools appear beside built-in magi-code tools, then diagnose setup without provider credentials.
Supported transports:
- `stdio`: local child process MCP servers.
- `http`: MCP Streamable HTTP endpoints using POST/GET/DELETE.
## Settings
MCP servers live in non-secret `~/.magi-code/settings.json` under `capabilities.mcp`.
Stdio server:
```json
{
"capabilities": { "mcp": {
"filesystem": {
"type": "stdio",
"command": "node",
"args": ["/path/to/server.js"],
"env": { "MCP_ROOT": "/tmp/mcp-root" },
"enabled": true,
"timeout": 30
}
}
} }
```
HTTP server with static headers:
```json
{
"capabilities": { "mcp": {
"remote_search": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "{env:MCP_REMOTE_SEARCH_TOKEN}",
"X-Team": "platform"
},
"enabled": true,
"timeout": 30
},
"local_dev": {
"type": "http",
"url": "http://localhost:8787/mcp",
"headers": {},
"enabled": true,
"timeout": 15
}
} } }
```
HTTP server with OAuth:
```json
{
"capabilities": { "mcp": {
"my_oauth_server": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"oauth": {
"client_id": "your-client-id",
"scopes": ["read", "tools"],
"authorization_server": "https://auth.example.com"
},
"enabled": true,
"timeout": 30
}
}
} }
```
Fields:
| Field | Behavior |
| --- | --- |
| `type` | `stdio` or `http`. |
| `command` / `args` / `env` | Stdio only. Command is spawned directly. The child starts with `PATH` plus the Windows startup baseline, then receives the explicit configured `env` overlay; configured values are non-secret. |
| `url` | HTTP only. Must be `https://...`, except explicit loopback HTTP (`localhost`, `127.0.0.0/8`, or `[::1]`) for local development. URL credentials are rejected. Redirects are never followed. |
| `headers` | HTTP only. Static headers. Sensitive headers must use `{env:VAR_NAME}`. Mutually exclusive with `oauth` for `Authorization` / `Proxy-Authorization`. |
| `oauth.client_id` | HTTP OAuth only. Optional public client id. If omitted, dynamic client registration is used when the server advertises it. |
| `oauth.scopes` | HTTP OAuth only. Optional requested scopes. |
| `oauth.authorization_server` | HTTP OAuth only. Optional authorization-server override. |
| `enabled` | Optional; defaults to `true`. Disabled servers are skipped. |
| `timeout` | Optional seconds per request; defaults to `30`, max `300`. |
HTTP `timeout` bounds each request. Cancellation is checked before and around an HTTP request, but an in-flight blocking POST/body cannot be interrupted; `notifications/initialized` uses the same path. Stdio and pending-response waits remain cancellation-responsive.
Server and tool name components must each be non-empty and use only ASCII letters, digits, `_`, or `-`; neither component may contain `__`. A server id may not end with `_`, but a tool name may end with `_`. Qualified names use exactly `mcp__<server>__<tool>` and are limited to 64 bytes total. These restrictions keep the server/tool separator unambiguous.
## HTTP security rules
- `settings.json` is non-secret. Do not put bearer tokens, API keys, OAuth tokens, or passwords in it.
- Remote MCP and OAuth endpoints must use HTTPS. HTTP is accepted only for explicit loopback hosts: `localhost`, `127.0.0.0/8`, and `[::1]`.
- URL userinfo is rejected. Query and fragment data are accepted for endpoint configuration but stripped from metadata/discovery URLs and diagnostics.
- MCP POST, GET/SSE, DELETE, OAuth discovery, registration, and token clients disable redirects. A redirect fails before credentials can reach another origin or downgrade to HTTP.
- Sensitive HTTP headers must use `{env:VAR_NAME}`. Sensitive names are `Authorization`, `Proxy-Authorization`, and any header name containing `token`, `secret`, or `api-key` case-insensitively.
- Non-sensitive headers may use literal values, for example `"X-Team": "platform"`.
- All HTTP header values are redacted in debug output, errors, manager status, CLI diagnostics, sessions, and provider-visible paths.
- Diagnostics display sanitized URLs only: scheme, host, port, and path. Query strings, fragments, and URL credentials are not printed.
- HTTP error bodies are bounded before display.
- Provider auth variables are never copied into MCP HTTP headers automatically.
## OAuth HTTP authentication
OAuth is explicit and interactive:
```sh
magi-code mcp login my_oauth_server
magi-code mcp logout my_oauth_server
magi-code mcp list
```
Behavior:
- `mcp login <server>` discovers OAuth metadata, uses Authorization Code + PKCE S256, binds its callback to localhost only, and stores the resulting tokens locally.
- `mcp logout <server>` deletes the local token file only; it does not revoke remote tokens.
- `mcp list` shows OAuth status: authenticated, not authenticated, expired, refreshable, or invalid.
- Normal agent runs never open a browser. If auth is missing or expired without refresh, diagnostics tell you to run `magi-code mcp login <server>`.
Token storage:
- Tokens live under `$MC_HOME/mcp-tokens/<server>.json`.
- Token files are written with `0600` permissions on Unix.
- Tokens never belong in `settings.json`.
- Tokens, client secrets, authorization codes, PKCE verifier/state values, and bearer headers are redacted from logs, errors, Debug output, CLI diagnostics, sessions, and provider-visible tool output.
Security and limits:
- OAuth is mutually exclusive with static `Authorization` and `Proxy-Authorization` headers for the same server.
- PKCE S256 is used for all login flows.
- The callback listener binds localhost only.
- Client Credentials and Device Code grants are not supported.
- Login is an explicit CLI command, not automatic during agent/tool execution.
## Tool names
Discovered MCP tools are namespaced as:
```text
mcp__<server>__<tool>
```
Example: server `filesystem` tool `read_file` becomes `mcp__filesystem__read_file`. Qualified names must be exactly `mcp__<server>__<tool>` and no more than 64 bytes total (UTF-8; current safe components are ASCII). Both components must be non-empty and use only ASCII letters/digits/`_`/`-`; neither may contain `__`. Only server names cannot end with `_`; tool names may end with `_`. These restrictions keep the server/tool separator unambiguous.
## Diagnostics
Diagnostics read `MC_HOME` and `settings.json`, do not attach/create sessions, and do not require provider auth.
```sh
magi-code mcp list
```
Prints configured servers, type, enabled/disabled state, OAuth auth status when configured, and connection result. Enabled servers are started long enough to run initialize and `tools/list`; failures are reported with phase diagnostics on stderr. HTTP servers are shown as `http <sanitized-url>`. The command exits `0` if the list command itself ran, even when individual servers fail.
```sh
magi-code mcp test remote_search
```
Starts only the selected server, runs initialize and `tools/list`, prints server name/version/protocol plus discovered tool names/descriptions, then shuts down. For HTTP servers, shutdown sends best-effort session `DELETE` when the server issued an MCP session id. It exits non-zero for missing, disabled, spawn/connect, initialize, or list failures.
### Startup policy by interface
`magi-code mcp list` and `magi-code mcp test` diagnose servers without opening a conversation. List reports per-server failures without making unrelated servers unusable. Mission Control applies a stricter launch gate: every configured enabled MCP server must connect, initialize, and discover tools before a queued prompt can run. An execution-critical failure restores the terminal, exits nonzero, and never runs that queue. The strict path's first-success/second-canceled stdio cleanup is covered by tests; this interface-specific policy does not change the MCP transport or diagnostic contracts above.
Mission Control requests cancellation before cleanup. Critical/provider worker joins are bounded at 2 s each before detach/error, but an in-flight HTTP POST/body—including `notifications/initialized`—cannot observe cancellation. The 2 s critical join may detach the worker while it remains subject to that server's configured request timeout (30 s default, 300 s maximum). Terminal restoration happens first. Pre-request cancellation and stdio/pending-response paths remain responsive; a detached non-cooperative worker is not a no-side-effects guarantee.
## Supported MCP surface
Supported now:
- `stdio` transport.
- Streamable HTTP transport with POST JSON-RPC, optional GET SSE notifications, and DELETE session termination.
- `initialize`, `notifications/initialized`, `tools/list`, and `tools/call`.
- HTTP `Mcp-Session-Id` tracking and `MCP-Protocol-Version` headers after initialize.
- SSE parsing for Streamable HTTP responses.
Not supported yet:
- Client Credentials OAuth grant.
- Device Code OAuth grant.
- Legacy pre-2025-03-26 SSE transport.
- WebSocket transport.
- MCP resources, prompts, sampling, elicitation.
- Live `tools/list_changed` route refresh.
- magi-code-as-MCP-server mode.
## Related docs
- [PRD-0077: Mission Control Interactive Startup and Queued Prompts](../prd/0077-mission-control-interactive-startup-and-queued-prompts.md)
- [PRD-0066: MCP Stdio Tools Client Support](../prd/0066-mcp-stdio-tools-client-support.md)
- [PRD-0067: MCP Streamable HTTP Client Support](../prd/0067-mcp-streamable-http-client-support.md)
- [ADR-0045: MCP Stdio Client Tools](../adr/0045-mcp-stdio-client-tools.md)
- [PRD-0068: MCP OAuth HTTP Client Support](../prd/0068-mcp-oauth-http-client-support.md)
- [ADR-0046: MCP OAuth Token Authentication](../adr/0046-mcp-oauth-token-authentication.md)
- [Configuration](configuration.md)
- [Tools and safety model](tools-and-safety.md)
---
[Back to feature docs](README.md) · [Back to repository README](../../README.md)