Claude Code Wiki
首页 深入解析 工具系统

MCPTool:Model Context Protocol 深度集成

高级 工具系统

Claude Code 通过 MCPTool 实现了对 Model Context Protocol(MCP)的深度集成,使其能够连接外部 MCP 服务器并动态获取工具、资源和命令。这种架构将 Claude Code 从一个封闭的工具系统转变为一个开放的、可扩展的代理平台,允许用户通过配置文件集成任意第三方服务和能力,同时保持统一的权限模型和错误处理机制。

Sources: MCPTool.ts, client.ts

核心架构:从协议到工具的映射

MCPTool 采用动态适配器模式:基础 MCPTool 类只是一个模板,实际运行时会被 MCP 服务器的具体工具定义覆盖。这种设计允许 Claude Code 在启动时从连接的 MCP 服务器动态发现工具,并将它们转换为内部 Tool 接口,无需硬编码任何服务器特定的逻辑。

整个 MCP 集成系统分为三个核心层:连接管理层(负责建立和维护与 MCP 服务器的通信)、协议适配层(将 MCP 协议的对象模型转换为 Claude Code 的 Tool/Command/Resource 模型)、执行层(处理工具调用、资源读取和用户交互)。每一层都通过依赖注入和回调机制解耦,使得添加新的传输协议或认证方式无需修改核心逻辑。

Sources: MCPTool.ts, client.ts

架构层次与数据流

graph TB
    subgraph "应用层"
        A[QueryEngine] --> B[Tool Registry]
        B --> C{Tool Type?}
    end
    
    subgraph "MCP 适配层"
        C -->|MCP Tool| D[fetchToolsForClient]
        C -->|MCP Resource| E[fetchResourcesForClient]
        C -->|MCP Command| F[fetchCommandsForClient]
        
        D --> G[Tool Discovery]
        E --> H[Resource Discovery]
        F --> I[Prompt Discovery]
    end
    
    subgraph "连接管理层"
        G --> J[connectToServer]
        H --> J
        I --> J
        
        J --> K{Transport Type?}
        K -->|stdio| L[StdioClientTransport]
        K -->|sse| M[SSEClientTransport]
        K -->|http| N[StreamableHTTPClientTransport]
        K -->|ws| O[WebSocketTransport]
        K -->|sdk| P[SdkControlClientTransport]
    end
    
    subgraph "协议层"
        L --> Q[MCP SDK Client]
        M --> Q
        N --> Q
        O --> Q
        P --> Q
        
        Q --> R[tools/list]
        Q --> S[resources/list]
        Q --> T[prompts/list]
    end
    
    subgraph "外部服务"
        R --> U[MCP Server 1]
        S --> V[MCP Server 2]
        T --> W[MCP Server N]
    end
    
    style A fill:#e1f5ff
    style D fill:#fff4e6
    style J fill:#f3e5f5
    style Q fill:#e8f5e9

协议适配过程发生在 fetchToolsForClient 函数中:当 MCP 服务器通过 tools/list 请求返回工具列表时,每个工具定义(包含 name、description、inputSchema、annotations)被转换为一个完整的 Tool 对象。这个转换过程会保留 MCP 服务器的元数据(如 readOnlyHint、destructiveHint),同时注入 Claude Code 特定的功能(如权限检查、进度报告、结果截断)。关键的是,call 方法被覆盖为通过 MCP 客户端发送 tools/call 请求,并将结果转换回 Claude Code 的格式。

Sources: client.ts, types.ts

连接管理:多传输协议支持

Claude Code 支持五种传输协议连接 MCP 服务器,每种协议针对不同的部署场景优化:stdio 用于本地进程通信(最常见,适合命令行工具封装)、SSE 用于服务器推送事件(适合 Web 服务)、HTTP 用于可流式传输的 HTTP(适合 REST API)、WebSocket 用于双向实时通信(适合 IDE 集成)、SDK 用于进程内直接调用(适合插件系统)。所有传输层都实现了 MCP SDK 的 Transport 接口,确保协议层的统一性。

