cheerio-mcp-bridges
cheerio-mcp-bridges
四個「窄工具」MCP server,讓一個沒辦法操作終端機 GUI 的 orchestrator agent(例如跑在 Cowork 裡的 Claude)能夠驅動本機已安裝、已登入的四個 coding CLI:
Server | 內部呼叫 | 對外工具 | 語言 |
|
|
| Node.js |
|
|
| Node.js |
|
|
| Node.js |
|
|
| Node.js |
四個 bridge 彼此獨立,不需要四個都裝。 先跑 npm run doctor 看這台機器有哪些 CLI 可用,只啟用對應的 bridge 就好。
四個 server 各自暴露單一、範圍受限的工具(不是通用 run_command)——只能「把一段 prompt 送給那個 agent」。殘餘風險在於底層 CLI 收到 prompt 後自己能做什麼,因此預設姿態偏保守。
設計要點
工作目錄由 server 鎖定:cwd 來自環境變數(
PI_BRIDGE_CWD/AGY_BRIDGE_CWD/CODEX_BRIDGE_CWD/COPILOT_BRIDGE_CWD),呼叫端的 prompt 無法變更。確定性的 session 續接:
pi:server 自己產生 UUID →
--session-id(pi 支援「不存在就建立」),第一次呼叫就把 id 回傳;之後帶同一個 id 續接,不依賴「continue 最近一個」的模糊語意。agy:無法預指定 id,第一次跑完從
--output-format stream-json的conversation_id撈出來回傳;之後用--conversation <id>續接。codex:第一次跑完從
thread.started事件的thread_id撈出來回傳;之後用codex exec resume <id>續接。copilot:server 自己產生 UUID →
--session-id,第一次呼叫就把 id 回傳;之後帶同一個 id 續接。
零 shell 注入:四邊都
shell:false直接 spawn,prompt 當作單一 argv 元素,任何 shell 特殊字元都不會被解讀。保守的權限旗標:
預設允許讀寫檔案(符合使用者選擇),但寫入/危險能力仍分段控制。
pi 預設不帶專案信任
-a(approve_project才開)。agy 預設不帶
--dangerously-skip-permissions;workspace 讀寫自動放行、shell 指令維持 gated,除非dangerously_allow_all:true。codex 預設 sandbox 為
read-only(danger-full-access要明確指定)。copilot 預設只帶
--allow-all-tools(非互動必要),不帶--allow-all(含 paths + urls),後者要dangerously_allow_all:true。
稽核:每次呼叫寫一行 JSONL 到
logs/<pi|agy|codex|copilot>-YYYYMMDD.jsonl(prompt、session/thread id、exit code、耗時、usage)。可用性登記表(避免對已知被限流的 model/host 白打):四個 bridge 呼叫 CLI 前都會先查
state/availability.json,命中封鎖中就直接回傳清楚錯誤、不 spawn CLI 浪費呼叫;呼叫後若偵測到限流訊號(429/quota/rate limit 等)會自動記錄封鎖時間。也支援人類手動回報「某 model 被鎖到幾點」。完整格式、三種 confidence(exact/estimated/human-reported)行為與手動回報做法,見state/README.md。
踩過的坑(實測得出)
stdin 必須關閉:CLI 都會把 piped stdin 當額外 context,Node spawn 預設留一個開著的 stdin pipe 會讓 CLI 卡住等 EOF。解法:
stdio: ['ignore','pipe','pipe']。pi extensions 預設關閉:互動型 extension(如
auto-annotate/plannotator)會在 headless 模式掛住(等一個永遠不出現的 UI)。因此預設帶--no-extensions,需要時用enable_extensions:true開回來。codex 必須帶
--skip-git-repo-check:如果 cwd 不是 git repo(例如C:/Cheerio),不帶這個 flag 會直接報錯退出。copilot 非互動模式一定要
--allow-all-tools:文件明確寫了 non-interactive mode 必須帶這個,否則會卡住等使用者確認權限。bridge 預設就帶--allow-all-tools,但--allow-all(含 paths + urls)只在dangerously_allow_all:true時才開。copilot MCP server 載入很慢:非互動模式下 copilot 仍然會載入所有 MCP server(playwright、notion、tavily 等),光是啟動就要 10~30 秒。timeout 設太短會在 MCP 載入階段就被 kill。
copilot 預設 auto-routing 可能撞 quota:不指定 model 時,copilot 的 hydra router 會自動選模型(例如
gpt-5-mini),如果該模型的配額用完就會直接失敗。建議呼叫端明確指定 model。Copilot/Codex 都無法非互動查詢剩餘總額度:
Copilot:
copilot billing/copilot limits是 help topic,只在互動模式 UI 裡有用。非互動 CLI 沒有copilot usage之類的指令。bridge 只能從model.call_failure事件裡的quotaSnapshots拿到「這次失敗時的快照」,無法主動查詢剩餘。Codex:
codex login status只顯示登入方式(Logged in using ChatGPT),沒有用量/配額查詢。codex doctor只做安裝診斷。bridge 的turn.completed.usage只有當次 token 用量,無剩餘額度。
企業級 TLS 攔截 Proxy 可能導致
npm install失敗:某些組織會使用 TLS 檢查型 Proxy(例如資安廠商的憑證攔截方案)對 HTTPS 流量做中間人解密。這會讓 Node.js 的 TLS 驗證失敗,npm install報UNABLE_TO_GET_ISSUER_CERT_LOCALLY或certificate chain incomplete之類的錯誤。解法:設定環境變數NODE_EXTRA_CA_CERTS指向公司的完整憑證鏈檔案(PEM 格式),注意需要的是 CA 中繼憑證(intermediate cert),不是只有 leaf cert。企業級 IP allow list 擋 CLI 存取(bridge 預設已處理):如果你的帳號所屬的企業級方案(例如 GitHub Copilot Enterprise)啟用了 IP allow list,
ask_copilot可能會被 API 擋下(錯誤訊息類似 "enterprise has an IP allow list enabled, and your IP address is not permitted")。根本原因通常是:bridge server 的父進程環境帶有HTTP_PROXY/HTTPS_PROXY之類的 proxy 設定,子進程的 CLI 工具繼承了這些 proxy 變數,導致 OAuth 請求繞經企業 proxy 出去,而 proxy 的出口 IP 不在對方的 allow list 內。bridge 從 v0.2.0 開始預設會自動 strip 掉子進程 env 裡的 proxy 環境變數(HTTP_PROXY/HTTPS_PROXY/ALL_PROXY含大小寫變體),讓 CLI 直接對外連線來避開這個問題。如果你的環境情況相反(必須經過 proxy 才連得到目標服務),可以設BRIDGE_BYPASS_PROXY=false切回讓子進程繼承 proxy 設定。
跨機器安裝(從零開始)
四個 bridge 彼此獨立。先跑
npm run doctor看這台機器有哪些 CLI 可用,只把對應的 bridge 註冊進 MCP client 設定就好,其他沒裝的不要加。
前置需求
Node.js ≥ 18(需要支援
node:test和 ES module)npm ≥ 9
Step 1:Clone & 安裝
git clone https://github.com/CheerioCorner/cheerio-mcp-bridges.git
cd cheerio-mcp-bridges
npm installStep 2:檢查哪些 CLI 可用
npm run doctor會輸出一個表格,告訴你 4 支 CLI 各自找到了沒有、能不能正常執行 --version,以及建議啟用哪些 bridge。
Step 3:安裝你需要的 CLI(如果還沒裝)
以下是各 CLI 的安裝與登入方式,沒裝的跳過就好,不用全部裝:
pi(earendil-works/pi)
npm install -g @earendil-works/pi-coding-agent
pi # 首次啟動會引導登入驗證:pi --version 或 pi --help
agy(Google Antigravity CLI)
# 請參考官方文件安裝,通常是一個獨立執行檔
# https://github.com/nicholasareed/antigravity
agy # 首次啟動會引導 Google 帳號授權驗證:agy --version
codex(OpenAI Codex CLI)
# 請參考 OpenAI 官方文件安裝
# Windows 通常安裝在 %LOCALAPPDATA%/Programs/OpenAI/Codex/
codex login # 會引導 ChatGPT 帳號授權驗證:codex --version、codex login status
copilot(GitHub Copilot CLI)
npm install -g @github/copilot-cli
copilot login # 會引導 GitHub 帳號授權驗證:copilot --version
Step 4:選擇性啟用 bridge
把你需要的 bridge 設定從 mcp-config.example.json 複製進你的 MCP client 設定(例如 ~/.mcp.json 或 .mcp.json)。
不要四個全抄。 只複製你這台機器有裝且有登入的 CLI 對應的區塊,然後調整路徑與環境變數。
例如你只裝了 pi 和 copilot,就只加 pi-bridge 和 copilot-bridge 兩個區塊。
Step 5:驗證 bridge 正常運作
啟動你的 MCP client 後,用對應的工具送一個很小的 prompt 測試:
ask_pi:{ "prompt": "Reply only: pong" }ask_agy:{ "prompt": "Reply only: pong" }ask_codex:{ "prompt": "Reply only: pong" }ask_copilot:{ "prompt": "Reply only: pong" }
應該要收到 pong 回覆和一行 bridge metadata。如果收到錯誤訊息,檢查:
CLI 執行檔路徑(環境變數
*_BRIDGE_ENTRY)是否正確CLI 是否已登入
cwd 環境變數(
*_BRIDGE_CWD)是否存在
快速開始
cd C:/Cheerio/CheerioCorner/mcp-bridges # 或你 clone 的路徑
npm install
npm run doctor # 檢查哪些 CLI 可用
npm test # 執行 parser/arg-builder 單元測試(不花 API 額度)註冊到 MCP client
見 mcp-config.example.json。那是一份菜單——照你這台機器實際有的 CLI,只挑對應的區塊複製進你的 MCP client 設定(.mcp.json),並依實際路徑調整。不是四個都要抄。
工具介面
ask_pi
參數 | 型別 | 預設 | 說明 |
| string | — | 要送給 pi 的指令(必填) |
| string | 自動產生 | 帶上一次回傳的值即可續接同一對話 |
| boolean | false | true 時只給 |
| string | — | 覆寫 model |
| boolean | false | 是否信任專案本地資源(pi -a) |
| boolean | false | 是否載入 extensions(有掛住風險) |
| number | 300000 | 硬性逾時 |
回傳:pi 的最終文字 + 一行 pi-bridge metadata(含 session_id)。
ask_agy
參數 | 型別 | 預設 | 說明 |
| string | — | 要送給 agy 的指令(必填) |
| string | 自動擷取 | 帶上一次回傳的值即可續接 |
| string | — | model slug(見 |
| low|medium|high | — | 推理強度 |
| boolean | false | 開終端沙箱限制(--sandbox) |
| boolean | false | 危險:自動批准所有工具權限(含 shell) |
| number | 300000 | 硬性逾時(同步作為 agy --print-timeout) |
回傳:agy 的最終回應 + 一行 agy-bridge metadata(含 conversation_id、status)。
ask_codex
參數 | 型別 | 預設 | 說明 |
| string | — | 要送給 Codex 的指令(必填) |
| string | 自動產生 | 帶上一次回傳的 thread_id 即可續接 |
| string | — | 覆寫 model(如 |
| read-only|workspace-write|danger-full-access | read-only | 沙箱策略 |
| number | 300000 | 硬性逾時 |
回傳:Codex 的最終文字 + 一行 codex-bridge metadata(含 thread_id、usage)。
ask_copilot
參數 | 型別 | 預設 | 說明 |
| string | — | 要送給 Copilot 的指令(必填) |
| string | 自動產生 | 帶上一次回傳的值即可續接同一對話 |
| string | — | 覆寫 model(如 |
| none|minimal|low|medium|high|xhigh|max | — | 推理強度 |
| number | — | 單次呼叫的花費上限(安全閥) |
| boolean | false | 危險:加 |
| number | 300000 | 硬性逾時 |
回傳:Copilot 的最終回應 + 一行 copilot-bridge metadata(含 session_id、usage、quota_snapshots)。
額度查詢限制:Copilot CLI 沒有非互動模式的指令能查詢「剩餘總額度」。
copilot billing/copilot limits只在互動模式的 UI 裡有用。bridge 只能回報「這次呼叫消耗多少」(usage+ 當次quotaSnapshots),無法回報剩餘總額度。Codex 同理,codex login status只顯示登入狀態,無用量查詢。
環境變數
變數 | 預設 |
|
|
| pi 的 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BRIDGE_BYPASS_PROXY:bridge 預設會在呼叫底層 CLI 前 strip 掉子進程 env 裡的 HTTP_PROXY/HTTPS_PROXY/ALL_PROXY(含大小寫變體),避免子進程被父進程繼承到的企業 proxy 設定牽連。只有明確設成字串 "false" 時才關閉 strip 行為。