MCP 預載是 Token 刺客?從 Uber 萬人工程團隊看:如何靠「動態工具發現」與 Code-Mode 砍掉 70% 隱形成本
許多團隊以為 MCP 工具掛越多越好,但 Uber 實測發現:預載 100+ 個工具 Schema,一問話就吃掉 70,000 Token!本文深度拆解 Uber 如何用 MCP Gateway、Tool Search 動態目錄、Code-Mode 與 16 種反模式治理,在 Agent 請求暴增 9 倍下保持成本平穩。

當 Anthropic 推出 Model Context Protocol(MCP,模型上下文協定)後,全球開發者社群迅速掀起了一場「工具擴充狂潮」。
不論是在 Claude Code、Cursor、Windsurf,還是自建的 AI Agent 系統中,大家開始把各式各樣的 MCP Server 往裡面塞:從 GitHub、GitLab、PostgreSQL、Elasticsearch、Slack、Brave Search 到 Sentry。工程師們滿懷期待,以為賦予 Agent 越多的工具,AI 就能全知全能地幫團隊搞定所有端到端任務。
但現實很快給了所有人一記悶棍:「MCP 工具掛得越多,Agent 不僅反應越來越慢、回覆頻繁產生幻覺,月底的 API 帳單更是呈現指數級暴增。」
為什麼會這樣?
全球少數在萬人研發團隊規模下全面鋪開 Agent 的叫車巨頭 Uber,在 2026 年 8 月底發布的重磅工程文章《Running a Software Factory Efficiently at Uber Scale》中,揭露了一個令人觸目驚心的事實:
「在標準的 MCP 架構下,若環境安裝了超過 100 個工具,光是為了把所有工具的 JSON Schema 預載進對話環境,在工程師一句話都還沒輸入之前,就已經白白吃掉了 50,000 至 70,000 個 Token!」
更致命的是,這 70K Token 並非一次性費用。在傳統的多輪對話(Multi-turn Session)中,每推進一輪任務,這 70K 的「靜態工具行李」就要被重新打包發送給模型一次。
面對每週超過 30,000 次執行的 Agent Skills、以及全公司 1,000 多個內部與第三方工具,Uber 是如何把 AI 請求量拉升 9.4 倍 的同時,將單次 Session 成本大幅壓低 52%?
本文將為你深度拆解 Uber 軟體工廠(Software Factory)的核心防禦體系:MCP Gateway、動態工具發現(Tool Search)、Code-Mode 代碼執行模式,以及他們內部稽核出的 16 種 Agent 浪費反模式,讓中小團隊與個人開發者也能立刻學會如何避開 Token 刺客。
1. 痛點剖析:為什麼「預載 MCP」會成為毀滅預算的 Token 刺客?
要理解 Uber 的解法,首先要看懂標準 MCP 的運作機制到底哪裡出了問題。

