Skip to main content
Glama
CheerioCorner

cheerio-mcp-bridges

cheerio-mcp-bridges

四個「窄工具」MCP server,讓一個沒辦法操作終端機 GUI 的 orchestrator agent(例如跑在 Cowork 裡的 Claude)能夠驅動本機已安裝、已登入的四個 coding CLI

Server

內部呼叫

對外工具

語言

pi-bridge

pi(earendil-works/pi)

ask_pi

Node.js

agy-bridge

agy(Google Antigravity CLI)

ask_agy

Node.js

codex-bridge

codex(OpenAI Codex CLI)

ask_codex

Node.js

copilot-bridge

copilot(GitHub Copilot CLI)

ask_copilot

Node.js

四個 bridge 彼此獨立,不需要四個都裝。 先跑 npm run doctor 看這台機器有哪些 CLI 可用,只啟用對應的 bridge 就好。

四個 server 各自暴露單一、範圍受限的工具(不是通用 run_command)——只能「把一段 prompt 送給那個 agent」。殘餘風險在於底層 CLI 收到 prompt 後自己能做什麼,因此預設姿態偏保守。

設計要點

  1. 工作目錄由 server 鎖定:cwd 來自環境變數(PI_BRIDGE_CWD / AGY_BRIDGE_CWD / CODEX_BRIDGE_CWD / COPILOT_BRIDGE_CWD),呼叫端的 prompt 無法變更

  2. 確定性的 session 續接

    • pi:server 自己產生 UUID → --session-id(pi 支援「不存在就建立」),第一次呼叫就把 id 回傳;之後帶同一個 id 續接,不依賴「continue 最近一個」的模糊語意。

    • agy:無法預指定 id,第一次跑完從 --output-format stream-jsonconversation_id 撈出來回傳;之後用 --conversation <id> 續接。

    • codex:第一次跑完從 thread.started 事件的 thread_id 撈出來回傳;之後用 codex exec resume <id> 續接。

    • copilot:server 自己產生 UUID → --session-id,第一次呼叫就把 id 回傳;之後帶同一個 id 續接。

  3. 零 shell 注入:四邊都 shell:false 直接 spawn,prompt 當作單一 argv 元素,任何 shell 特殊字元都不會被解讀。

  4. 保守的權限旗標

    • 預設允許讀寫檔案(符合使用者選擇),但寫入/危險能力仍分段控制。

    • pi 預設帶專案信任 -aapprove_project 才開)。

    • agy 預設--dangerously-skip-permissions;workspace 讀寫自動放行、shell 指令維持 gated,除非 dangerously_allow_all:true

    • codex 預設 sandbox 為 read-onlydanger-full-access 要明確指定)。

    • copilot 預設只帶 --allow-all-tools(非互動必要),--allow-all(含 paths + urls),後者要 dangerously_allow_all:true

  5. 稽核:每次呼叫寫一行 JSONL 到 logs/<pi|agy|codex|copilot>-YYYYMMDD.jsonl(prompt、session/thread id、exit code、耗時、usage)。

  6. 可用性登記表(避免對已知被限流的 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 installUNABLE_TO_GET_ISSUER_CERT_LOCALLYcertificate 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 install

Step 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 --versionpi --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 --versioncodex 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-bridgecopilot-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

參數

型別

預設

說明

prompt

string

要送給 pi 的指令(必填)

session_id

string

自動產生

帶上一次回傳的值即可續接同一對話

read_only

boolean

false

true 時只給 read,grep,find,ls,禁 edit/write/bash

model

string

覆寫 model

approve_project

boolean

false

是否信任專案本地資源(pi -a)

enable_extensions

boolean

false

是否載入 extensions(有掛住風險)

timeout_ms

number

300000

硬性逾時

回傳:pi 的最終文字 + 一行 pi-bridge metadata(含 session_id)。

ask_agy

參數

型別

預設

說明

prompt

string

要送給 agy 的指令(必填)

conversation_id

string

自動擷取

帶上一次回傳的值即可續接

model

string

model slug(見 agy models

effort

low|medium|high

推理強度

sandbox

boolean

false

開終端沙箱限制(--sandbox)

dangerously_allow_all

boolean

false

危險:自動批准所有工具權限(含 shell)

timeout_ms

number

300000

硬性逾時(同步作為 agy --print-timeout)

回傳:agy 的最終回應 + 一行 agy-bridge metadata(含 conversation_idstatus)。

ask_codex

參數

型別

預設

說明

prompt

string

要送給 Codex 的指令(必填)

session_id

string

自動產生

帶上一次回傳的 thread_id 即可續接

model

string

覆寫 model(如 o3codex-mini

sandbox

read-only|workspace-write|danger-full-access

read-only

沙箱策略

timeout_ms

number

300000

硬性逾時

回傳:Codex 的最終文字 + 一行 codex-bridge metadata(含 thread_idusage)。

ask_copilot

參數

型別

預設

說明

prompt

string

要送給 Copilot 的指令(必填)

session_id

string

自動產生

帶上一次回傳的值即可續接同一對話

model

string

覆寫 model(如 claude-haiku-4.5

effort

none|minimal|low|medium|high|xhigh|max

推理強度

max_ai_credits

number

單次呼叫的花費上限(安全閥)

dangerously_allow_all

boolean

false

危險:加 --allow-all(含 paths + urls)

timeout_ms

number

300000

硬性逾時

回傳:Copilot 的最終回應 + 一行 copilot-bridge metadata(含 session_idusagequota_snapshots)。

額度查詢限制:Copilot CLI 沒有非互動模式的指令能查詢「剩餘總額度」。copilot billing / copilot limits 只在互動模式的 UI 裡有用。bridge 只能回報「這次呼叫消耗多少」(usage + 當次 quotaSnapshots),無法回報剩餘總額度。Codex 同理,codex login status 只顯示登入狀態,無用量查詢。

環境變數

變數

預設

PI_BRIDGE_CWD / AGY_BRIDGE_CWD

C:/Cheerio/pi

PI_BRIDGE_ENTRY

pi 的 dist/cli.js 全域路徑

AGY_BRIDGE_ENTRY

agy.exe 路徑

PI_BRIDGE_TIMEOUT_MS / AGY_BRIDGE_TIMEOUT_MS

300000

CODEX_BRIDGE_CWD

C:/Cheerio

CODEX_BRIDGE_ENTRY

codex.exe 路徑

CODEX_BRIDGE_TIMEOUT_MS

300000

COPILOT_BRIDGE_CWD

C:/Cheerio

COPILOT_BRIDGE_ENTRY

copilot.cmd 路徑

COPILOT_BRIDGE_TIMEOUT_MS

300000

MCP_BRIDGE_LOG_DIR

<repo>/logs

BRIDGE_BYPASS_PROXY

true

BRIDGE_BYPASS_PROXY:bridge 預設會在呼叫底層 CLI 前 strip 掉子進程 env 裡的 HTTP_PROXY/HTTPS_PROXY/ALL_PROXY(含大小寫變體),避免子進程被父進程繼承到的企業 proxy 設定牽連。只有明確設成字串 "false" 時才關閉 strip 行為。