MCP vs CLI 到底誰比較省 Token?你可能看過兩種完全相反的答案:一派說 MCP 把整本工具說明書塞進 context,還沒開始工作就先燒掉幾萬 token;另一派則說 typed tools 能減少猜參數、重試與錯誤,最後反而更省。
這個痛點不是紙上談兵。2026 年 8 月 11 日的 mcptoon Show HN,截至 8 月 12 日已超過 60 points、共有 41 comments;同週一位 r/mcp 實作者自述,某個 186-tool GitLab 設定約有 168 kB JSON Schema,粗估約占 40K tokens。後者沒有附 tokenizer、原始 schema 與 client 版本,所以只能當需求訊號,不能改寫成「一台 MCP server 固定吃 40K」。
更關鍵的是,8 月 9 日出現一份 涵蓋 7 種 Agent scaffolding、5 個模型的公開研究(並非完整 7×5 全因子):它報告的結果沒有支持「MCP 天生比較貴」或「CLI 一定更省」,反而把焦點拉回包住模型的 Harness。不過 AlphaLab 檢查公開程式碼後也找到驗收污染與 credential 隔離缺口,因此本文會把數字當成待驗證的線索,不當成乾淨因果結論。接下來用一個六步 repository 任務,從零搭出更嚴格、可在自己 repo 重跑的 paired A/B Test。
先說結論:MCP vs CLI 比的不是招牌,而是整台機器
🧪 記憶把手:Context 負載=固定前綴+動態 schema/result/transcript+失敗重跑流量;帳單則按 provider 的 usage 欄位各自計價。
Cache read/write 可能改變費率,卻不會把已進入 request 的內容從 context 扣掉。這裡把 scaffold/harness 都當成包住模型、替它送 prompt、掛工具、跑 loop 的執行層。
- 不能直接下結論:論文報告的 13 組 paired MCP÷CLI 比值從 0.43× 到 29.06×,中位數 0.93×;公開 harness 又有隔離缺口,不能把它讀成固定 penalty。
- 先比完成,再比省:只計算便宜卻沒完成的 run,等於把「沒做完」誤當成節省。
- 一定要驗證工具路徑:把 MCP 接上不代表 Agent 真的用 MCP;一句「請用 MCP」也擋不住它偷走 shell、HTTP API 或其他 built-in tool。
- 先拆兩個軸:
model_surface是 typed tools 或 shell/CLI;backend_path才是 MCP、直接 API 或本機 process。若走 MCP,再另記mcp_transport是 stdio 或 Streamable HTTP。 - 最後通常是三選一:窄而成熟的任務偏 CLI;需要 typed inputs、動態 discovery 或跨服務整合時偏 MCP;工具很多但每次只用少數時,偏向 lazy/compressed MCP。

