idevlab-blogs
From:
chenli
Date:
Subject:

MCP 跑偏了

MCP 跑偏了的封面

最近读到 Pi 团队的《You Said No MCP!》。Pi 曾经明确说过“不要 MCP”,0.99.0 却把 MCP 和代码模式(codemode)一起做成了内置功能。[1] [3]

这谈不上打脸。Mario 当初批评的是常见 MCP 服务端的那一套:几十个工具描述一股脑塞进上下文,既贵又难组合。他更偏爱 Bash、命令行和代码,因为中间结果可以留在执行环境里,不必一轮轮喂回模型。[2] Pi 现在的做法,是把 MCP 工具接到代码模式下面:模型在沙箱里写一段程序把调用串起来,而不是先读完几十份工具说明,再临场决定下一步。[1] [3]

这个做法很漂亮,我还是觉得 MCP 跑偏了,只是方向和 Mario 说的不一样。上下文膨胀更多是当时最佳实践的问题,换个用法就能缓解;我在意的是另一件事。

去年我花了很长时间做 MCP Server,算是比较早吃螃蟹的。最折腾的从来不是少写了一个字段,而是对方说完“我支持 MCP”之后,一堆问题仍然悬着:工具怎么加载?分页和长任务处理不处理?支持哪一版授权?读不读结构化结果?碰到需要用户确认的操作,到底会不会弹窗?两边都写着 MCP,聊起来却像在说两种方言。

一句话:MCP 没有给服务端和 Agent 一个靠得住的办法,去判断对面会怎样把这次调用走完。

管道通了,活没干完

2024 年 Anthropic 发布 MCP 时,我们都把它想象成 AI 应用的 Type-C:接一次,到处能用。[4] 这个方向没有错。

但插得上,不等于能一起干活。工具调完之后,结果是列表还是一段说明?下一页谁来取?长任务怎么跟进?服务端要求用户确认,客户端会不会真的弹出来?任务跑到一半被取消,下次是重来、续上,还是拿到一段没法复用的历史?演示里不会暴露这些,调通一个工具就够了;放进真实流程,每一个都可能卡住。

拿结构化结果来说。MCP 后来加了 outputSchema 和 structuredContent,让服务端能声明返回数据的结构;但规范同时建议,为了兼容旧客户端,最好在文本字段里再放一份。[5] 官方 Ruby SDK 的响应对象支持 content 和 structuredContent,却不会替服务端自动把后者转回文本。[6] 于是服务端没法凭“支持 MCP”知道对方怎么消费结果,客户端也没法凭工具名判断,拿到的是稳定数据,还是写给模型看的说明。同一个工具,在这边是严格的程序接口,在那边只是模型要读的一段话。两种用法都说得通,可都被塞进“已支持”三个字里,开发起来就格外拧巴。

同样的协议连接到不同宿主应用,却会遇到完全不同的能力与结果

最头疼的是授权。客户端版本、注册方式、回调地址、令牌刷新,任何一环都能决定连不连得上。我当初在这上面卡了很久:有的客户端干脆不支持鉴权,有的只实现了一半,到今天也没补齐。大家都写着兼容 MCP,然后在登录这一步集体卡住。MCP 2026 年的规范也承认,授权是实现者投入集成时间最多的领域之一,并继续调整了 iss 验证、动态客户端注册和客户端身份绑定。[7]

同一份授权凭据面对不同实现,可能得到通过、拒绝或反复重试的结果

用户不关心这些排列组合,只看到同一个服务在这里能用,在那里不能。好的标准,至少应该让不兼容变得可见、可检测、可解释。支持矩阵、兼容性测试、讲得清楚的错误信息,往往比再加一个新功能更值钱。

两头都在猜

站在服务端作者这头,最难受的是不知道对面的 Agent 到底支持什么:新的授权流程认不认?资源、任务、用户确认处理不处理?收到 structuredContent,是照着 schema 用,还是转成文本丢给模型?新能力写好了,有的客户端悄悄退回文本,有的直接用不了。为了多跑通几个客户端,只能保守实现,或者一层层堆兼容分支。最后看起来支持一大堆能力,实际得按最弱的那个客户端来设计。