连接生命周期通过 connectToServer 函数管理,该函数使用记忆化缓存避免重复连接同一服务器。缓存键由服务器名称和配置对象生成,当配置变更时缓存自动失效。连接建立后会注册清理回调,确保进程退出时正确关闭所有 MCP 服务器(特别是 stdio 传输需要终止子进程)。连接超时默认 60 秒,可通过环境变量 MCP_CONNECTION_TIMEOUT_MS 调整。

Sources: client.ts, types.ts

传输协议对比

协议类型配置字段适用场景认证方式性能特征
stdiocommand, args, env本地 CLI 工具、脚本封装进程继承低延迟、高吞吐
SSEurl, headers, oauthWeb 服务、远程 APIOAuth 2.0、Bearer Token服务器推送、长连接
HTTPurl, headers, oauthREST API、微服务OAuth 2.0、自定义头部请求-响应、可流式
WebSocketurl, headersIDE 集成、实时协作Token、mTLS全双工、低延迟
SDKname进程内插件、扩展无需认证零网络开销

连接失败处理采用分层策略:首先捕获 MCP SDK 抛出的协议错误(如 McpError),然后将其转换为 TelemetrySafeError 以避免敏感信息泄露到遥测系统。对于 stdio 传输,还会捕获子进程的 stderr 输出并记录到调试日志,帮助诊断启动失败。连接成功后,会立即预取工具、资源和命令列表并缓存,减少后续调用的延迟。

Sources: client.ts, auth.ts

工具发现与动态注册

工具发现是 MCP 集成的核心功能,通过 fetchToolsForClient 函数实现。该函数首先检查服务器的 capabilities.tools 能力声明,如果支持则发送 tools/list 请求获取工具列表。每个 MCP 工具定义包含:name(工具标识符)、description(人类可读描述)、inputSchema(JSON Schema 格式的参数定义)、annotations(可选的元数据,如 readOnlyHintdestructiveHintopenWorldHint)。

转换过程会深度定制基础 MCPTool 的每个方法:name 字段使用 mcp__<server>__<tool> 格式避免冲突(可通过环境变量 CLAUDE_AGENT_SDK_MCP_NO_PREFIX 禁用前缀),descriptionprompt 直接使用 MCP 服务器的定义(超过 2000 字符会被截断),inputJSONSchema 直接传递 MCP 的 JSON Schema,checkPermissions 返回带有自动规则建议的 passthrough 行为。最关键的是 call 方法的覆盖:它通过 MCP 客户端发送 tools/call 请求,支持进度回调和 elicitation 重试。

Sources: client.ts, MCPTool.ts

工具调用流程

sequenceDiagram
    participant QE as QueryEngine
    participant Tool as MCPTool Instance
    participant Client as MCP Client
    participant Server as MCP Server
    
    QE->>Tool: call(args, context)
    Tool->>Tool: extractToolUseId(parentMessage)
    Tool->>Tool: emit progress(started)
    
    loop Session Retry (max 1)
        Tool->>Client: ensureConnectedClient()
        Client->>Client: check cache
        alt Cache miss/expired
            Client->>Server: reconnect via Transport
            Server-->>Client: connection ack
        end
        
        Tool->>Client: callMCPToolWithUrlElicitationRetry()
        Client->>Server: tools/call request
        
        alt Elicitation needed
            Server-->>Client: elicitation request
            Client->>QE: handleElicitation()
            QE->>QE: show dialog to user
            QE-->>Client: user response
            Client->>Server: elicitation response
        end
        
        Server-->>Client: tool result
        Client-->>Tool: mcpResult
        
        alt Session expired
            Tool->>Tool: clear cache, retry
        else Success
            Tool->>Tool: emit progress(completed)
            Tool-->>QE: {data, mcpMeta}
        end
    end

工具过滤机制通过 isIncludedMcpTool 函数实现,允许用户通过配置文件排除特定的 MCP 工具。过滤发生在工具注册阶段,不会影响 MCP 服务器本身。工具的 searchHint 字段从 MCP 工具的 _meta.anthropic/searchHint 元数据中提取,用于改进工具搜索的相关性排序。alwaysLoad 标记(来自 _meta.anthropic/alwaysLoad)会强制工具始终加载到上下文中,即使自动分类器认为它不相关。

Sources: client.ts, UI.tsx

资源管理:暴露外部数据源