MCP vs CLI 差在哪?先把兩條路畫清楚
先把模型想成一位坐在工作桌前的工程師。MCP 像每項工具都附上有型別的操作卡:名稱、用途、參數與 JSON Schema 都寫清楚,模型可以發出結構化呼叫。CLI 則像只給它一個 shell,再告訴它 git、gh、rg、jq 已安裝;模型靠訓練時學過的命令與 --help 完成工作。
兩者都不是「零工具說明」。CLI 仍要帶 shell 與檔案工具的 schema,MCP 也不必然把每個遠端工具全文塞給模型。最新版 MCP 2026-07-28 Tools 規格明確寫道:實作可以自行決定如何把工具呈現給使用者與模型;tools/list 也支援 pagination 與 caching。換句話說,「全部 schema 每回合重送」是某些 client 的 delivery choice,不是協定強迫的唯一做法。
這也是為什麼問題不能只寫成「MCP vs CLI」。同一個 MCP server,可以被 client eager-load 44 個 schema,也可以先給一個搜尋/gateway tool,需要時才展開 1 個完整 schema;同一個 CLI,也可能先用 jq 把 20 筆 issue 壓成三個欄位,或把整包 JSON 原封不動塞回 context。介面是入口,Harness 才決定行李怎麼打包。
公平實驗因此要把兩個軸分開:model_surface 記錄模型看到 native typed tools 還是 shell/CLI;backend_path 記錄背後走 MCP、直接 API 還是本機 process。若路徑是 MCP,再記 mcp_transport 為 stdio 或 Streamable HTTP。mcptoon 雖讓模型輸入 CLI,但它的 discovery 與 call 流程分別仍透過 MCP initialize/tools/list/tools/call,且固定使用 2024-11-05 handshake;這證明 surface 與 backend path 是兩個軸,不代表它已支援全部 2026-07-28 server。
本文的主實驗會固定同一個持久 broker、MCP server、connection lifecycle 與 canonical result payload:A arm 把能力暴露成 native typed tools;B arm 只給 shell,透過自製 repoctl CLI façade 呼叫同一個 broker。第一輪不做 TOON、欄位裁切或重新包裝,只估模型表面差。之後才加做「CLI full vs filtered」與「MCP eager vs progressive discovery」,把 projection、schema delivery 與 bundled-client overhead 分開。
Harness Tax 的 4 筆帳:你到底在付什麼?
① 固定前綴:Agent 每次出門都背的背包
System prompt、developer instructions、permission policy、built-in tools、skills 索引與 scaffold 控制語句,常在第一個使用者字出現前就已存在。請保存每個 serialized component 的原文、bytes、token count 與 SHA-256。第一個 request 的 total input 還含 user task 與 wrapper;最多只能當 upper-bound baseline,或先減掉兩邊以同一 tokenizer 計算的相同 task payload。
② 工具目錄:一次載入,還是每回合重送?
MCP tool definition 通常包含名稱、description 與 input schema。成本不只看工具數,還要看每一個 model request 實際帶了多少 schema、多少 bytes、估算多少 tokens。如果 client 支援 lazy discovery,另外記錄何時從名稱索引展開完整定義。只看 server 有幾個工具,仍不知道模型看見了多少。
③ Transcript 與結果:工具回來的貨,也要塞進車廂
工具輸出可能比 schema 更肥。CLI 的 --json 結果若沒先經 jq 投影,一樣會灌滿 context;MCP typed result 若由執行環境先 filter、join、aggregate,只把必要欄位交給模型,也可以很省。Anthropic 的 Code execution with MCP 就示範了按需讀取 tool definition、在執行環境過濾資料,再只把小結果送回模型的做法。
④ 失敗與重試:沒完成的 run 也會留下帳單
Agent 猜錯參數、走錯工具、卡在 permission、重複讀檔,甚至自稱完成但 repository 沒變,都已經消耗 token。最實用的總指標不是「最低單次 token」,而是每次通過驗收的成本:全部 run 花費 ÷ 通過 run 數。再另外報告 failure cost share:失敗 run 花費 ÷ 全部花費。
新研究真正發現什麼?先讀懂 4 個數字
這份研究用一個 private GitHub repository 任務,讓實際採用的 27 種 scaffold/model 組合執行六個操作。MCP arm 使用 44 個 GitHub MCP tools,CLI arm 使用 shell、git 與 gh。研究公開了 v1.0.0 measurement harness 與逐 run dataset。最重要的不是抓一個倍數當標題,而是看懂哪些只是觀察、哪些仍混著其他變因。
⚠️ AlphaLab 程式碼複核:公開 reset 只關閉 open PR,但 verifier 會抓全部歷史 PR,而 pr_opened 只檢查清單是否非空;舊 PR 因此可能替新 run 得分。另一邊,MCP arm 的 Agent process 仍繼承 GitHub PAT,部分完成列又大量使用 shell/curl。所以下列都是論文報告值,不是純介面效果;尤其 29.06× outlier 不能叫作「純 MCP 路徑」。

