MCP集成
1. 定位
src/services/mcp/ 不是一个单纯的“第三方连接器目录”,而是 Claude Code 对外部能力的运行时协议接入层。它做的事情可以概括成两部分:
- 配置汇总:决定有哪些 MCP server 应该进入系统
- 连接执行:真正建立 transport、处理 auth、拉取 tools / prompts / resources / skills,并执行调用
因此,MCP 集成是整个生态扩展体系里最接近“运行时总线”的一层。
2. 配置汇总层
配置汇总的主入口是 src/services/mcp/config.ts。
2.1 配置模型
src/services/mcp/types.ts 定义了 McpServerConfig 与 ScopedMcpServerConfig。当前支持的 transport / 配置类型包括:
stdiossesse-idehttpwsws-idesdkclaudeai-proxy
其中,对外文档通常只需要把 stdio、sse、http、ws、sdk 视为主要 transport;其余更偏内部接入或特化场景。
2.2 Scope 与来源
MCP 配置不是单一文件读取,而是多 scope 汇总。当前类型系统里的 scope 包括:
enterpriseuserprojectlocaldynamicclaudeaimanaged
在 getClaudeCodeMcpConfigs() 这条链路中,真正参与 Claude Code 本地配置聚合的重点来源是:
- enterprise
- user
- project
- local
- plugin dynamic
之后 getAllMcpConfigs() 还会继续把 claude.ai connectors 合并进来。
2.3 策略过滤
配置汇总阶段还会执行策略过滤:
allowedMcpServersdeniedMcpServersallowManagedMcpServersOnly
config.ts 中分别实现了名字、命令数组和 URL 模式级别的 allowlist / denylist 判断。这说明 MCP 的安全约束并不是只在建连时拦截,而是在配置进入系统前就开始过滤。
2.4 项目级审批与显式启停
对 project .mcp.json 中的 server,系统还会结合 getProjectMcpServerStatus() 判断其状态:
approvedrejectedpending
此外,isMcpServerDisabled() 与 setMcpServerEnabled() 负责显式启停。也就是说,MCP server 的可见性并不是“配置存在就一定连接”,而是叠加了策略、审批与用户开关。
3. 插件提供的 MCP Server 如何并入
src/utils/plugins/mcpPluginIntegration.ts 是 Plugin 与 MCP 的接口层。
3.1 输入来源
插件可以通过几种方式提供 MCP server:
- 插件目录中的
.mcp.json - manifest 中的
mcpServers - MCPB / DXT bundle
- assistant-mode channels 上的
userConfig
3.2 环境变量与用户配置注入
resolvePluginMcpEnvironment() 会在插件 server 进入 MCP 总配置前做变量展开,主要处理:
${CLAUDE_PLUGIN_ROOT}${user_config.X}- 一般环境变量
${VAR}
同时还会为 stdio server 注入:
CLAUDE_PLUGIN_ROOTCLAUDE_PLUGIN_DATA
这一步让插件 MCP server 具有“插件上下文感知”。
3.3 作用域前缀与去重
插件 server 被装配时会调用 addPluginScopeToServers(),统一加上类似 plugin:<pluginName>:<serverName> 的作用域前缀,并标记 scope: 'dynamic'。
之后 config.ts 还会对 plugin MCP servers 做去重,避免:
- 和手工配置的 server 重复
- 插件之间提供同一底层命令或 URL 的 server
因此 Plugin 提供 MCP server 时,不会直接无条件覆盖主配置,而是进入统一合并与去重规则。
4. 连接执行层
MCP 执行的主入口在 src/services/mcp/client.ts。
4.1 建连与 transport
client 层会基于不同配置选择不同 transport,例如:
StdioClientTransportSSEClientTransportStreamableHTTPClientTransport- WebSocket transport
- SDK control transport
这说明 MCP 集成不是面向单一协议实现,而是面向“多 transport 的统一客户端封装”。
4.2 连接状态模型
types.ts 中定义的 MCPServerConnection 不是简单“连上/没连上”二元状态,而是多态状态:
connectedfailedneeds-authpendingdisabled
这个状态模型会被会话层、UI 层和 /mcp 命令共同消费。
4.3 建连后拉取的能力
建连成功后,MCP 客户端不会只拉取 tools,还会根据 server capabilities 拉取:
- tools
- prompts / commands
- resources
- skills
其中 skill 是 MCP 集成里最容易被忽略的一环。当前实现会在 prompts 或 resources 发生 list_changed 时,刷新相关缓存,并把新的 MCP skills 与 prompts 一起写回命令集合。
这说明 MCP 的输出不是“只为 Tool 层服务”,而是会回流到命令层与技能层。
5. 关键运行机制
5.1 OAuth 与 needs-auth
client.ts 对远程 server 的 auth 处理相当重。它显式区分:
- 已连接
- 需要认证
- 401 后的 token refresh
- 会话级 auth 缓存
遇到 401 或未授权状态时,server 会被标记为 needs-auth,并写入本地缓存,避免持续重试导致的噪音和延迟。
5.2 Session Expired 与自动恢复
对于 HTTP 类 MCP server,代码里单独识别了 session 失效场景,例如:
- 404 + JSON-RPC
-32001 - “Connection closed” 派生错误
一旦识别,会清理连接缓存并要求下次工具调用重新建连。这说明 MCP 集成在设计上已经把“长连接会过期”视为常态,而不是异常边角。
5.3 Large Result 持久化与截断
当 MCP tool 返回结果过大时,client.ts 不会简单抛错,而是会:
- 估算内容大小
- 决定是否截断
- 必要时把内容持久化到文件
- 返回一段引导文本,提示后续如何读取
这一步把 MCP 大输出从“模型上下文风险”转成了“可回读的外部工件”。
5.4 URL Elicitation Retry
对 MCP 的 URL elicitation,callMCPToolWithUrlElicitationRetry() 会在检测到 UrlElicitationRequired 后:
- 调用 hook
- 或将请求送入 UI / SDK 交互层
- 等待用户完成
- 再重试工具调用
这体现出 MCP client 不是“盲目 RPC 转发器”,而是能和用户交互流程配合的协议适配器。
6. 与 Commands、Skills、Resources 的关系
MCP 集成的一个关键特点,是它同时影响多种运行时对象。
6.1 Tools
这是最直观的一层。MCP tool 会被包装为内部 Tool,供模型调用。
6.2 Commands
MCP prompts 会作为命令进入系统,命名规则通常是 mcp__<server>__<prompt>。src/services/mcp/utils.ts 里也专门区分了 MCP prompts 与 MCP skills 的名字模式与过滤逻辑。
6.3 Skills
MCP skills 则会被建模为 loadedFrom === 'mcp' 的 prompt commands,并进入 mcp.commands。之后:
commands.ts可以把它们筛出attachments.ts会把它们并入 skill listingSkillTool也会把它们和本地 skills 合并展示
所以,从用户和模型的视角看,MCP 并不只是“多了几个远端工具”,而是整个能力集合都可能因远端 server 而变化。
6.4 Resources
MCP resources 则以 ServerResource 形式进入资源视图,用于后续浏览、读取和引用。
7. 小结
MCP 集成在 Claude Code 中承担的是外部能力接入总线的角色。它并不只负责“连上一个 server”,而是把外部能力完整转换为内部运行时对象,并在这个过程中处理:
- 多 scope 配置聚合
- 策略过滤与审批
- 插件 server 注入
- transport 适配
- auth 与会话恢复
- tool / prompt / skill / resource 拉取
- 大结果处理与交互式重试
因此,在生态扩展三层里,MCP 是最靠近执行面的那一层;它把 Plugin 分发进来的 server,或者用户直接配置的 server,真正变成了会话可用能力。