MCP 资源允许服务器暴露可读的数据源(如文件系统、数据库、API 端点),Claude Code 通过 ListMcpResourcesToolReadMcpResourceTool 两个内置工具访问它们。资源发现通过 fetchResourcesForClient 函数实现,该函数发送 resources/list 请求获取资源列表,每个资源包含 uri(唯一标识符)、name(显示名称)、description(可选描述)、mimeType(可选 MIME 类型)。

ListMcpResourcesTool 接受可选的 server 参数过滤特定服务器的资源,返回所有匹配资源的元数据数组。ReadMcpResourceTool 则通过 serveruri 参数读取具体资源内容,支持文本和二进制数据。对于二进制资源(如图片、PDF),内容会被保存到临时文件,工具结果中返回文件路径而非原始数据,避免在上下文中占用大量 token。

Sources: ListMcpResourcesTool.ts, ReadMcpResourceTool.ts

资源读取与二进制处理

flowchart TD
    A[ReadMcpResourceTool.call] --> B{Resource Type?}
    
    B -->|Text| C[Return text content]
    C --> D[Direct inclusion in context]
    
    B -->|Binary| E[Read blob data]
    E --> F[Determine MIME type]
    F --> G{Size check}
    
    G -->|< 10MB| H[Save to tool-results directory]
    G -->|>= 10MB| I[Reject with error]
    
    H --> J[Generate file path]
    J --> K[Return path + metadata]
    K --> L[Claude uses FileReadTool]
    
    style A fill:#e1f5ff
    style E fill:#fff4e6
    style H fill:#e8f5e9

资源缓存策略使用 LRU 缓存(最多 20 个服务器),缓存键为服务器名称。当服务器断开连接时(触发 onclose 回调),缓存会被清除以确保重新连接后获取最新资源列表。资源工具本身也会被动态添加:如果没有任何 MCP 服务器提供资源工具,Claude Code 会自动添加 ListMcpResourcesToolReadMcpResourceTool 到工具注册表中。

Sources: client.ts, mcpOutputStorage.ts

命令集成:MCP Prompts 作为斜杠命令

MCP 服务器的 prompts 能力允许服务器提供预定义的提示模板,Claude Code 将它们转换为斜杠命令。转换过程在 fetchCommandsForClient 函数中实现:发送 prompts/list 请求获取提示列表,每个提示包含 name(命令标识符)、description(命令描述)、arguments(可选参数列表)。

转换后的命令名称格式为 /mcp__<server>__<prompt>,参数通过空格分隔传递。当用户执行命令时,getPromptForCommand 方法会被调用,它发送 prompts/get 请求到 MCP 服务器,传递提示名称和参数。服务器返回的 messages 数组(包含角色和内容)会被转换为 Claude Code 的消息格式并注入到对话上下文中。

Sources: client.ts, useManageMCPConnections.ts

命令生命周期

stateDiagram-v2
    [*] --> Discovery: prompts/list request
    Discovery --> Registration: Convert to Command
    Registration --> Registry: Add to command registry
    
    Registry --> Invocation: User types /mcp__server__prompt
    Invocation --> ParameterParsing: Parse arguments
    ParameterParsing --> ServerRequest: prompts/get request
    
    ServerRequest --> ResponseTransform: Receive messages
    ResponseTransform --> ContextInjection: Convert to MessageParam
    ContextInjection --> [*]: Messages in conversation
    
    note right of Discovery
        Cached by server name
        LRU size: 20 servers
    end note
    
    note right of ServerRequest
        Supports dynamic content
        Server can generate based on args
    end note

动态命令更新通过 MCP 的 notifications/prompts/list_changed 通知实现。当服务器提示列表变更时,Claude Code 会收到通知并重新获取命令列表,更新命令注册表。这种机制允许 MCP 服务器根据上下文动态调整可用命令,例如基于用户权限或当前项目状态显示不同的命令集。

Sources: useManageMCPConnections.ts, client.ts

认证与安全:OAuth 2.0 和跨应用访问

MCP 集成支持多种认证机制,最复杂的是 OAuth 2.0 授权码流程,通过 ClaudeAuthProvider 类实现。该类实现了 MCP SDK 的 OAuthClientProvider 接口,负责发现授权服务器元数据、启动浏览器授权流程、接收回调、交换令牌和自动刷新。令牌存储在 macOS Keychain 或加密的文件存储中,确保安全性。

