C Claude Code Internals
| EN | ES

MCP(模型上下文协议)

MCP 将 Claude Code 连接到外部工具和服务。实现跨越 src/services/mcp/ 中的 23 个文件,支持 4 种传输类型、2 种认证流程、6 种配置范围和完整的企业策略系统。

4 传输类型 6 配置范围 23 实现文件 2 认证流程(OAuth + XAA)
i 工具命名约定
每个 MCP 工具暴露为 mcp__<server>__<tool>[a-zA-Z0-9_-] 之外的字符替换为 _, 最多 64 个字符。此前缀用于允许/拒绝权限规则。

架构

组件 文件 用途
Client client.ts (~3,400 lines) 连接、传输创建、工具包装、工具调用
Config config.ts (~800 lines) 从所有范围加载配置
Auth auth.ts (~1,200 lines) OAuth + XAA 认证流程
XAA xaa.ts (512 lines) 跨应用访问协议 (RFC 8693 + RFC 7523)
Normalization normalization.ts mcp__ 前缀的名称规范化
Env Expansion envExpansion.ts 配置中的 ${VAR} 和 ${VAR:-default} 展开
In-Process InProcessTransport.ts 进程内服务器的链接传输对(Chrome、Computer Use)
Elicitation elicitationHandler.ts MCP elicitation 请求处理器(基于 URL 的认证提示)
MCPTool src/tools/MCPTool/ 每个暴露给模型的 MCP 工具克隆的基础模板
McpAuthTool src/tools/McpAuthTool/ 需要认证的服务器的伪工具

配置范围(优先级顺序)

服务器从 6 个源加载。当名称冲突时,更高优先级覆盖更低优先级。 企业范围是排他的:如果 managed-mcp.json 存在, 所有其他范围都被忽略。

# 范围 来源 说明
1 claudeai API fetch Claude.ai 组织连接器(最低优先级)
2 plugin dynamic 来自已安装插件的服务器
3 user ~/.claude/settings.json 全局用户配置
4 project .mcp.json 向上遍历目录树到主目录
5 local .claude/settings.local.json 私有项目配置(不提交)
6 enterprise managed-mcp.json 排他性:此文件存在时忽略所有其他范围

项目配置示例(.mcp.json)

{
  "mcpServers": {
    "github": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }
    },
    "my-api": {
      "type": "sse",
      "url": "https://example.com/mcp/sse",
      "headers": { "Authorization": "Bearer ${API_TOKEN}" }
    }
  }
}

All config fields support ${VAR} and ${VAR:-default} expansion. Servers in .mcp.json require explicit user approval before connecting (stored in enabledMcpjsonServers in settings).

传输类型

stdio default

启动通过 stdin/stdout 通信的子进程。最常见的传输方式。type 字段可选以保持向后兼容性。

Stderr 用于调试(上限 64MB)。Chrome 和 Computer Use 服务器使用进程内优化以避免约 325MB 的子进程开销。

sse remote

长连接 EventSource 连接。流无超时;单个 HTTP 请求有 60 秒超时。

支持基于浏览器的 OAuth 流程。支持 headersHelper 脚本用于动态认证头。

http remote

实现 MCP 2025-03-26 Streamable HTTP 协议。自动添加 Accept: application/json, text/event-stream。

通过 session ID 支持会话管理。支持 OAuth 认证。

ws remote

WebSocket 传输。支持 Bun 和 Node.js 运行时。协议:["mcp"]。

支持代理和 TLS 选项。Headers 可配置。

连接生命周期

启动

1

Load configs from all scopes (enterprise takes exclusive control if present)

2

Deduplicate servers by signature (URL for remote, command for stdio)

3

Filter by enterprise allow/deny policies

4

Check project server approval status

5

Connect local servers (concurrency: 3) and remote servers (concurrency: 20) in parallel

6

On auth failure: cache 15 min, create McpAuthTool pseudo-tool

7

On success: fetch tools, commands, and resources in parallel

工具调用流程

1

Model outputs tool_use block with name "mcp__server__tool"

2

ensureConnectedClient() verifies or reconnects if cache was cleared

3

Permission check via standard permission system (passthrough by default)

4

callMCPTool() with timeout, checks isError flag in response

5

processMCPResult(): if output > 100,000 chars, saves to temp file and returns Read instructions

6

On URL elicitation error (-32042): retries up to 3 times

关闭

Stdio servers

SIGINT → 100ms → SIGTERM → 400ms → SIGKILL

Total failsafe: 600ms maximum

Remote servers

client.close() → closes transport, rejects pending requests

认证

OAuth standard flow SSE + HTTP

Browser-based OAuth with automatic token storage in the OS keychain, keyed by server name and config hash. Auto-refreshes on 401. Supports step-up (403 with scope) and revocation (RFC 7009).

"oauth": {
  "clientId": "my-app",
  "callbackPort": 8080,
  "authServerMetadataUrl": "https://auth.example.com/.well-known/..."
}
XAA (Cross-App Access) enterprise SSO

Enterprise SSO flow using RFC 8693 token exchange and RFC 7523 JWT Bearer grant. Enabled with CLAUDE_CODE_ENABLE_XAA=1. Key benefit: a single browser popup authenticates N MCP servers (cached id_token is reused).

Flow: PRM Discovery → AS Metadata → id_token → ID-JAG → access_token

McpAuthTool (pseudo-tool) needs-auth state

When a server fails to connect due to auth, a pseudo-tool named mcp__<server>__authenticate is created. When the model calls it, the OAuth flow starts, and upon completion the real tools replace the pseudo-tool. Always auto-approved (no user permission prompt). Auth failure is cached for 15 minutes.

工具暴露

命名示例

Server name Tool name Exposed as
github create_issue mcp__github__create_issue
slack search_public mcp__slack__search_public
My Server! do-thing mcp__My_Server___do_thing