- Scaffolding 差異很大:論文報告的 completed-run scaffold medians 從 14,660 到 288,808 input tokens,約 20×;但模型組合與 scaffold 功能並不相同,這是 observed spread,不是 Harness Tax 的因果估計。
- 介面方向不穩:13 組同 scaffolding、同模型且兩邊都完成的 paired ratio,MCP÷CLI 從 0.434× 到 29.056×,中位數 0.934×。加上實際路徑污染後,最安全的讀法是「目前證據不足以給介面一個固定 penalty」。
- 失敗次數相同,失敗價格不同:主矩陣兩邊都完成 16/19,重複資料也都完成 25/29;論文模型化成本中,失敗花費占比是 MCP 12.9%、CLI 2.2%。這是尾端成本線索,不是 MCP 必然較危險的證明。
- Delivery method 是候選機制:Hermes 每輪共帶 7 個 model-facing schema(含 2 個 gateway);其餘四個 eager clients 每輪帶完整 44 個 GitHub MCP schema,另加各自 built-ins。論文分組後報 70,836 vs 216,986(約 3.1×),但只有 Hermes on-demand,模型、scaffold 與可觀測路徑也不同,不能歸因於 delivery。
- 單次實測很吵:重複 local configuration 時,典型最大值÷最小值為 1.51×,最寬到 5.41×。單憑一次 20% 差異,無法與這份研究觀察到的 run-to-run variation 區分。
研究最大的限制仍是只有一種 software task,而且 GitHub 已有成熟的 gh CLI;主矩陣的 hosted cells 多數只跑一次,也沒有正式信賴區間、power analysis 或隨機化 arm 順序。它最有價值的地方,是提醒我們不能只看介面標籤;它還不能替 database、browser、SaaS 或內部 API 做結論。
自己做 MCP vs CLI A/B Test:固定一個六步任務
如果你已讀過 AlphaLab 的 Claude Code Token A/B Test,上一篇教的是「同 repo、同 commit、一次只換一個壓縮工具」;這一篇多加兩個更嚴格的鎖:同一個 Agent harness,以及實際 tool path 必須符合 arm。