Agent 作者这头也不轻松。发现了一个 MCP Server,不代表知道它靠不靠谱:搜索能不能分页,筛选是不是真的生效,写操作有没有确认,授权过期会返回什么。工具描述写得再全,也保证不了两边把同一个词理解成同一个行为。于是运行时只好自己兜底超时、重试、降级和人工确认,谁都不敢轻信。

服务端不知道 Agent 接不接得住,Agent 不知道服务端兑不兑现。所谓“接一次就能通”,最后成了“接一次、测一次、记一笔特例”。兼容测试,还是每个接入的人自己再做一遍。

扩展把裂缝撑得更大

MCP Apps、插件扩展本身没有问题,业务工具当然需要界面。协议承载的东西越多,“支持 MCP”这句话能说明的就越少。

OpenAI 最近给 ChatGPT 加的 Plugin Extensions 就是例子。文档写得很清楚:它是在 MCP 和 MCP Apps 之上再定义的一层,共享部分走 MCP Apps,ChatGPT 独有的能力通过 window.openai 访问。[9] [11] [12] 对 ChatGPT 来说合情合理;可对服务端作者来说,从“MCP 已连接”再也推断不出侧边栏、对话面板、文件查看器在不在。同一个服务端,能用上多少功能,全看宿主实现了哪些扩展。

OpenAI 开发文档中的插件扩展入口示意:侧边栏、对话内面板与右侧工作区;图源:OpenAI Developers

Microsoft 的文档把这种差异列成能力矩阵,也建议应用在运行时检查宿主能力、准备替代路径。[10] 各家都在补自己的产品体验。补得越多,MCP 的“通用”就越像基础管道,真正决定体验的那一层又回到了各家私有实现里。

代码模式很好,命令行不是万能钥匙

Pi 和 Cloudflare 的代码模式确实解决了一个真问题:复杂调用交给代码组合,中间结果留在执行环境里,只把结论带回上下文。[8] Pi 通过工具元数据和延迟加载,把 MCP 接到自己的运行方式下面。它没有证明所有 MCP 服务端从此可以无差别地协作,也没有证明每个智能体都该照这个方式设计。

运行框架可以在基础管道之上完成发现、过滤、代码组合与上下文管理

批评完 MCP,很多人顺势转向命令行。对编程智能体来说,这很自然:模型会 Bash、grep、jq,代码库、Git 和登录态本来就在开发者电脑上。可要说命令行是所有智能体的通用接入方式,就跨得太远了。一个只需要查订单、改工单的智能体,没必要先领一台完整的 Linux 机器。把什么都包成命令行,原本只是“怎么调用”的问题,就变成了“机器里该放哪些状态和凭据”的问题。

OpenAI 的 Agents API 给了一条更清楚的边界:运行框架、会话和执行环境是三件事。智能体可以设置 environment.type = none,照样调用远程 MCP 和函数工具,真要处理文件、跑测试时再创建执行环境。[13] 读订单是服务连接,跑一批测试才是执行环境的事。两者分开,权限和成本都更好算。

命令行适合某些任务,但不应让每个小任务都先拖上一整台工作站

沙箱不是智能体的家

把常驻电脑当默认方案,很容易把智能体想象成“住在一台电脑里的东西”。我更愿意把沙箱看作执行节点:需要时创建,用完回收,只调远程工具时甚至不用创建。任务、状态、权限、审批记录和产物,都不该跟着某个沙箱一起消失。

凭据最能说明问题。在自己电脑上敲 gh issue list 很顺手,因为 GitHub、AWS、浏览器 Cookie 都在本地。临时沙箱没有这些前提。把全部凭据注入每个实例,或者干脆把主目录挂进去,撤权、审计、泄漏处置马上一地麻烦。所以 Claude Code 的云端沙箱把真正的 Git 凭据留在外面,沙箱只拿按会话限定的短期凭据访问代理;OpenAI 用 Vault 把 MCP 凭据放在智能体配置之外,Codex Cloud 的网络密钥则由受控代理在请求里替换。[14] [15]

沙箱是按需执行资源,身份、权限与凭据应留在受控边界之外

任务一变长,差别就更明显。换了设备、电脑休眠、网络中断、同事接手,任务都不该跟着某个桌面会话一起失踪。长期在线的控制层保住进度和授权,再决定下一步派给本地、沙箱还是远程服务;执行节点只管把眼前这段做完。今天的数据早就不以某台电脑为中心了。电脑是可调度的节点,不是智能体的身份。

