架构总览:从配置到可用工具
两种 MCP 模式:内置 vs 外部
Claude Code 的 MCP 实现区分 内置 MCP 服务器 和 外部 MCP 服务器。两者使用相同的客户端协议和工具发现机制,但在连接方式、生命周期管理和配置来源上完全不同。内置 MCP 服务器
内置 MCP 服务器由 Claude Code 自身提供,无需用户手动配置。它们在启动时自动注册为dynamic scope 的配置,并在同进程内运行。
InProcessTransport:零开销同进程通信
内置服务器通过InProcessTransport(src/services/mcp/InProcessTransport.ts)运行,不启动子进程:
InProcessTransport 的核心设计:
send()通过queueMicrotask()异步投递消息到对端,避免同步请求/响应的栈深度问题close()双向关闭,任一端关闭都会触发两端的onclose回调- 无网络开销、无 IPC 序列化、无进程启动时间
动态注册流程
内置服务器在main.tsx 的启动流程中注册,注入 dynamicMcpConfig:
setupComputerUseMCP() 返回的配置(src/utils/computerUse/setup.ts):
连接时拦截
connectToServer() 在 client.ts:906-944 中根据服务器名拦截内置服务器:
保留名称保护
内置服务器的名称被保留,用户无法手动添加同名配置(config.ts:636-648):
main.tsx:2351-2368):如果用户配置中包含保留名(非 type:'sdk'),直接 process.exit(1)。
VSCode SDK MCP
VSCode SDK MCP 是特殊的内置模式。IDE(如 VS Code、JetBrains)通过嵌入方式启动 Claude Code,并传入type:'sdk' 的 MCP 配置。这类配置:
- 不经过保留名称检查(IDE 可以使用任意名称)
- 不参与 enterprise MCP 的排他控制
- 通过 VSCode SDK transport 连接
- 支持双向通知(如
file_updated、experiment_gates)
外部 MCP 服务器
外部 MCP 服务器由用户在配置文件中声明,通过子进程或网络连接运行。配置来源
配置示例
配置合并与去重
getAllMcpConfigs()(config.ts)按优先级合并多个来源的配置:
- 企业管控配置存在时,独占返回(忽略所有其他来源)
- 否则合并:user → project → local → plugin → claude.ai
- 插件与手动配置去重:通过
getMcpServerSignature()生成内容签名(基于 command/args/url),插件配置被同名手动配置抑制 addScopeToServers()为每个配置项标注来源 scope
7 种传输层实现
connectToServer()(client.ts:596-1643)根据 config.type 分发到不同的 Transport 实现:
stdio 传输的进程管理
stdio 类型的 MCP 服务器作为子进程运行,cleanup 时采用 信号升级策略(client.ts:1431-1564):
远程传输的认证状态机
SSE/HTTP 类型使用ClaudeAuthProvider 实现 OAuth 认证流程。认证失败时进入 needs-auth 状态,并写入 15 分钟 TTL 的缓存文件(mcp-needs-auth-cache.json),避免重复弹出认证提示。
连接缓存与重连机制
connectToServer 使用 lodash memoize 缓存连接对象,缓存 key 为 ${name}-${JSON.stringify(config)}。
缓存失效触发
当连接关闭时(client.onclose),清除所有相关缓存(client.ts:1376-1404):
连接降级检测
远程传输有 连续错误计数器(client.ts:1229):
请求级超时保护
每个 HTTP 请求使用独立的setTimeout 超时(wrapFetchWithTimeout,client.ts:493),而非共享 AbortSignal.timeout()。原因是 Bun 对 AbortSignal.timeout 的 GC 是惰性的——每个请求约 2.4KB 原生内存,即使请求毫秒级完成也要等 60s 才回收。
工具发现:从 MCP 到 Tool 接口
fetchToolsForClient()(client.ts:1744-2000)使用 memoizeWithLRU 缓存(上限 100),将 MCP 工具转换为 Claude Code 的统一 Tool 接口:
内置 MCP 的工具发现
内置 MCP 服务器虽然使用 InProcessTransport,但工具发现流程与外部服务器完全一致:- Computer Use:
createComputerUseMcpServerForCli()在src/utils/computerUse/mcpServer.ts中构建 MCP Server 对象,注册ListToolsRequestSchemahandler。工具描述包含平台特定的已安装应用列表(1s 超时枚举)。 - Claude in Chrome:
createClaudeForChromeMcpServer()在@ant/claude-for-chrome-mcp包中构建 Server,提供 17+ 个浏览器控制工具。 - VSCode SDK:由 IDE 端提供工具列表,通过 SDK transport 传递。
工具描述截断
MCP 工具描述上限 2048 字符(MAX_MCP_DESCRIPTION_LENGTH)。OpenAPI 生成的 MCP 服务器曾观察到 15-60KB 的描述文档。
工具能力标注
每个 MCP 工具根据tool.annotations 自动标注:
MCP 工具的权限检查
MCP 工具默认返回{ behavior: 'passthrough' }(client.ts:1816-1834),意味着它们始终进入权限确认流程。工具名使用 mcp__ 前缀精确匹配权限规则。
内置 MCP 服务器的工具通过 allowedTools 列表自动授权——在 main.tsx 启动时加入,绕过普通权限提示。例如 Computer Use 工具的 request_access 自行处理会话级审批。
MCP 工具的执行链路
Session 过期自动重试
HTTP 传输的 MCP session 可能过期。检测到McpSessionExpiredError 后自动重试一次(client.ts:1862),因为 ensureConnectedClient() 已经清除了缓存并建立了新连接。
内容截断与持久化
大型 MCP 工具输出通过truncateMcpContentIfNeeded 截断,二进制内容(图片)通过 persistBinaryContent 写入文件并返回文件路径。图片自动 resize(maybeResizeAndDownsampleImageBuffer)。