Step 1|先寫完成條件,再寫 prompt
在可丟棄的 fixture repo 放一個真實但範圍小的 bug,要求 Agent:① 重現指定 failing test;② 找到責任實作;③ 用一句話說明 root cause;④ 做最小修補;⑤ 加 regression test;⑥ 執行固定驗證命令並回報 changed files。不要拿 production repo 當實驗場,也不要直接把 patch 送給模型。
驗收器不讀 Agent 的「我完成了」,而是在 run 結束後獨立執行:public_test_exit == 0、hidden_test_exit == 0、patch_scope_ok、no_test_weakening、forbidden_route_calls == 0。若任務包含 PR,還要核對本輪開始時間後建立的唯一 PR、預期 head SHA 與 branch;「歷史上有任何 PR」絕對不算完成。
Step 2|凍結 Harness manifest
每次 run 都保存一份 manifest.json,至少包含:model ID/revision、reasoning effort、temperature、system prompt、MCP server commit、CLI 版本、起始 commit、cache policy、max turns、timeout 與預算上限。共享欄位必須完全相同;只有事先登記的 model_surface 與因此必然不同的 model-facing tools 可變,並把兩邊 tool definitions 的原文與 hash 都留存。出現其他差異,這一對就不算 paired run。
Step 3|固定後端,只切換模型表面
A|native MCP:模型看見 read/write/patch/test 等 allowlisted operations 的 typed equivalents 與完整 schema。B|CLI façade:模型只看見 shell 與自製 repoctl。兩邊打到同一個 long-lived broker/session;broker 先依 canonical operation manifest 執行,再產生並 hash canonical result,最後才由兩個 presentation adapter 包裝。除 serialization 與 tool-call syntax 外,payload/error semantics、排序、截斷、limits、timeout 與 connection lifecycle 必須一致。
隔離要放在真正的 security boundary:credential 由 Agent sandbox 外、不同 OS user 或 container 的 broker/sidecar 持有;Agent 只能走 allowlisted IPC,不能讀 broker env/cmdline/config,也沒有直連 backend 的 egress。Native arm 移除 CLI、直接 HTTP/API 與檔案後門;CLI arm 移除 native tools。每個 event 都寫入 requested surface、executed backend path 與 MCP transport。只刪 GH_TOKEN,卻把另一個 PAT 留在 Agent environment,門仍沒鎖。
論文前期 21 個 MCP-connected runs 中,6 個只用 MCP、6 個只走 shell、6 個混用、3 個沒叫工具;論文另註記其中有 4 個繞過兩種指定介面、直接打 Web API,但沒有交代這 4 個與前述分類如何重疊。白話說:prompt 只能請參賽者走左門,sandbox、broker 與 backend audit log 才能證明右門真的鎖上。
Step 4|把每個 request 寫成 JSONL
保存的是Harness 組裝後、真正送進模型的 request,不只是 MCP server 回傳的 tools/list。每輪至少記:pair/arm、model snapshot、system 與 tools 原文及 hash、provider usage、schema/result bytes、cache read/write、tool event、retry、latency;run 結束再加 hidden grader、route violation 與實際成本。只有 hash 不夠稽核,原文也要留在私有 artifact。
{"pair_id":"bug-07-r03",
"arm":{"model_surface":"native_typed","backend_path":"mcp",
"mcp_transport":"stdio","discovery":"full"},
"request_index":4,"input_tokens":18420,"output_tokens":612,
"cache_read_tokens":12600,"cache_write_tokens":0,
"schema_count":7,"schema_bytes":9310,"result_bytes":842,
"tool_event":{"operation":"repo.patch","executed_path":"mcp","retry":0},
"route_violations":0,"completed":null}
上面只是欄位示意,不是論文資料。MCP 與 CLI 要經過同一個計數 proxy,連 subagent request、CLI --help、stdout/stderr 與 retry 都歸檔;但原始 I/O 另記 bytes,只有實際注入後續 model request 的片段才算 input tokens,provider retry 也以 provider usage/invoice 為準。只讀 parent session usage,會讓會分派子代理的 scaffold 虛假地便宜;wc -c 永遠只能叫 bytes。
Step 5|每次重設 repo,交錯執行兩個 arm
每個 run 從同一 immutable SHA 建 fresh worktree;remote/API 狀態則使用唯一 run_id fixture,或先後驗證 issue/branch/PR reset,grader 必須配對 run_id、created_at 與 head SHA。Cold runs 使用隔離 cache namespace;warm runs 先讓各 arm 以自己的相同 prefix 預熱。若 cache 無法控制,就只報 observed fields,把 state 當 measured covariate。3~5 pairs 只能除錯;正式 N 應由 pilot paired variance、預先定義的 minimum meaningful effect 與 CI width/power 決定。只重跑同一 fixture,CI 只適用該 task 的隨機重複;要泛化就抽樣多個 tasks,並按 task/cluster bootstrap。
for task in frozen_tasks:
for replicate in range(N):
for arm in randomized(["native_mcp", "cli_facade"]):
repo = fresh_worktree(task.base_sha)
harness = frozen_harness.with_adapter(arm)
recorder.capture_exact_model_requests = True
outcome = harness.run(task.prompt, repo)
route_ok = broker.audit(arm, outcome.tool_events)
grade = hidden_grader(repo, task)
save(outcome, route_ok, grade)
這是 framework-agnostic pseudocode:把 with_adapter() 換成你 Agent 的 tool registry;broker.audit() 查 backend 事件,而不是相信 transcript;hidden_grader() 則要在 Agent session 結束後、沒有模型參與的程序裡執行。
Step 6|先看成功率,再算 Token 與錢
- Completion rate:
通過全部 checks 的 runs ÷ attempted runs。 - Tokens per verified completion:
全部 attempted-run token usage ÷ verified completions;另報單一 request 最大 input/context tokens。若 provider 把 cache read 視為 input 子集,不要再加總一次。 - Cost per verified completion:
全部 runs 成本 ÷ 完成 runs,把 retry 與 failure 一起算進真正產能。 - Failure cost share:
失敗 runs 成本 ÷ 全部成本。 - Path adherence:主分析按原始 arm 分派保留每次 attempted run;route violation 視為未通過,成本仍留在分母。可另做 adherent-only sensitivity analysis,但不能取代主結果。
兩邊都通過驗收的 pair,才計算 paired surface delta = cost(native MCP) − cost(CLI façade);所有 assigned-arm 失敗與成本仍另報。Route violation 預先定義為 apparatus failure,主表用 intention-to-treat 保留,再加 per-protocol sensitivity。若要找機制,再做 CLI full vs filtered/TOON 與 MCP eager vs progressive discovery;不要把 projection 或 delivery 節省倒灌成「CLI 天生勝出」。
想把觀測補齊,可延伸讀 Agent Observability;想先理解 loop、tools 與 stop condition,先補 AI Agent Harness 心智模型,再看 最小 Harness 實作。
MCP vs CLI 怎麼選?其實還有第三條路