1.1 JSON Schema 的「隱形重量」
當你啟動一個支援 MCP 的 Agent 時,客戶端會先向所有連線的 MCP Server 發出 tools/list 請求。每個工具為了讓大語言模型(LLM)精確理解何時調用、如何調用,必須附帶極為詳細的描述:
- 函數名稱(Function Name)
- 自然語言功能描述(Description)
- 每個輸入參數的型別(Type)、說明(Description)、是否必填(Required)
- 巢狀物件結構或 Enum 列舉選項
一個設計良好的生產級 API 工具(例如「查詢某筆訂單的退款歷史與金流紀錄」),其 JSON Schema 往往輕易突破 500~800 個 Token。 如果你掛載了 100 個工具,那就是 50,000 到 80,000 個 Token 的常駐負載。
1.2 上下文稀釋與「注意力腐爛(Attention Rot)」
除了花錢,更大的代價是模型變笨。 當 LLM 的上下文窗口塞滿了 7 萬個 Token 的各類工具說明,而你真正的 Prompt 只有一句:「幫我檢查這支 Go 服務為什麼在 high load 下會出現 connection pool timeout?」 時,有效資訊比率(Signal-to-Noise Ratio)被稀釋到了極致。
模型不僅容易「注意力渙散」,忽略你原本指示中的細節規範,甚至會開始產生工具幻覺(Tool Hallucination)——明明該讀本地代碼,卻莫名其妙去呼叫 Slack MCP 搜尋無關聊天紀錄。
2. Uber 的降本利器:MCP Gateway 與動態工具發現(Tool Search)
面對超過 1,000 個工具的龐大生態,Uber 沒有因噎廢食關閉 MCP,而是重新發明了工具的供給模式。
傳統預載模式(Token 刺客):
[LLM 啟動] ──一次性預載 1,000 個工具 Schema (70K+ Tokens)──> [對話每一輪反覆攜帶] 💸
Uber 軟體工廠模式(動態隨選):
[LLM 啟動] ──只給予一個 Tool Search 目錄(~300 Tokens)──>
[任務分析] ──Agent 搜尋 "Payment Database"──>
[動態載入] ──Gateway 僅注入 1 個查詢工具 Schema──> [執行完畢釋放] ⚡
2.1 打造統一的 MCP Gateway
Uber 將全公司散落在各部門的 1,000+ 工具(包含內部微服務、Jira、CI/CD 系統、資料庫查詢、第三方 API)收攏在一個統一的 MCP Gateway 後方。 這個 Gateway 扮演三個核心角色:
- 身份驗證與授權(AuthN/AuthZ):確保 Agent 只能存取該工程師具備權限的資料,阻擋非法的跨部門讀取。
- 敏感資料脫敏(PII Redaction):在任何工具回傳結果進入 LLM 上下文之前,自動模糊化使用者電話、地址、信用卡號等敏感資料。
- 介面統一抽象(CLI 投射):將所有 MCP 工具對外抽象成類似命令行(CLI)的形式,讓 Agent 能夠用標準指令的方式進行呼叫。
2.2 動態工具目錄:Tool Search
這是 Uber 節省 Token 最關鍵的設計。在 Uber 的軟體工廠裡,任何 Agent 在初始化時,禁止預先載入任何業務工具的完整 Schema。
Agent 一開始只會拿到一個極精簡的內建工具——search_tools:
{
"name": "search_tools",
"description": "根據關鍵字或任務目標,搜尋可用的工具目錄並取得其使用規範",
"parameters": {
"query": {"type": "string", "description": "任務關鍵字,例如:'mysql query', 'deploy canary', 'trace alert'"}
}
}
當工程師要求 Agent:「幫我查詢司機端接單逾時的排程作業紀錄」,Agent 的運作流程如下:
- 目錄檢索:Agent 呼叫
search_tools("driver dispatch timeout job")。 - 輕量回傳:MCP Gateway 透過向量檢索或關鍵字比對,僅回傳最相關的 2 個工具名稱與簡短摘要(耗費不到 200 Tokens)。
- 即時綁定(Just-in-Time Binding):Agent 確認需要使用
get_dispatch_metrics,此時系統才把該工具的詳細參數 Schema 注入當前回合。 - 即用即丟:任務處理完畢後,該工具 Schema 不會永久留在歷史對話中,避免在後續討論架構或寫代碼時持續佔用 Token。
光是這個「從全部預載改為動態搜尋」的架構重構,就讓 Uber 每個 Session 的開場 Token 浪費直接暴跌 90% 以上!
3. 第二大殺手鐧:用 Code-Mode 終結 Multi-turn 的對話輪次浪費
除了工具 Schema 本身,另一個巨大的 Token 黑洞是 Agent 調用工具的中間過程。

