magi-code 0.63.0

Repository-aware CLI coding agent for terminal work
Documentation
# 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 `mcp_servers`.

Stdio server:

```json
{
  "mcp_servers": {
    "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
{
  "mcp_servers": {
    "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
{
  "mcp_servers": {
    "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; `env` is a non-secret child-process map. |
| `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`. |

Server ids must use ASCII letters, digits, `_`, or `-`, and cannot contain `__`.

## 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`. MCP tool names follow the same safe-name rules and cannot contain `__`.

## 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.

## 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-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)