控制层把任务按需分派到本地、临时沙箱和远程服务,再集中收回状态与产物

MCP 该退回一个更小的位置

MCP 已经装进了工具、资源、提示词、模型采样、用户交互、任务、界面、扩展和授权。每一项都有理由,但它们并不在同一层。2026-07-28 版规范其实也在收:核心协议改成无状态,去掉了握手和协议级会话;任务移出核心,成为官方扩展;根目录、采样和日志被标记为过时。[7]

我更愿意把 MCP 看成一层稳定的能力接口:有什么能力,接受什么输入,返回什么输出,一次受控调用怎样完成。工具发现、延迟加载、代码模式、界面、长任务和沙箱调度,交给上层的运行框架。让每一层按自己的速度变化:接口保守,框架尝新,产品为自己的关键路径负责。

那干脆重写一个更漂亮的协议?现实没这么干脆。标准不只看技术对不对,还要算迁移成本、已有投入、开发者习惯和平台利益。MCP 的优势不在于它已经把问题想清楚了,而在于它已经在那里:服务端、SDK、用户预期都有了。它大概率不会消失,甚至会成为所有智能体都有的一根公共管道。

风险也在这里:管道无处不在,但接入之前,开发者仍要逐个确认客户端、扩展、授权、界面和恢复方式。当年我们为不同的 API 做适配,盼着 MCP 终结碎片化;如果最后变成为不同厂商“对 MCP 的理解”做适配,就有点讽刺了。

我说它跑偏,指的是它最后可能只统一了一根管道。更多的 App、Extension、Plugin、Skill 和 Agent 都会接在它上面,从采用率看,MCP 会很成功。但决定任务能不能完成的行为仍散落在两端的私有实现里,开发者还是得为每一个对方重新做一次集成。

代码模式、Apps、Extensions、命令行、沙箱和云端控制层,各自都有理由,很多也解决了具体问题。把这一年折腾出来的东西摊在一起,我总会想起刘震云的《一地鸡毛》。不是要引用书里哪句话,只是这个书名太贴切:协议越来越完整,Agent 越来越聪明,架构图越来越复杂,每个人都在解决眼前那个合理的问题。最后低头一看,还是一地鸡毛。

参考资料

  1. Earendil,You Said No MCP!,Pi 对 MCP、代码模式与工具组合的解释。
  2. Mario Zechner,What if you don’t need MCP at all?,关于 MCP 工具加载、上下文与组合方式的批评。
  3. Pi,Pi 0.99.0,内置 MCP、代码模式、工具发现与结构化输出更新。
  4. Model Context Protocol,What is the Model Context Protocol?(2024-11-05),MCP 的早期开放协议定位。
  5. Model Context Protocol,Tools specification,outputSchema、structuredContent 与兼容性建议。
  6. Model Context Protocol Ruby SDK,Tool::Response implementation,Ruby SDK 的 content 与 structuredContent 响应实现。
  7. Model Context Protocol,2026-07-28 Specification Changelog;MCP 2026-07-28: A stateless protocol core and more。
  8. Cloudflare,Code Mode: the better way to use MCP,2025-09-26。
  9. Model Context Protocol,MCP Apps: Bringing UI Capabilities To MCP Clients;MCP Apps overview。
  10. Microsoft Learn,Add MCP apps to declarative agents in Microsoft 365 Copilot,宿主应用能力矩阵与替代路径建议。
  11. OpenAI Developers,Add UI to your MCP server,MCP Apps bridge 与 ChatGPT 专属 window.openai 扩展。
  12. OpenAI,DevDay 2026 Recap;OpenAI Developers,Plugin Extensions 与 Plugins reference,在 MCP 与 MCP Apps 之上的插件扩展规范、共享 bridge 与 ChatGPT 专属能力。
  13. OpenAI Developers,Agents API architecture;MCP connections,运行框架、执行环境与远程 MCP 边界。
  14. OpenAI Developers,Vaults,MCP 凭据的外置保管与按连接匹配;Anthropic,Making Claude Code more secure and autonomous 与 Claude Code security,云端沙箱与 Git 凭据代理。
  15. OpenAI Developers,Cloud environments,网络密钥的占位符与受控代理替换机制。