3.1 傳統 Chat-Mode 的死穴:確定性邏輯的無謂對話
在標準的 Agent 迴圈(ReAct Pattern)中,如果一個任務需要「查詢分頁資料、逐筆比對、重試失敗請求」:
- Turn 1:LLM 決定呼叫
fetch_logs(page=1)。 - Turn 2:收到 2,000 行 Log(進上下文),發現沒有目標,LLM 決定呼叫
fetch_logs(page=2)。 - Turn 3:又收到 2,000 行 Log,LLM 發現連線逾時,決定
sleep(5)後重試。 - Turn 4:重試成功,LLM 開始做文字過濾……
在這種模式下,每一次 API 呼叫、每一次輪詢等待、每一頁龐大的原始回傳值,通通都成了上下文裡的 Token。你付費給地表最強的推理模型,結果只是讓它在做迴圈、計數器與字串篩選!
3.2 Uber 的 Code-Mode:把確定性邏輯下放給腳本
Uber 大量引入了 Code-Mode(代碼執行模式)。 當任務涉及多步驟、批次處理或長流程時,Agent 的角色不是「自己充當執行引擎」,而是**「編寫一段微型 Python 或 Bash 腳本」**:
# Agent 在背景沙盒生成的 Code-Mode 腳本範例
import requests, json
def find_root_cause(service_name):
for page in range(1, 10):
res = requests.get(f"https://internal.gateway/logs?svc={service_name}&page={page}").json()
for entry in res['items']:
if "DEADLOCK_DETECTED" in entry['message']:
return entry['stack_trace'] # 只回傳關鍵出錯棧
return "Not found"
print(find_root_cause("order-service"))
- 腳本在安全的隔離沙盒中執行,分頁、重試、中間上萬行的 JSON 都在沙盒記憶體中處理,完全不經過 LLM。
- 最終只有被
print()出來的關鍵 15 行 Stack Trace 回傳給模型。 - 結果:原先需要 10 輪對話、累積 50,000 Tokens 的過程,在 Code-Mode 下只需 1 輪對話 + 300 Tokens 即可漂亮收官!
4. 終結亂搜:2,400 萬節點的「AI Context Graph」
很多時候,Agent 會狂呼工具、狂搜代碼,根本原因不是它程式寫得差,而是**「它不知道這家公司的東西到底放在哪裡」**。