跨应用访问 是一个高级特性,允许 MCP 服务器通过用户的企业身份提供商(IdP)访问其他应用程序。配置非常简单:只需在 MCP 服务器配置中设置 oauth.xaa: true,Claude Code 会自动处理 OIDC 登录、ID Token 获取和令牌交换。XAA 配置(IdP issuer、clientId)是全局的,存储在 settings 中,避免为每个服务器重复配置。

Sources: auth.ts, xaa.ts

OAuth 流程与令牌管理

sequenceDiagram
    participant Client as MCP Client
    participant Auth as ClaudeAuthProvider
    participant Storage as Secure Storage
    participant Browser as User Browser
    participant AS as Authorization Server
    
    Client->>Auth: tokens() - get cached tokens
    Auth->>Storage: read tokens
    Storage-->>Auth: null (first time)
    Auth-->>Client: null
    
    Client->>Auth: clientInformation() - discover
    Auth->>AS: GET /.well-known/oauth-authorization-server
    AS-->>Auth: {authorization_endpoint, token_endpoint}
    Auth-->>Client: client metadata
    
    Client->>Auth: authorize() - start flow
    Auth->>Auth: generate PKCE challenge
    Auth->>Browser: open authorization URL
    Browser->>AS: user login & consent
    AS-->>Browser: redirect to localhost
    Browser->>Auth: callback with auth code
    Auth->>AS: exchange code for tokens
    AS-->>Auth: {access_token, refresh_token}
    Auth->>Storage: save tokens
    Auth-->>Client: authorization complete
    
    Note over Client,AS: Later - token refresh
    
    Client->>Auth: tokens() - expired
    Auth->>Storage: read refresh_token
    Auth->>AS: refresh token request
    AS-->>Auth: new access_token
    Auth->>Storage: update tokens
    Auth-->>Client: fresh tokens

令牌刷新策略采用指数退避重试机制:当收到 401 错误时,AuthProvider 会尝试刷新令牌,最多重试 3 次,每次间隔加倍(1s、2s、4s)。刷新失败会触发 needs-auth 状态,提示用户重新授权。所有 OAuth 参数(state、code_verifier)都会被安全地清理,避免日志泄露敏感信息。

Sources: auth.ts, xaaIdpLogin.ts

Elicitation:服务器发起的用户交互

Elicitation 是 MCP 的一个独特能力,允许服务器在工具执行过程中请求用户输入或确认。这通过 ElicitRequestSchema 请求处理器实现,支持两种模式:表单模式(服务器定义输入字段,Claude Code 渲染表单)和 URL 模式(服务器提供 URL,用户在浏览器中完成操作后通知服务器)。

URL 模式的 elicitation 特别适合 OAuth 授权或外部服务集成:服务器返回一个 URL 和 elicitationId,Claude Code 显示该 URL 并等待用户完成操作。用户可以在浏览器中登录第三方服务,完成后服务器会发送 ElicitationCompleteNotification,触发 Claude Code 继续工具执行。这种机制避免了在 CLI 中处理复杂的 Web 流程。

Sources: elicitationHandler.ts, client.ts

Elicitation 交互模式

flowchart LR
    A[Tool Call] --> B{Elicitation Type?}
    
    B -->|Form| C[Server defines fields]
    C --> D[Claude renders form]
    D --> E[User fills inputs]
    E --> F[Submit to server]
    F --> G[Continue execution]
    
    B -->|URL| H[Server provides URL]
    H --> I[Display URL to user]
    I --> J[User opens in browser]
    J --> K[Complete external action]
    K --> L[Server sends completion]
    L --> M[Resume tool call]
    
    style A fill:#e1f5ff
    style D fill:#fff4e6
    style I fill:#e8f5e9

Elicitation 超时和重试由客户端控制:URL 模式默认等待 5 分钟,用户可以通过界面取消或重试。表单模式支持验证,服务器可以在用户提交后返回错误消息,要求重新输入。所有 elicitation 请求都通过 handleElicitation 回调传递给上层,允许 Claude Code 在不同环境(CLI、IDE、Desktop)中以最适合的方式渲染交互界面。

Sources: elicitationHandler.ts, client.ts

