模型: openai/gpt-5.4
生成日期: 2026-04-01
书名: Claude Code VS OpenCode:架构、设计与未来
章节: 第7章 — MCP:AI的USB-C
Token用量: 约 12,500 input + 2,200 output(估算)
7.2 MCP实现对比
如果说 7.1 讨论的是 MCP 在理念层面为什么重要,那么这一节关心的是另一个问题:三套系统到底“怎么把它做出来”。OpenCode、Claude Code、Oh-My-OpenCode(OMO)都把 MCP 视为关键能力层,但它们的实现风格并不相同。读源码后可以很明确地看到三种取向:OpenCode 强在 breadth,即协议覆盖面广、开放基座完整;Claude Code 强在 depth,即把 MCP 做成了深度产品子系统;OMO 则强在 creativity,把 MCP 与技能系统、兼容层、内建远程服务做了高度创造性的组合。
OpenCode:完整而开阔的 MCP client 基座
OpenCode 的 MCP 实现主要位于 packages/opencode/src/mcp/。核心文件是 index.ts,配套还有 auth.ts、oauth-provider.ts、oauth-callback.ts。从架构角度看,它最重要的特征是:它不是“象征性支持 MCP”,而是真正把自己做成了一个 full MCP client。
首先,在 transport 层,它直接使用官方 SDK 提供的多种客户端 transport:
StdioClientTransport:连接本地 subprocess 型 MCP serverSSEClientTransport:连接基于 SSE 的远程 serverStreamableHTTPClientTransport:连接 streamable HTTP server
这意味着 OpenCode 从一开始就覆盖了本地与远程两大主要 MCP 部署场景。对一个开源 Agent runtime 来说,这个覆盖面已经非常重要,因为它决定了生态接入上限。
其次,OpenCode 不只是“连上 server”,而是把 MCP tool 真正转成自身 runtime 能消费的 tool abstraction。在 mcp/index.ts 里,convertMcpTool() 会把 MCP server 返回的 tool definition 转换成 AI SDK 的 dynamicTool。这里的关键点在于 schema normalization:MCP tool 通常以 JSON Schema 描述参数,OpenCode 需要把它整理成内部一致的 tool interface,再交给模型与执行层使用。也就是说,它做了一个非常典型的 adapter:把外部协议对象,转成内部原生工具对象。
这一步很关键。因为如果 host 只是“把 MCP 当外部黑盒”,那 MCP 很难真正融入 agent 推理链路;而 OpenCode 的做法是让 MCP tool 在宿主内部变成“一等工具公民”。这样,模型调用 MCP tool 时,体验上更像是在调用 host 自带工具,而不是在跨一个怪异子系统。
第三,OpenCode 认真处理了 MCP 的三类能力,而不只关注 tool。源码里可以看到它会 listPrompts()、listResources(),并分别管理 prompt 与 resource 的信息缓存。同时它还注册 tool list changed notification,在 server 工具集发生变化时通过 bus 发事件。这说明它理解 MCP 不是“tool-only protocol”,而是一个更丰富的 capability protocol。
第四,OpenCode 实现了相当完整的 OAuth support。auth.ts 中定义了 token、client info、code verifier、oauth state 等结构,并把认证信息持久化到 mcp-auth.json。oauth-provider.ts 实现 OAuth client provider,oauth-callback.ts 负责本地 callback server、state 验证与超时处理。这套实现当然还不像大型商业产品那样庞大,但对开源宿主来说,已经足以支撑真实远程 MCP server 的接入,而不只是 demo 级玩具。
综合来看,OpenCode 的 MCP 设计核心是:覆盖面广、结构干净、足够通用。它把 tools、resources、prompts、stdio/SSE/HTTP transport、OAuth、动态工具转换这些关键部件都铺好了,非常像一个面向生态的基础设施层。
Claude Code:把 MCP 做成产品操作系统的一部分
Claude Code 的情况明显不同。它的中心文件 src/services/mcp/client.ts 长达 3,348 行。这个体量本身就说明,它不是在“支持一个协议”,而是在构建一个完整的 MCP product subsystem。
第一层差异,是 transport depth。Claude Code 在 types.ts 中支持 stdio、sse、http、ws、sdk,还包括内部特殊类型如 claudeai-proxy。此外,它还有 InProcessTransport,用于同进程内 client/server 通信;以及 SdkControlTransport,用于 CLI 进程与 SDK 进程之间桥接 MCP 消息。换句话说,Claude Code 不只是把 MCP 用来连接“外部 server”,它还把 MCP 当作内部系统边界来使用。
第二层差异,是 auth complexity。Claude Code 的 MCP auth 不是简单的 access token 存取,而是覆盖 OAuth discovery、token refresh、token revocation、callback port 管理、auth cache、claude.ai auth 协同,甚至还有 XAA 等更复杂配置。为什么会这样?因为一旦 MCP 进入 commercial product,认证就不再是“能连上就行”的问题,而是“长期运行下各种失败路径怎么收敛”的问题。token 会过期、metadata 会不规范、用户会中途取消、server 会返回 401,产品必须提供恢复路径。
第三层差异,是 product UX integration。Claude Code 实现了 elicitation 处理。所谓 elicitation,可以理解为 MCP server 主动向客户端请求更多用户输入或确认信息的一种交互机制。这类术语不常见于传统 CS 教材,更像 AI 产品化过程里长出来的 interaction protocol。elicitationHandler.ts 中可以看到,Claude Code 会注册 request handler,把 elicitation 事件挂到 AppState 队列里、等待用户响应、记录 analytics,并处理 completion notification。这说明 Claude Code 已经把 MCP 视为 UI 可交互的一部分,而不只是后台能力调用。
第四层差异,是 policy and permissions。Claude Code 针对某些 MCP server,尤其 channel 类 server,做了额外的 allowlist、org policy、channel permission gating。channelNotification.ts、channelPermissions.ts 等文件表明:在 Claude Code 里,并不是所有 MCP server 都被同等对待。有些 server 被看作通信通道,因此必须满足 claude.ai OAuth、组织级启用策略、session allowlist 等条件。这个设计非常“商业化”:协议支持只是起点,真正落地还要考虑信任边界和产品治理。
第五层差异,是 ecosystem curation。officialRegistry.ts 会从 Anthropic 的 registry endpoint 拉取官方 MCP URL 列表并缓存,提供 isOfficialMcpUrl() 判断。这个能力看似小,但含义很深:Claude Code 不只是支持开放生态,它还尝试对生态做“官方发现与信任锚定”。当生态扩张到一定规模后,discoverability 与 trust 本身就是产品功能。
第六层差异,是 Claude.ai integration。Claude Code 能获取符合条件的 claude.ai MCP configs,把它们映射成 claudeai-proxy 类型 server;同时还能通过 SdkControlClientTransport 桥接 SDK 内部运行的 MCP server。这代表它把 MCP 同时用于外部集成、内部组件、云端连接器和产品平台整合。
因此,Claude Code 的 MCP 关键词不是 breadth,而是 depth。它把协议、产品、权限、云端服务、内部 SDK、交互 UX 织成了一张密网。MCP 在 Claude Code 里,已经不像一个“插件接口”,更像是其 product operating environment 的一部分。
OMO:把 MCP 做成技能与生态迁移的组合件
OMO 的路线又不同。它没有试图重造一套比 Claude Code 更深的 MCP client 栈,而是利用 OpenCode 基座,走出了一条很有想象力的组合式道路。
首先,OMO 在 src/mcp/ 内置了 三个 remote MCP:
websearch:通过 Exa 或 Tavily 提供 web searchcontext7:提供官方文档检索grep_app:提供 GitHub 代码搜索
这三个 MCP 的配置实现很短,但选择非常精准。它们恰好覆盖了自主 Agent 最常见的研究三件套:网页发现、官方文档、真实代码样本。也就是说,OMO 不是追求“默认塞进一大堆 MCP”,而是优先把最能提升 agent 推理质量的三类能力固化成内建 substrate。
其次,OMO 做了一个非常实际的东西:Claude Code MCP loader。在 src/features/claude-code-mcp-loader/ 中,它会从多个 scope 读取 .mcp.json,再 transform 成 OMO/OpenCode 可用的格式。这本质上是一个迁移兼容层。它不要求用户重建 MCP 生态,而是允许用户把 Claude Code 的 MCP 配置直接迁过来。对于生态扩展来说,这种兼容性比“重新发明一套新规范”更有吸引力。
第三,也是 OMO 最有原创性的地方:skill-embedded MCPs。在 OMO 里,skill 不只是 prompt/instruction bundle,它还可以携带自己的 MCP 配置。SkillMcpManager 负责管理这些 skill 内嵌 MCP 的连接生命周期:支持 HTTP 与 stdio 两类连接;进行 env expansion;失败时 retry/reconnect;管理 auth provider;按 sessionID + skillName + serverName 做 client caching;空闲一段时间后自动清理连接。这种机制实质上是一种轻量级 connection pooling,也可以理解为“按技能域隔离的 MCP client cache”。
这件事的意义很大。传统系统里,skill 往往只负责“怎么想”,MCP 负责“怎么连工具”;两者分属不同扩展平面。而 OMO 把它们半融合了:一个 skill 可以同时附带行为知识和外部能力。这意味着“专业能力包”不再只是 prompt,而可以成为“prompt + tool substrate”的复合体。
src/tools/skill-mcp/tools.ts 里的 skill_mcp 工具进一步把这个想法落地。它允许当前 agent 去调用某个 skill 所声明的 MCP server 的 tool、resource 或 prompt。换句话说,skill 加载后,不仅指令进入上下文,它自己的外部能力也能立即进入执行面。这是非常漂亮的扩展模式。
总结:breadth、depth 与 creativity
因此,三者的对比可以非常简洁地概括为:
- OpenCode:breadth —— 完整、开放、通用的 MCP client 基座
- Claude Code:depth —— 深度产品化的 MCP 平台
- OMO:creativity —— 将 MCP、skills、兼容层、内建 remote capabilities 组合出新扩展范式
这个对比也提醒我们:所谓“支持 MCP”,其实至少有三层含义:
- Protocol coverage:是否覆盖 tools/resources/prompts、是否支持主要 transports、是否有 auth
- Product integration:是否与 UI、permission、policy、state recovery、interactive flow 深度集成
- Extensibility design:是否能与 plugins、skills、迁移兼容、用户生态结合
OpenCode 在第 1 层尤其强,Claude Code 在第 2 层遥遥领先,而 OMO 在第 3 层最有想象力。也正因如此,MCP 不只是一个技术协议,更是一面镜子:透过它,我们能看出一套 Agent 系统究竟想成为“开放基座”“商业操作系统”,还是“高创造力的编排平台”。