Browse documentation

Technical documentation / Reference

MCP stdio and HTTP tools

Feature docs index · Repository README

Configure Model Context Protocol (MCP) servers so their tools appear beside magi-code's built-ins. You can diagnose setup without provider credentials.

Supported transports:

Configuration and approval

Server definitions use the Claude-style .mcp.json convention, not a universal MCP specification. magi-code loads CONFIG_DIR/.mcp.json, then cwd/.mcp.json; CONFIG_DIR is the resolved MC_HOME (default ~/.magi-code). It does not search parent directories. A project server replaces the entire global definition with the same name, not individual fields.

Example .mcp.json:

{
  "mcpServers": {
    "filesystem": {
      "command": "node",
      "args": ["${MCP_SERVER_DIR}/server.js"],
      "env": { "MCP_ROOT": "${MCP_ROOT:-/tmp/mcp-root}" }
    },
    "remote_search": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": {
        "Authorization": "Bearer ${MCP_REMOTE_SEARCH_TOKEN}",
        "X-Team": "platform"
      },
      "timeout": 30
    },
    "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"
      }
    }
  }
}

All servers are disabled until approved. An enabled field in .mcp.json cannot grant approval. In Mission Control, /mcp lists discovered definitions; Up/Down selects, Enter toggles approval, and Esc closes. Changes apply on the next launch, not immediately or after /new.

Approvals are booleans in global settings.json at capabilities.mcp_approvals[canonical_source_path][name]:

{
  "capabilities": {
    "mcp_approvals": {
      "/absolute/path/to/project/.mcp.json": { "filesystem": true }
    }
  }
}

Only global settings can approve servers. Project settings cannot approve themselves, and a global definition's approval does not approve a same-name project replacement. Moving a definition to another canonical source path requires approval there.

Approval is tied only to the canonical source path and server name, not a definition fingerprint. Editing a definition at the same path and name retains approval; review those edits before the next launch.

FieldBehavior
typestdio (also the default when omitted) or http.
command / args / envStdio only. Command is spawned directly. The child starts with PATH plus the Windows startup baseline, then receives the explicit env overlay.
urlHTTP only. HTTPS required except explicit loopback HTTP (localhost, 127.0.0.0/8, or [::1]). URL credentials and redirects are rejected.
headersHTTP only. Values support environment expansion. Static Authorization / Proxy-Authorization are mutually exclusive with oauth.
oauth.client_idOptional public client id. If omitted, dynamic client registration is used when advertised.
oauth.scopesOptional requested scopes.
oauth.authorization_serverOptional authorization-server override.
timeoutOptional seconds per request; defaults to 30, max 300.

Discovery parses every definition's structural fields, including server names, transport types, required fields, and JSON value types. Structural errors can block loading even for disabled servers. Only enabled entries expand environment references and validate runtime fields such as commands, URLs, headers, and timeouts. Missing environment variables in disabled entries do not block loading. Enabling through /mcp expands and validates the selected definition before saving approval; failure leaves the saved approval unchanged.

For enabled entries, ${VAR} and ${VAR:-default} expand once while loading command, each argument, environment values, URL, and header values. A missing variable without a default fails configuration loading. Defaults apply to unset variables; an empty variable stays empty. Expansion is not recursive or shell evaluation. Use environment references rather than storing secrets in .mcp.json.

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.

Calls to the same server can overlap, including calls from parallel subagents. Request IDs correlate replies; connection shutdown remains exclusive. Canceling or timing out an admitted request closes the shared connection and fails pending siblings, so later calls need a new connection. A call canceled before admission does not close it. In-flight blocking HTTP POSTs still run until completion or their timeout. OAuth token acquisition/refresh is serialized within the shared provider; tool POSTs are not.

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

OAuth HTTP authentication

OAuth is explicit and interactive:

magi-code mcp login my_oauth_server
magi-code mcp logout my_oauth_server
magi-code mcp list

Behavior:

Token storage:

Security and limits:

Tool names

Discovered MCP tools are namespaced as:

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 the resolved configuration directory, global settings approvals, and both .mcp.json sources. They do not attach/create sessions or require provider auth.

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.

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; detaching a non-cooperative worker does not guarantee that it will have no side effects.

Supported MCP surface

Supported now:

Not supported yet:


Back to feature docs · Back to repository README

Edit this page on GitHub ↗