输出处理:验证、截断与持久化

MCP 工具的输出可能非常大(如数据库查询结果、文件列表),因此需要智能的截断和持久化策略。输出处理分为三个阶段:首先通过 getContentSizeEstimate 估算 token 数量(文本使用快速估计算法,图片固定 1600 tokens),然后检查是否超过 MAX_MCP_OUTPUT_TOKENS 限制(默认 25000,可通过环境变量或 GrowthBook 特性标志调整),最后根据内容类型选择截断或持久化。

对于文本输出,直接截断到字符限制(token 数 × 4),并附加截断消息提示用户使用分页工具。对于结构化内容(ContentBlock 数组),逐块累积直到达到限制,图片块会被压缩(通过 compressImageBlock)以减少 token 占用。对于二进制数据(如 PDF、图片),内容会保存到 ~/.claude/tool-results/ 目录,工具结果中只返回文件路径和元数据。

Sources: mcpValidation.ts, mcpOutputStorage.ts

输出处理决策树

输出类型Token 估算超限处理存储位置后续操作
纯文本字符数 / 4截断 + 提示内存中使用分页工具重试
结构化内容逐块累积截断 + 图片压缩内存中检查 structuredContent
二进制数据MIME 类型推断持久化到文件tool-results 目录使用 FileReadTool 读取
图片固定 1600压缩或持久化内存或文件直接显示或读取

持久化文件命名使用模式 {server}_{tool}_{timestamp}.{ext},扩展名根据 MIME 类型推断(如 application/pdf.pdf)。文件保存后会生成使用说明,指导 Claude 使用 offsetlimit 参数分块读取,避免一次性加载大文件。所有持久化文件会在会话结束时自动清理。

Sources: mcpValidation.ts, mcpOutputStorage.ts

错误处理与重连机制

MCP 集成的错误处理采用多层防御策略:协议层捕获 MCP SDK 的 McpError(包含 JSON-RPC 错误码如 -32000 ConnectionClosed),适配层将其转换为 TelemetrySafeError 以避免敏感信息泄露,应用层提供用户友好的错误消息和重试选项。错误分类通过构造函数名称和错误码实现,确保遥测数据的隐私安全性。

会话过期重试是关键机制:某些 MCP 服务器(如基于会话的 Web 服务)会在长时间不活动后使会话失效,返回特定的错误码。Claude Code 检测到这类错误后会清除连接缓存,重新建立连接,并自动重试工具调用(最多 1 次)。这种机制对用户透明,避免了手动重连的繁琐。

Sources: client.ts, MCPTool.ts

错误处理流程

flowchart TD
    A[Tool Call Error] --> B{Error Type?}
    
    B -->|McpError| C{Error Code?}
    C -->|-32042 Session Expired| D[Clear connection cache]
    D --> E[Retry once]
    E --> F{Retry succeeded?}
    F -->|Yes| G[Return result]
    F -->|No| H[Throw TelemetrySafeError]
    
    C -->|Other codes| I[Extract error message]
    I --> J[Sanitize for telemetry]
    J --> H
    
    B -->|Network Error| K[Log to debug]
    K --> L[Show connection hint]
    L --> H
    
    B -->|Auth Error| M[Update server status]
    M --> N[Show auth prompt]
    N --> O[User re-authorizes]
    O --> E
    
    style A fill:#ffebee
    style H fill:#e1f5ff
    style G fill:#e8f5e9

连接状态监控通过 Transport 的 onclose 回调实现:当底层连接断开时(如 stdio 子进程退出、WebSocket 连接丢失),缓存会被清除,下次工具调用时会自动重连。UI 层通过 MCPConnectionManager React Context 提供重连和切换服务器的功能,用户可以手动触发重连或禁用故障服务器。

Sources: client.ts, useManageMCPConnections.ts

性能优化:缓存与批处理

MCP 集成的性能优化集中在三个关键点:连接缓存(避免重复建立连接)、资源预取(启动时并行获取所有服务器的工具/资源/命令)、批处理启动(并发连接多个服务器,避免顺序等待)。这些优化使得即使配置了 10+ MCP 服务器,启动时间也能保持在可接受范围内。

