過去打開 pi.dev,會看到這個 coding agent 大方宣告「不支援 MCP」,但最新版的 Pi 把 MCP 放進了核心。這不只是妥協:開發團隊 Earendil 真正想推的是 Codemode——讓 Agent 寫一小段 JavaScript,在沙箱裡把多個工具呼叫串起來,而 MCP 是把外部工具接進這個沙箱最現成的管道。
下面用原文的例子走一遍:Agent 怎麼呼叫幾百次工具,上下文裡卻只留下一份結論。
先看問題:工具一次叫一個,為什麼不夠
MCP(Model Context Protocol)是模型串接外部工具的協定:工具伺服器描述自己有哪些功能,harness(負責跑對話迴圈、替模型執行工具的程式)再把工具交給模型。
Earendil 認為 MCP 最大的問題一直是難以組合。很多 MCP 伺服器是為這樣的 harness 設計的:把所有工具定義塞進上下文,模型每次呼叫一個工具、等結果回來再決定下一步;伺服器為了省 token,多半回傳文字而非結構化資料。照這種用法,想對一百多筆資料各做一次操作,就得來回上百輪,中間結果全堆進上下文。
命令列工具(CLI)好用,是因為模型能用管線、迴圈這類 shell 寫法一次處理一批。Earendil 認為 MCP 沒有本質上的理由做不到,缺的只是一個能用程式組合工具的地方。
Codemode:跑在 harness 這一側的沙箱
harness 執行工具有兩個位置:bash 所在、信任度不高的沙箱,以及 harness 自己的 Agent 迴圈所在、通常受信任的環境。
Codemode 跑在後者,專門用來編排工具呼叫:模型不再一次叫一個工具,而是寫一段 JavaScript,自己決定呼叫順序、要不要平行,再組合結果。因為在 harness 這側,它的狀態存在 session 紀錄裡,而不是檔案系統。選 JavaScript 是因為精簡版 JS 引擎可以編成 WASM(WebAssembly,可在隔離環境執行的二進位格式)一起發布,提供合理程度的保護。
在 Pi 裡,設定 MCP 時 Codemode 會自動載入,也能設成預設工具。
走一遍:找出 issue tracker 上最不耐煩的人
原文請 Pi「透過 Codemode 用 Jev 找出 issue tracker 上最沮喪的留言者」。Jev 是經由 Cloudflare Workers AI 取用的分類模型。模型寫出的程式做了四件事:
- 透過 Linear 的 MCP 工具,拉出 Pi 團隊最多 250 筆未關閉的 issue
- 定義分類問題:只判斷留言者的情緒,分成 none、mild、high 三級,並明確要求忽略 bug 本身的嚴重程度
- 開 4 個 worker 平行處理,每筆 issue 先用 MCP 工具抓留言,再交給 Jev 分類
- 用
store存下逐筆結果,再以「mild 機率 × 0.5 + high 機率」排序
執行紀錄顯示背後跑了三百多次工具與模型呼叫,回到對話的卻只有一份摘要:167 筆未關閉的 issue 中,156 筆中性、11 筆輕微不滿、沒有高度不滿,外加被標記的清單。逐筆判斷仍存在 Codemode 裡,之後追問某一筆不必重抓資料。
這就是「可組合」:迴圈、平行、排序都在沙箱內完成,上下文只留下模型需要讀的結論。
為什麼不乾脆只做 Codemode
既然重點是 Codemode,為何還把 MCP 從擴充套件收進核心?原文給了兩個理由。
第一是工具配置。新一代模型支援延遲載入工具(需要時才載入工具定義)等能力;有了 Codemode,每個工具還得決定是直接給模型呼叫,還是只在 Codemode 裡可用。一般的 MCP 擴充套件拿不到 Pi 工具配置裡足夠的中繼資料,所以要在核心讓工具能設成延遲載入或 Codemode 專用。
第二是態度。Earendil 認為 MCP 搭配 Codemode 解決了不少舊問題,而影響一個標準最好的方式是參與它。
還沒解決的部分
Earendil 也直說,即使有 Codemode,MCP 的組合性仍未完全到位,但問題更多出在現有伺服器與各家 harness 的用法。他們期待 MCP 更接近 OpenAPI 加上智慧型工具探索:工具回傳結構化資料,並能靠文件與描述被找到。上面例子能直接取 comments 欄位接著處理,前提就是伺服器回傳結構而非文字。
所以 Pi 轉向的重點不在協定,而在工具怎麼被呼叫。當工具能被程式組合、回傳結構化資料,MCP 和 CLI 的差距就在伺服器是否為這種用法設計。
參考來源
- “You Said No MCP!”(Earendil Engineering)
回應
還沒有回應,成為第一個留言的人吧。