MCP 协议与客户端架构:插件化的统一语言
Model Context Protocol (MCP) 是 Claude Code 的工具扩展协议。它用 JSON-RPC 统一了工具调用、资源读取和交互反馈,让大型语言模型能与外部数据源和工具进行结构化交互。
从定义开始
MCP 协议本质上是 基于 JSON-RPC 的工具、资源与 Prompt 的分发协议(JSON-RPC Dispatch Protocol)。
它在 Claude Code 内部(Client)和外部扩展(Server)之间建立了一个双向、实时的通信管道。通过它,Claude 能够发现并调用各种“超能力”——无论是本地的 shell 脚本、通过 SSE 连接的远程服务,还是托管在 claude.ai 上的连接器。MCP 并不是简单的 API 调用,它将“工具定义”、“资源读取”和“交互式反馈”统一在了一套异步消息框架下。
代码里的真实逻辑
整个客户端架构围绕生命周期管理和消息路由展开,其核心逻辑落在了 src/services/mcp/client.ts。
多协议传输层 (Transports): Claude Code 支持多种连接方式,由不同的 Transport 类实现:
- Stdio Transport:通过 shell 派生子进程(如
node或python),利用标准输入输出进行通信。这是本地插件的主流方式。 - SSE (Server-Sent Events) Transport:用于连接远程托管的 MCP 服务,支持持久化连接和动态认证。
- In-process Transport:用于加载内建的高性能插件,减少进程间通信开销。
- WebSocket Transport (
src/utils/mcpWebSocketTransport.ts):提供了另一种远程连接选择。
- Stdio Transport:通过 shell 派生子进程(如
连接生命周期管理 (Session Management):
src/services/mcp/MCPConnectionManager.tsx负责维护所有活跃的 MCP 连接。它处理初始握手(Handshake),并负责在连接失败时触发重连逻辑,或在配置文件变动时热重启对应的 Server 进程。工具动态注入与规范化: 一旦连接建立,客户端会通过
list_tools获取 Server 提供的工具集。- 名称规范化 (Normalization):
src/services/mcp/normalization.ts通过normalizeNameForMCP()将 Server 名称统一为^[a-zA-Z0-9_-]{1,64}$格式,确保工具调用的路由前缀合法。 - 路由分发:当模型决定调用工具时,
mcp_call会根据工具名中的前缀(如github__)将请求精确路由到对应的 Client 句柄。
- 名称规范化 (Normalization):
资源面与采样机制: 除了主动执行的工具,架构中还包含
resources/list和resources/read。这允许模型通过 URI 寻址读取外部静态数据。
边界条件
- 物理进程隔离:Stdio 类型的 Server 运行在独立的子进程中。Server 的奔溃不会拖垮 Claude Code,但会导致对应的工具前缀瞬间从上下文消失。
- 配置与状态的分离:
.mcp.json只负责告诉 Claude “去哪里连”,而连接后的needs-auth、connected或error状态则是由MCPConnectionManager在内存中实时维护的。 - 版本降级:协议遵循语义化版本。如果 Client 与 Server 版本不匹配,系统会尝试回退到基础功能,但这可能导致某些高级特性(如 Tool Search)失效。
- 性能开销:远程 SSE 连接引入了网络延迟。Claude Code 内部通过大量的缓存机制(如
fetchResourcesForClient)来尽量减少重复的协议往返。
接下来看什么
- 如果你想了解如何配置和添加新的 MCP Server,请看 MCP 注册表与服务发现。
- 如果你关插件的权限控制,请看 MCP 安全与信任模型。
- 如果你面对的是需要 OAuth 登录的远程服务,请看 MCP 认证与 OAuth 流程。
源码锚点
claude-code-opensource/src/services/mcp/client.ts— 客户端核心逻辑与 JSON-RPC 实现。
📄 src/services/mcp/client.ts — 客户端核心逻辑与 JSON-RPC 实现。
type JSONRPCMessage,
type ListPromptsResult,
ListPromptsResultSchema,
ListResourcesResultSchema,
ListRootsRequestSchema,
type ListToolsResult,
ListToolsResultSchema,
McpError,
type PromptMessage,
type ResourceLink,
} from '@modelcontextprotocol/sdk/types.js'
import mapValues from 'lodash-es/mapValues.js'
import memoize from 'lodash-es/memoize.js'
import zipObject from 'lodash-es/zipObject.js'
import pMap from 'p-map'
import { getOriginalCwd, getSessionId } from '../../bootstrap/state.js'claude-code-opensource/src/services/mcp/MCPConnectionManager.tsx— 连接生命周期与热重载管理。
📄 src/services/mcp/MCPConnectionManager.tsx — 连接生命周期与热重载管理。
interface MCPConnectionContextValue {
reconnectMcpServer: (serverName: string) => Promise<{
client: MCPServerConnection;
tools: Tool[];
commands: Command[];
resources?: ServerResource[];
}>;
toggleMcpServer: (serverName: string) => Promise<void>;
}claude-code-opensource/src/services/mcp/normalization.ts— MCP Server 名称的格式规范化(normalizeNameForMCP)。
📄 src/services/mcp/normalization.ts — MCP Server 名称的格式规范化(`normalizeNameForMCP`)。
export function normalizeNameForMCP(name: string): string {
let normalized = name.replace(/[^a-zA-Z0-9_-]/g, '_')
if (name.startsWith(CLAUDEAI_SERVER_PREFIX)) {
normalized = normalized.replace(/_+/g, '_').replace(/^_|_$/g, '')
}
return normalized
}claude-code-opensource/src/services/mcp/InProcessTransport.ts— 内建插件的内存级通信实现。
📄 src/services/mcp/InProcessTransport.ts — 内建插件的内存级通信实现。
class InProcessTransport implements Transport {
private peer: InProcessTransport | undefined
private closed = false
onclose?: () => void
onerror?: (error: Error) => void
onmessage?: (message: JSONRPCMessage) => void
/** @internal */
_setPeer(peer: InProcessTransport): void {
this.peer = peer
}
async start(): Promise<void> {}
async send(message: JSONRPCMessage): Promise<void> {
if (this.closed) {
throw new Error('Transport is closed')
}
// Deliver to the other side asynchronously to avoid stack depth issues
// with synchronous request/response cycles
queueMicrotask(() => {
this.peer?.onmessage?.(message)
})
}
async close(): Promise<void> {
if (this.closed) {
return
}claude-code-opensource/src/utils/mcpWebSocketTransport.ts— WebSocket 传输层的封装。
📄 src/utils/mcpWebSocketTransport.ts — WebSocket 传输层的封装。
// WebSocket readyState constants (same for both native and ws)
const WS_CONNECTING = 0
const WS_OPEN = 1
// Minimal interface shared by globalThis.WebSocket and ws.WebSocket
type WebSocketLike = {
readonly readyState: number
close(): void
send(data: string): void
}�层的封装。