選 typed MCP,如果「不猜參數」比省幾行說明更重要
新 API、內部服務、會寫入外部狀態的動作,typed input、可選的 output schema、由 server/host 強制執行的授權與確認政策,以及可發現性很有價值。尤其模型不熟悉自家 CLI 時,明確 schema 可能減少錯參數與 retry。這時要優化的是 tool design:工具窄、描述清楚、結果小,而不是為了省 token 把型別全部拆掉。
選 CLI,如果任務窄、命令成熟,而且輸出很好裁
git、gh、rg、jq 這類成熟工具,模型通常能用短命令完成,而且 shell 可以在結果進 context 前先 filter。已知、重複、可用 deterministic script 驗收的 pipeline,CLI 常是最小可用介面。代價是你要自己管理 quoting、exit code、credential 與 sandbox。
選 lazy/compressed MCP,如果工具很多、每次只會用少數
這條路保留 MCP protocol path、server 原有的授權機制與 typed tools,但只先露出名稱索引或 search_tools,命中後才展開完整 schema;結果再交給 code execution 或本機 filter。這也符合目前的 MCP client progressive-discovery 指引。注意:那份官方頁面的 token 圖是機制示意,不是控制 benchmark。
mcptoon 是好用的「兩軸」示例,但不適合直接充當 surface-only 主 arm。它公開的 97% discovery、40–60% result savings 是作者 microbenchmark,不是 task-level Agent A/B。截至 2026 年 8 月 12 日,PyPI 最新版是 0.2.1;GitHub main 的 pyproject/README/CHANGELOG 已是 0.2.2,source 固定 MCP 2024-11-05。TOON 預設把結構中的 string scalar 截到 200 字元、整體上限 4,000 字元,不能稱為無損;usage token 目前也未由 call path 填入。即使用 --json --full,它仍會抽取/重包內容、套用 guard 並管理自己的連線生命週期,不等於 raw MCP semantics。只有通過 canonical-payload equivalence test 才能當 paired arm;否則另列 bundled-client arm。
若你的重點是 MCP transport 本身如何跨無狀態部署,可接著讀 Stateless MCP 教學;若你想整理「哪些內容應該進 context」,則看 Context Engineering。
MCP vs CLI 實驗最常踩的 6 個坑
- 連 Harness 一起換:用 A 產品測 MCP、B 產品測 CLI,得到的是產品差,不是介面差;CLI façade 的後端也可能仍走 MCP,務必分開記 surface、backend path 與 MCP transport。
- 只在 prompt 指定介面:Agent 有別條路就可能偷走;一定要移除 config、credential 或 network route,再查 tool register。
- 相信 final answer:「已完成」不是驗收。用 repository state、測試、API 或資料庫查詢做外部 grader。
- 只留下成功 runs:昂貴失敗被刪掉後,最不穩定的 arm 會看起來最省。
- 把 cached tokens 當免費:cache 會改變帳單,但 token 仍可能占 context,provider 的折扣規則也不相同;raw input、cached input 與實付成本要分欄。
- 只跑一次:Agent 具有隨機性,服務延遲與 cache 也會漂;報 paired repetitions、median、range,再判斷差異是否大到值得改架構。
常見問題(FAQ)
Q1:MCP 天生比 CLI 貴嗎?
不一定。目前公開研究報告的 paired ratios 方向不穩,且其 harness 有路徑與驗收缺口;MCP client 如何載入 schema、任務跑幾輪、結果是否先過濾,都會改變答案。
Q2:那 CLI 一定比較省 Token 嗎?
也不一定。CLI 若讓 Agent 一直查 --help、猜參數、重試,或把巨大 JSON 原樣回填,可能比一個窄而清楚的 typed tool 更貴。
Q3:單一 MCP server 真的會占 40K context tokens?
某些組合可能,但 40K 不是協定常數。那個數字來自一位實作者對 186 tools、約 168 kB JSON Schema 的自述估算;server 大小、client 呈現方式與 tokenizer 改變,結果就會變。
Q4:MCP 規格要求 client 把全部 schema 放進每個 request 嗎?
不是這樣規定。規格定義 tools/list/tools/call 與 tool schema,也允許 client 自行決定互動呈現;2026-07-28 版還明列 listing 的 pagination 與 caching。
Q5:Prompt cache 會把 Harness Tax 全部消掉嗎?
不會。它可能降低重複前綴的計費,但結果、未命中的 prefix、重試與 context 容量仍存在。實驗要同時保存 raw input、cached input 與實付成本。
Q6:怎麼確認 Agent 沒有偷換工具?
用兩層證據。第一層讓 Agent process 根本拿不到另一條路的 credential/config/network access;第二層由 backend 記錄每個 tool、shell command 與 outbound request。只看 prompt 或 transcript 不夠。
Q7:最該盯的單一指標是什麼?
Cost per verified completion。它把「有沒有真的完成」放回分母,也不會讓失敗與 retry 消失;再配 failure cost share,才能看出尾端風險。
Q8:什麼時候值得改成 lazy/compressed MCP?
工具很多、實際使用稀疏、schema 或結果已成為可觀測瓶頸時。先從 log 證明 fixed schema bytes 與 result bytes 確實占大頭,再改 discovery;不要只因網路上一個百分比就重寫整套 client。
給新手的 5 個重點
- MCP vs CLI 是介面比較;Harness Tax 才是完整成本問題。
- 同模型還不夠,system prompt、built-in tools、cache、starting state 與 stop rule 都要固定。
- 先用外部 grader 驗收,再比較 tokens、cost、retries。
- 隔離實際路徑並記錄 tool register,否則你量到的是未知混合物。
- typed MCP、CLI 與 lazy MCP 可以共存;依任務選最小但足夠可靠的介面。
想把這套方法放進自己的 Agent 專案,可以從 AlphaLab AI 課程補齊 prompt、tools、eval 與 automation 的實作脈絡;也可回到 AI 專區,依序讀完 Harness、Context Engineering 與 Observability。
接著閱讀
左右滑動查看更多推薦
結語:先秤背包,再爭哪條路比較短
「MCP 還是 CLI?」像在問兩條路哪條省油,卻沒先看車重、塞了多少貨、繞了幾圈、失敗後重跑幾次。真正可攜的答案不是固定倍數,而是分清兩本帳:Context 負載包含固定前綴、動態 schema/result/transcript 與重跑流量;帳單再依 provider 對 uncached input、cache read/write、output/reasoning 的費率計算。
今天就選一個可重設的測試 repo,寫下五個 machine checks,保存 system/tool schema 原文與 hash,跑第一對隔離的 native MCP/CLI façade sessions。只要你能證明「兩邊真的做了同一件事、真的走了指定路、真的完成」,下一個 token 數字才值得相信。