connectToServer 函数使用 memoize 高阶函数缓存连接结果,缓存键由服务器名称和配置对象序列化生成。当配置变更时(如环境变量更新、OAuth 令牌刷新),缓存会自动失效。fetchToolsForClientfetchResourcesForClientfetchCommandsForClient 三个函数使用 LRU 缓存(大小 20),确保频繁访问的服务器数据在内存中,减少重复请求。

Sources: client.ts, client.ts

启动性能优化策略

graph LR
    A[App Startup] --> B[Load MCP Configs]
    B --> C[Partition servers]
    
    C --> D[Disabled servers]
    C --> E[Active servers]
    
    E --> F[Batch connect - concurrency 20]
    
    F --> G1[Server 1: connect]
    F --> G2[Server 2: connect]
    F --> G3[Server N: connect]
    
    G1 --> H1[Prefetch: tools+resources+commands]
    G2 --> H2[Prefetch: tools+resources+commands]
    G3 --> H3[Prefetch: tools+resources+commands]
    
    H1 --> I[Merge to registry]
    H2 --> I
    H3 --> I
    
    I --> J[App ready]
    
    style F fill:#fff4e6
    style I fill:#e8f5e9

并发连接控制通过 pMap 库实现,默认并发度为 20。这比传统的固定批次处理更高效:每个连接完成后立即释放槽位,避免慢速服务器阻塞整个批次。连接超时(60 秒)确保即使某个服务器无响应,也不会无限期阻塞启动。所有连接和预取操作都并行执行,最大化利用网络和 CPU 资源。

Sources: client.ts, useManageMCPConnections.ts

配置管理:多层级配置合并

MCP 配置支持六个作用域,按优先级从低到高:managed(企业强制配置)、enterprise(企业管理配置)、user(全局用户配置)、project(项目级配置)、dynamic(运行时动态配置)、local.mcp.json 文件)。配置合并时,高优先级配置会覆盖低优先级的同名服务器,但不同名服务器会合并。

配置来源包括:~/.config/claude-code/settings.jsonmcpServers 字段(user 作用域)、项目根目录的 .claude/settings.json(project 作用域)、项目根目录的 .mcp.json(local 作用域)、企业管理的 managed-mcp.json(managed 作用域)、Claude.ai 的远程配置(claudeai 作用域)、插件提供的 MCP 服务器(pluginSource 字段标记来源)。

Sources: config.ts, types.ts

配置作用域与合并规则

作用域存储位置优先级可修改性适用场景
managed~/.claude/managed/managed-mcp.json最低(1)只读企业强制策略
enterprise企业配置服务器2管理员组织级共享
user~/.config/claude-code/settings.json3用户个人偏好
project.claude/settings.json4项目成员项目特定
local.mcp.json5开发者本地开发
dynamic运行时 API最高(6)程序动态发现

环境变量展开在配置加载时自动执行:配置字符串中的 ${VAR_NAME}$VAR_NAME 会被替换为对应的环境变量值。这允许敏感信息(如 API 密钥)通过环境变量传递,避免硬编码在配置文件中。展开逻辑支持默认值语法 ${VAR:-default},当变量未定义时使用默认值。

Sources: config.ts, envExpansion.ts

实际应用场景

场景 1:数据库查询工具 — 通过 MCP 封装 PostgreSQL 客户端,提供 query 工具执行 SQL 查询,list_tables 工具浏览架构。服务器通过 resources 能力暴露数据库元数据(表结构、索引信息),Claude 可以先读取资源了解数据库结构,再构造精确的查询。

场景 2:云服务集成 — 使用 SSE 传输连接 AWS/Azure/GCP 的 MCP 服务器,通过 OAuth 认证访问用户资源。服务器提供 list_instancesdeploy_functionread_logs 等工具,Claude 可以执行完整的云资源管理流程。XAA 功能允许服务器以用户的身份访问其他 SaaS 服务。

场景 3:IDE 深度集成 — 通过 WebSocket 传输连接 VS Code 或 JetBrains 的 MCP 服务器,提供 goto_definitionfind_referencesrename_symbol 等语言感知工具。服务器通过 elicitation 请求用户确认重构操作,确保安全性。这种集成使 Claude Code 成为一个强大的代码智能助手。

Sources: client.ts, elicitationHandler.ts

延伸阅读