工具注解(来自 MCP 规范)

Annotation Property Effect
readOnlyHint isConcurrencySafe, isReadOnly 工具可并行运行,视为只读
destructiveHint isDestructive 权限提示中的更高风险信号
openWorldHint isOpenWorld 工具可访问外部系统
_meta.anthropic/searchHint searchHint 工具被延迟(不加载到上下文直到搜索)
_meta.anthropic/alwaysLoad alwaysLoad 工具绕过延迟,始终在上下文中

Tool descriptions are capped at 2048 characters. When output exceeds 100,000 characters, it is saved to a temp file and the model receives instructions to use the Read tool.

权限系统

All MCP tools return checkPermissions() → passthrough. This means in default mode the user is always prompted, in bypassPermissions mode they are auto-approved, and in auto mode the YOLO classifier decides.

用户权限规则

{
  "permissions": {
    "allow": [
      "mcp__github__search_code",
      "mcp__slack__*"
    ],
    "deny": [
      "mcp__untrusted_server__*"
    ]
  }
}

企业服务器策略(managed-mcp.json)

{
  "allowedMcpServers": [
    { "serverName": "github" },
    { "serverUrl": "https://*.company.com/*" },
    { "serverCommand": ["npx", "-y", "@company/mcp-*"] }
  ],
  "deniedMcpServers": [
    { "serverName": "untrusted" }
  ]
}

Denylist always takes precedence over allowlist.

CLI 命令

# Add a stdio server (default scope: local)
claude mcp add my-server npx -y @org/mcp-server
  -s, --scope <scope>      # local, user, or project
  -e, --env KEY=VALUE      # environment variables

# Add a remote server (transport auto-detected from URL)
claude mcp add my-api https://api.example.com/mcp
  -t, --transport sse|http
  -H, --header "Key: Value"
  --client-id <id>         # OAuth client ID
  --xaa                    # Enable Cross-App Access

# Add with full JSON config
claude mcp add-json my-server '{"type":"http","url":"https://example.com/mcp"}'

# Other operations
claude mcp remove my-server [-s scope]
claude mcp list
claude mcp get my-server

/mcp 斜杠命令

Subcommand Description
/mcp 打开 MCP 设置 UI
/mcp enable [name|all] 启用服务器
/mcp disable [name|all] 禁用服务器
/mcp reconnect <name> 重新连接特定服务器(清除缓存,新连接)

高级功能

Headers helper script

Set headersHelper to a script path. The script receives the server name and URL as env vars and must output JSON headers. Runs with 10s timeout. Dynamic headers override static ones.

MCP resources

Servers can expose resources (files, data) via ListMcpResourcesTool and ReadMcpResourceTool. Both are deferred tools. Blob resources are base64-decoded and written to disk.

MCP prompts as commands

Server-exposed prompts become slash commands (mcp__server__prompt-name). Arguments are parsed from the prompt's argument schema and passed to client.getPrompt().

Agent-specific servers

Agents can reference existing servers by name (shared) or define inline servers (cleaned up when the agent finishes). Required servers are declared and must be configured.

Server instructions

Servers provide usage instructions during handshake (truncated at 2048 chars). Injected as a system prompt section each turn. Delta mode (feature-gated) avoids cache invalidation.

In-process transport

Chrome and Computer Use servers run in-process via InProcessTransport, avoiding ~325MB subprocess overhead. Uses linked transport pairs with queueMicrotask() delivery.

关键常量和超时

Variable / Constant Value Purpose
MCP_TIMEOUT 30,000ms 每个服务器的连接超时
MCP_TOOL_TIMEOUT 100,000,000ms (~27.8h) 工具调用超时(实际上无限)
MCP_REQUEST_TIMEOUT_MS 60,000ms 每个 HTTP 请求超时(SSE/HTTP)
MAX_MCP_OUTPUT_TOKENS 25,000 工具输出中的最大 token
maxResultSizeChars 100,000 chars 保存到文件前的输出大小上限
MAX_MCP_DESCRIPTION_LENGTH 2048 chars 工具描述上限
MCP_AUTH_CACHE_TTL_MS 15 min needs-auth 缓存持续时间
MCP_FETCH_CACHE_SIZE 20 工具/资源/命令的 LRU 缓存大小
local concurrency 3 同时本地(stdio)服务器连接
remote concurrency 20 同时远程服务器连接
MAX_ERRORS_BEFORE_RECONNECT 3 重新连接前的终端错误
MAX_URL_ELICITATION_RETRIES 3 URL elicitation (-32042) 重试

MCP_TIMEOUT, MCP_TOOL_TIMEOUT, and MAX_MCP_OUTPUT_TOKENS are in the SAFE_ENV_VARS set: they can be set via managed settings without triggering a security dialog.

错误处理

Error type Handling
连接超时(30s) 服务器标记为失败
认证错误(401) 缓存为 needs-auth 15 分钟,创建 McpAuthTool
ECONNRESET / ETIMEDOUT / EPIPE 计数:3 个连续错误关闭传输
ECONNREFUSED / EHOSTUNREACH 终端错误,立即关闭传输
会话过期(404 + -32001) 清除缓存,自动重试一次
URL elicitation (-32042) 向用户显示 URL 对话框,最多重试 3 次
大多数用户不知道的关于 MCP 的三件事
第一:.mcp.json 中的服务器在连接前需要明确批准 — 在设置中使用 enableAllProjectMcpServers: true 批量批准。 第二:你可以使用通配符权限规则如 mcp__slack__* 来允许整个服务器而无需批准每个工具。 第三:MCP 工具超时实际上是无限的(约 27.8 小时)— 如果工具似乎卡住了,使用 /mcp reconnect server-name 强制重新连接。