Agent 工程对照
← 返回框架对照

工具 · 第 5 章

MCP 接入

外部 MCP 服务器以什么方式成为可用工具?

三家接 MCP,Pi 刻意不接;Codex 与 DeepSeek 独立收敛到几乎同一套工具命名。

场景建议

编辑判断

按你的需求,倾向哪种做法

借鉴的是那一家的设计,不等于选用那个框架。

场景

会接很多个 MCP 服务器,工具重名不可避免

两家都用 mcp__服务器__工具 命名,撞名或超长时追加身份哈希,保证不同工具不会合并成同一个名字。

场景

服务器的工具列表会变

它的插件在服务器工具列表变化时重新同步,公开名只由(服务器名, 原始名)决定。

场景

不想为 MCP 引入额外依赖

Pi 在 README 里明确不内置 MCP,用命令行工具加 Skills 替代。

容易踩的坑

  • 命名长度上限要跟着目标模型的函数名约束走:Codex 封顶 128,DeepSeek 封顶 64。

四家怎么做

差异与源码

openJiuwen

MCP 工具包成普通 Tool,和本地工具走同一条管线

每个 MCP 服务器的工具被包成 MCPTool——它就是 Tool 的子类,带 McpToolCard 元数据,和本地函数工具共享参数规整、事件触发与错误包装。传输方式由 McpServerConfig.client_type 选择,默认 sse;client 目录下有 stdio、sse、streamable http、playwright、openapi 五种客户端,另有 reconnect.py 处理重连。代价是 MCP 在这里没有自己的命名空间策略,工具名冲突要靠上层注册表处理。

适合
希望 MCP 工具与本地工具完全同构、共享参数规整与事件的系统。
代价
没有自己的命名空间策略,工具名冲突要靠上层注册表处理。
Codex

mcp__服务器__工具 命名,冲突时追加身份哈希

模型看到的名字是带前缀的 mcp__<服务器>__<工具>,先对命名空间、再对工具名做冲突检测:同一个可调用名背后有多个原始身份,就追加原始身份的 sha1 前 12 位,名字总长封顶 128。Codex 在 MCP 上是双向的:codex-mcp 与 rmcp-client 负责接入外部服务器(含 OAuth 登录流程),mcp-server crate 则把 Codex 自己暴露成一个名为 codex 的 MCP 工具,供别的 Agent 调用。

适合
既要接外部 MCP,又要把自己暴露给别的 Agent 调用。
代价
双向实现,外加 OAuth 登录流程,依赖与配置面最大。

此后的变化

  • 2026-W36 →

    新增能力协商门控的 MCP 用户验证(openai/userVerification 经 elicitation/create 处理),但在 Codex 内刻意保持未启用:收到请求即取消,待 app-server 与 UI 就绪后再开。

DeepSeek Harness

插件把 MCP 工具注册进 ToolRuntime,公开名是身份的纯函数

mcp-client 是一个插件,发现服务器的工具后注册到 ctx.tools,并在服务器的工具列表变化时重新同步。命名契约写在文件头:每个工具的身份是(服务器名, 原始名),公开名 mcp__<服务器>__<原始名> 只由它决定;原始名只在 tools/call 线上使用,公开名永远不反向解析。字符替换或截断到 DeepSeek 函数名约束(64 字符、只允许字母数字下划线连字符)改变了名字时,追加身份的 SHA-256 前 12 位,保证不同工具不会撞名。与 Codex 的方案几乎同构,差别在长度上限跟着自家模型的函数名约束走。

适合
工具列表会在运行时变化、名字必须稳定可预测的场景。
代价
要遵守「公开名永不反向解析」的契约,原始名只能在调用时使用。
Pi

刻意不支持:内核无 MCP,交给扩展

这是一格负面证据。在跟踪 commit 上对 pi 全仓库检索 mcp,除了这份 README、使用文档和一处注释里提到「MCP 桥接」产生的图片,没有任何 MCP 客户端实现。README 的 Philosophy 一节把它写成设计立场:用带 README 的命令行工具加 Skills 代替,或者自己写扩展接入 MCP;同一段还把子代理、权限弹窗、计划模式都列为不内置。README 的扩展能力清单里,MCP server integration 是作为「扩展能做到的事」出现的。

适合
认同「命令行工具加 README 就够了」、想让内核保持最小的团队。
代价
要接 MCP 就得自己写扩展。

此后的变化

  • 2026-W40 →

    不再是「不支持」:coding-agent 内置独立的 MCP 客户端(stdio 与 streamable HTTP,带 OAuth),服务器来自 mcp.json 或 pi.registerMcpServer(),首次使用时才加载。实现是内置扩展而非内核功能,可被替换。

横向读这一行

三家接 MCP、一家刻意不接。有意思的是 Codex 和 DeepSeek 独立收敛到了几乎同一套命名方案:模型看到的名字是 mcp__服务器__工具,撞名或超长时追加身份哈希的前 12 位,区别只在长度上限跟着各自模型的函数名约束走(128 对 64)。openJiuwen 把 MCP 工具包成普通 Tool,与本地工具共用管线;Pi 在 README 里写明「No MCP」,要接就写扩展。

这个问题为什么存在

第 5 章

工具调用:MCP 与 Skills

把世界暴露给模型:协议、技能与渐进式披露