我们将 MCP 引入核心的原因,不仅在于 MCP 本身的变化,还在于我们发现它所需进行的改动总体上具有普遍价值。例如,我们为 MCP 所做的这些改动,也让 Jev 在 Pi 中更容易使用。归根结底,Pi 所需要的与 MCP 所需要的非常相似:一个以解释器形式存在的沙箱,供其运行与实验。
尽管 MCP 的许多方面都有了改进,但仍有不少问题悬而未决。MCP 最大的问题依然是难以组合。即便有了 codemode——它只是一个允许组合工具调用的精巧小沙箱——MCP 也未能完全实现这一点。不过到了如今,这更多是现有各类 MCP 服务器以及各种与之协作的 harness 实现方式的问题,而非 MCP 本身的问题。
许多 MCP 服务器仍然是为那种直接把工具倾倒进上下文的 harness 构建的,并试图通过返回文本在自身一侧优化 token 效率。我们如今更倾向于把 MCP 看作某种更接近于“带智能工具发现的 OpenAPI”的东西。这意味着工具应返回结构化数据,并且工具应能通过其文档和描述被发现。
CLI 之所以功能强大,是因为 agent 和模型可以用高效的 bash 技巧把各种东西连接起来。但从根本上说,没有理由不能用 MCP 做同样的事。Pi 中的 MCP 就是构建在把这些工具暴露给 JavaScript 沙箱之上,与其他 harness(如 Codex)的做法类似。
这会引出一个问题:为什么我们不干脆在没有 MCP 的情况下实现 Codemode。部分原因与如今 Pi 中工具的表达方式有关。近几个月我们做了大量工作,让 Pi 能适配新模型的能力,包括延迟工具加载、会话中途的系统消息以及推理级别的调整。但我们尚未升级工具装载(tool loadout)机制,以便更好地扩展到这些新能力。
在 Codemode 模式下,需要决定工具是对 LLM 完全可用,还是仅对 LLM 的 codemode 部分可用。普通的 MCP 扩展无法从 Pi 的工具装载中获得足够的元数据,来让这种体验良好运作。因此我们需要确保工具可以被配置为延迟加载,或成为 Codemode 专属的东西。
虽然我们本可以只把元数据接好以支持更好的 MCP 扩展,但我们认为 MCP 与 Codemode 的结合解决了它传统上的许多问题。我们相信,对某事物产生积极影响的最好方式就是拥抱它。尽管我们认为现代 MCP 已处于远超以往的良好状态,但其服务器和模式仍有改进空间。所以我们想参与这场讨论,帮助塑造它,使其在小型 harness 中也能良好运作,而不是站在一旁袖手旁观。
我们谈论了这么多 Codemode,或许值得解释一下它究竟是什么。当 harness 执行工具时,大体上涉及两侧:一是 bash 运行的一侧,二是 harness 的 agent 循环运行的一侧。两侧的信任级别截然不同。harness 循环通常运行在受信任的环境中,而它执行的工具往往运行在一个并非那么受信任的沙箱内。
Codemode 的特别之处在于它运行在 harness 所在的位置。最好把它理解为一种编排和协调工具调用的机制。它是一个沙箱,允许 agent 以更灵活的方式发出这些工具调用,自行决定调用顺序,并可以用 JavaScript 将它们组合起来。由于 Codemode 同样运行在 harness 一侧,其状态也作为会话记录(session transcript)的一部分来维护,而不是存放在文件系统中。
理论上任何语言都可以做到这一点,但 JavaScript 非常有吸引力,因为小型化的 JavaScript 可以以 WASM 二进制形式交付,并提供相当程度的保护。