當工程師詢問:「這支支付 API 的上游 schema 變更要通知哪個團隊?」
- 沒有上下文引導的 Agent:會在龐大的 Monorepo 裡使用
grep、翻找 Git Blame、爬取隨機 Markdown 文件,來回觸發幾十次工具呼叫,把上下文塞爆後依然無功而返。 - Uber 的 AI Context Graph:
- 將全公司超過 30 個內部系統(代碼庫、架構定義、Jira、維運警報、部署管線、Slack 討論頻道)串接成包含 2,400 萬個節點與 8,000 萬條關係 的企業知識網。
- Agent 透過圖譜查詢,能在一秒內看清:「服務 A」由「團隊 B」擁有、依賴「資料庫表 C」、最近一次由「工程師 D」部署。
這直接根治了 Agent「因為無知而四處盲目探路」所造成的海量工具浪費。
5. 實戰健檢:Uber 抓出的 16 種 Agent 浪費反模式(Anti-Patterns)
Uber 在其工程系統中建立了即時的 Session Dashboard,用來監控並攔截開發者在使用 Agent 過程中無意識犯下的浪費行為。以下是其中最具代表性的反模式,建議每個開發者與團隊對照自檢:
| 反模式名稱 | 典型特徵與危害 | Uber 的解決對策 |
|---|---|---|
| 1. 模型過配(Over-specced Model) | 用頂級推理模型(如 Claude Opus / GPT-4.5)處理簡單的代碼格式化、單元測試補全或文字翻譯。 | 依任務建立 Pareto 評測,預設將明確、有限範圍任務路由給輕量高性價比模型。 |
| 2. 工具輸出未截斷(Unbounded Tool Outputs) | 工具一口氣回傳數千行 log、整個 HTML DOM 或數十萬字未過濾 JSON,塞爆整個 Session。 | Gateway 強制限制工具回傳上限(如 4KB),超量時自動儲存為暫存檔,僅提供檢索切片。 |
| 3. 提示詞快取失效(Cache Invalidation) | 在 System Prompt 或前置對話中放置「動態時間戳記」或隨機 UUID,導致 LLM 的 Prompt Cache 每次都 Miss。 | 嚴格規範靜態內容置頂、動態輸入置底,保持 Prompt 結構穩定以最大化命中快取。 |
| 4. 幽靈全域規則(Zombie Global Instructions) | 開發者把幾千字、與當前專案毫無關聯的全域公司規範通通塞在通用設定裡,每輪對話都背著走。 | 模組化規則,透過專案根目錄的 .cursorrules 或專屬 Skill 依專案動態注入。 |
| 5. 遞迴子 Agent 失控(Runaway Sub-agents) | 主 Agent 在未獲取明確邊界的情況下,不斷派生子 Agent 去搜集資料,產生指數級放大的 API 請求。 | 限制子 Agent 最大派生深度(如最多 1 層)與總 Token 預算熔斷機制。 |
| 6. 盲目輪詢(Chat-based Polling) | 讓 LLM 每隔幾秒自己 call 工具檢查一次 Build 或 Deploy 是否完成。 | 改用背景異步事件回呼,或透過 Code-Mode 腳本在沙盒完成輪詢後再叫醒模型。 |
6. 中小團隊與個人開發者:立刻能用的 4 個落地指南
你可能沒有 Uber 數百人的基礎架構團隊,也造不起 2,400 萬節點的知識圖譜,但這套**「軟體工廠思維」**完全可以在你個人的開發環境中落地:
第一步:精簡你的 MCP 清單,啟用「按需加載」
檢查你的 claude_desktop_config.json 或 Cursor MCP 設定檔:
- 不要把所有 Server 全開:將低頻使用的工具(如特定資料庫管理、冷門 API)停用。
- 分環境隔離:為不同專案設定獨立的 MCP 設定檔,寫前端時不要載入後端維運工具。
- 善用社群新推出的動態 MCP 管理器或 CLI 模式,避免常駐開場吃掉數萬 Token。
第二步:利用 Code-Mode 技巧解決大量資料篩選
當你需要 Agent 排查大量日誌或分析大檔案時,不要對它說:「請幫我閱讀這個 50MB 的 access.log」。 你應該指示它:
「請寫一段 Python 腳本,用正則表達式篩選出該 log 中狀態碼為 500 的前 20 筆資料與對應路徑,並在終端機印出精簡摘要給我。」
這能瞬間把數百萬 Token 的讀取消耗,降至不到 500 Token 的代碼生成消耗。
第三步:保護你的 Prompt Cache(快取對齊)
- 靜態放前,動態放後:將系統人設、架構規範、代碼風格等「不會改變的長文本」放在 System Prompt 最頂端。
- 切勿在 System Prompt 裡塞入
{{current_timestamp}}:只要一秒不同,各大模型供應商(Anthropic、OpenAI、Google)的高額 Prompt Caching 折扣就會立刻失效!
第四步:建立開發者「即時體感」
Uber 的實踐證明:月底把帳單寄給工程師是毫無意義的,因為那時錢早就燒光了。 在你的開發終端機中,養成隨時留意 Session 消耗的習慣(例如 Claude Code 會在底部顯示當前 Session 的花費金額)。當一個對話累積花費超過 0.5 美元時,主動開啟新的 Session,而不是在一個陳舊且充滿雜訊的 Context 裡繼續硬聊。
7. 官方實務演講影片
想深入了解 Uber 軟體工廠的底層設計與現場架構演示,可以觀看 Uber 工程團隊在 AI Engineer 大會上的完整公開演講:
Uber 工程團隊在 AI Engineer 大會分享 Agentic SDLC 與 Software Factory 架構細節。影片來源:AI Engineer 官方 YouTube 頻道。
8. 常見問題(FAQ)
Q1:Uber 說的「70% PR Attributed to Agents」,代表工程師都不用寫代碼了嗎?
不是。 Uber 原文強調的是「可歸因於(Attributed)」。這代表在這些 PR 中,有本機 Agent 或背景系統 Agent 參與了代碼草擬、單元測試生成、代碼審查或 CI 失敗修復。每一道 PR 最終仍必須經過人類資深工程師的 Review 與驗收,軟體工程的核心瓶頸已經從「能不能寫出來」,變成了「該不該做這個功能與架構治理」。
Q2:我只用 Cursor 或 Claude Code,MCP 真的會吃掉那麼多 Token 嗎?
真的會。 你可以在終端機或開發者工具中檢查初次請求送出的 Payload。每個 MCP 工具的輸入參數、列舉說明都是完整的文字。當你的外掛越來越多,光是 System Context 就可能佔用幾萬 Token,這不僅讓你更快撞上 API 限額,更會顯著拉高每一次對話的延遲。
Q3:動態工具發現(Tool Search)會不會增加對話延遲?
剛好相反。 雖然多了一步輕量的目錄檢索(通常僅耗費幾百毫秒),但因為後續每一輪對話的 Payload 從 70K 銳減至幾千 Token,模型整體的首字回傳時間(TTFT)與生成速度反而顯著提升,整體端到端花費的時間通常比預載所有工具更快。
資料來源與延伸閱讀
- Uber Engineering Blog:《Running a Software Factory Efficiently at Uber Scale》
- Uber Engineering 官方 X 貼文:x.com/UberEng/status/2093444169037762840
- AI Engineer 2026 演講:《Agentic SDLC at Uber》