title: "MCP Token Cost:我把我的 MCP 伺服器從 15 個工具縮減到 4 個"
published: true
description: 我把一個真實的 AWS 成本排查 MCP 伺服器從 15 個工具重建成 4 個。相同帳號、相同問題,工具呼叫從 7 次降到 2 次,schema 縮小 88%。
tags: mcp, aws, ai, discuss

這是一個你應該在意的數字。GitHub 官方的 MCP 伺服器,在你還沒問任何問題之前,就會先載入約 55,000 個 token、涵蓋 93 個工具定義。在 200K 的上下文視窗裡,這已經超過你配額的四分之一,而且這些 token 是在代理開始做事之前就先花掉的。

我一開始也不信,直到我自己量過之後。於是我照著大多數人的做法,做了一個小型 AWS MCP 伺服器,把它接到 Kiro,然後只問了一個問題:「這個帳號裡,我在哪裡在浪費錢?」它用了 7 次工具呼叫 才回答。接著我完全依照 AWS 自己的工具設計手冊,把同一個伺服器重建了一次。相同帳號、相同問題。2 次工具呼叫。 15 個工具變成 4 個。工具 schema 縮小了 88%。

這就是那次重建的故事,所有數字都直接攤在眼前。這是一篇實際拆解 MCP token 成本的文章:它從哪裡來、怎麼量、又該怎麼砍。不是那種只有 add_numbers 工具的 hello world 伺服器,而是一個只讀的 AWS 成本排查伺服器,能找出真實的浪費支出,而且同一個 repo 裡放了兩個版本。

完整程式碼都在 GitHub 上,兩個伺服器放在同一處,方便你比較差異:

https://github.com/simplynadaf/aws-lean-mcp

這篇文章適合誰

你已經在 Kiro、Claude Code 或 Cursor 裡接過幾個 MCP 伺服器了。也許你自己做過一個。Demo 時它運作得很好,結果當你加進更多工具後,代理開始變慢、變笨,也變貴。你看過「context bloat(上下文膨脹)」這個詞,想知道它是不是真的、到底有多糟,以及該怎麼處理。

如果你看得懂 Python 函式和 JSON 檔案,就能跟上。

目錄

  1. MCP 伺服器把你的代理拖垮的兩種方式
  2. 故意做成反模式的版本(v1:15 個工具)
  3. 逐步重建:一步步修正(v2:4 個工具)
  4. 成效總表:哪些地方變了
  5. 關於 context meter 的誠實說法
  6. 連 AWS 自己也把工具列表維持得很小
  7. 你也可以自己試試看
  8. 部落格文章沒告訴你的事

1. MCP 伺服器把你的代理拖垮的兩種方式

AWS 在 2026 年 7 月發表了一篇最清楚的拆解文章,標題是 MCP 工具設計:實務做法與取捨。它指出了兩種失敗模式,而且這兩者會互相助長。

膨脹。 每一個工具定義,不管模型有沒有用到,都會在每次呼叫時載入到上下文視窗裡。每個工具 schema 大約占 550 到 1,400 個 token,所以 50 個工具在真正開始工作前,就可能吃掉 30,000 到 70,000 個 token 的定義。一般 Claude Code 工作階段如果裝了 5 到 10 個 MCP 伺服器,在你輸入第一個提示之前就先燒掉 50,000 到 67,000 個 token。你每一輪都在付這筆稅。

混淆。 隨著上下文越來越滿,你的工具名稱又開始長得很像(describe_volumes、describe_addresses、describe_snapshots,都很薄、都很相似),模型就可能選錯工具、傳錯參數、拿到空結果,然後重試。每次重試都會再增加更多 token。膨脹導致混淆,混淆又造成更多膨脹。形成惡性循環。

這兩者的根本原因,就是大家最常用的 MCP 伺服器建置方式:拿一個 API,把每個 endpoint 各自包成一個工具,然後一次丟出 30 個。看起來很完整,其實是陷阱。


2. 故意做成反模式的版本(v1:15 個工具)

要修東西,得先有壞掉的東西。所以 server_v1_bloated.py 就是照著大多數人實際會怎麼上線的方式來做的。15 個工具,每個都只是對一個 boto3 呼叫做很薄的一對一包裝。

@mcp.tool()
def describe_volumes() -> dict:
    """Describe Amazon EBS volumes in the account for the configured region.

    This tool calls the EC2 DescribeVolumes API and returns the complete
    response payload for every EBS volume it can see. Use this tool when you
    need to inspect block storage devices, their attachment state, size in
    GiB, volume type (gp2, gp3, io1, io2, st1, sc1, standard), encryption
    status, IOPS, throughput, the Availability Zone, creation timestamp, and
    the list of tags. A volume whose State field is 'available' is not
    attached to any instance and may be wasted spend...
    """
    return ec2.describe_volumes(Filters=_DEMO_FILTER)

這段 docstring 在這裡為了篇幅有刪減。原始 repo 裡更長,而這正是重點。注意裡面已經埋了三個問題:

  • docstring 很長,而且每次呼叫都會載入到上下文中,不管有沒有用到。
  • 它回傳完整的 40 欄位 boto3 blob。這就是 response bloat:代理拿到一堆永遠不會讀的欄位。
  • 要回答「我在哪裡在浪費錢?」這個問題,代理必須自己知道要先呼叫 describe_volumes,再呼叫 describe_addresses,接著是 describe_snapshots,然後檢查 load balancer,最後自己把所有結果串起來。

我在 Kiro 裡對這個臃腫版本問同一個問題時,它做了 7 次 成本排查工具呼叫:get_caller_identity、describe_volumes、describe_addresses、describe_snapshots、describe_instances、describe_nat_gateways、describe_load_balancers。它一次一個呼叫地東找西找,最後把答案拼起來。確實找到了答案,但過程並不好看。


3. 逐步重建:一步步修正(v2:4 個工具)

server_v2_lean.py 具備完全相同的能力。相同的只讀檢查、相同的帳號、相同的發現結果。它採用 AWS 的那套做法,而且每一階都對應一個明確的修正。

修正 1:以成果為導向的工具。 不再是 15 個薄薄的 wrapper,而是 4 個工具,每一個都能完成一整個商業動作。最核心的那個:

@mcp.tool()
def find_waste(scope: Literal["account", "region", "service"] = "account",
               detail: bool = False) -> dict:
    """一次找出 AWS 的浪費支出。每個發現回傳 5 個決策欄位
    (id、kind、size/ip、why、region)。若要完整內容,設 `detail=True`。
    """

「我在哪裡在浪費錢?」現在只要一個呼叫,不是七個。這個工具會在內部執行所有檢查,然後直接回傳發現結果。

修正 2:schema 限制。 scope 參數是 Literal["account", "region", "service"],不是自由輸入文字。模型不會傳進亂七八糟的值,也不需要猜。AWS Prescriptive Guidance 建議工具參數大約控制在 8 個以內。這裡每個工具都只有兩個參數。

修正 3:精簡回應。 預設情況下,find_waste 只會回傳每個發現中 5 個與決策相關的欄位,而不是完整 blob。如果代理真的需要全部內容,就傳 detail=True。Anthropic 在 MCP 的程式執行指引裡也強調同樣的觀念:在工具結果送進模型之前先過濾、縮小,讓代理讀 5 筆資料,而不是 10,000 筆。

if not detail:
    keep = ("id", "kind", "size_gib", "public_ip", "why", "region", "source_volume")
    findings = [{k: v for k, v in f.items() if k in keep} for f in findings]

修正 4:延遲載入的分類資訊。 不再把所有合法值都硬寫進每個工具說明裡,而是提供一個小型的 describe_scope() 工具,只有在代理需要確認輸入時才呼叫。Anthropic 的 Tool Search 方法表示,只有在相關時才載入定義,最多可減少 85% 的 token。

修正 5:真正可理解的錯誤。 如果 scope 不合法,會回傳 "scope must be one of: account, region, service",而不是 "no results"。模型可以從前者修正過來,後者只會讓它陷入重試迴圈。

當我對精簡版問同一個問題時,它先呼叫 find_waste 一次,接著再呼叫 estimate_savings 來估算金額。2 次呼叫。 很乾淨。


4. 成效總表:哪些地方變了

同樣是只讀代理、同樣的問題、同一個 us-east-1 的真實 AWS 帳號。這裡的每個數字都來自實際執行,而且是現場錄製的。

指標 v1 臃腫版 v2 精簡版 差異
暴露的工具數 15 4 -73%
工具說明大小(字元數,作為 schema token 的代理指標) 7,898 897 -88%
回答該問題所需的工具呼叫次數 7 2 -71%
實際引用的發現專案 3 個 ID 同樣 3 個 完全相同
來自真實 Price List API 的金額 是 是 完全相同
有嘗試任何變更操作? 否 否 全程只讀

兩個版本都找到了相同的浪費支出,而且引用了相同的資源 ID:

  • vol-0c85bd44ef6f9c19d:一個未掛載的 8 GiB gp2 volume,每月約 $0.80。
  • snap-0e8e4ff717cead51e:一個孤兒 8 GiB snapshot,每月約 $0.40。
  • eipalloc-000992c9956cfaaa5:一個未關聯的 Elastic IP。代理無法從定價工具取得可驗證的費率,所以把影響標成「未驗證」,而不是亂猜。我是刻意這樣設計的,因為我希望它能誠實拒絕。

一個以成果為導向的工具,就做到了臃腫版本要用 7 次、猜來猜去才做完的事。

順帶一提,這些 schema 字元到底等於多少美元。v1 的 7,898 個字元,大約是 2,000 個輸入 token,而且每一輪都會載入。精簡版的 897 個字元,大約是 225 個 token。以 Claude Sonnet 每百萬輸入 token 3 美元計算,單次差距其實很小,只是幾分之一美分。它之所以重要,是因為它會乘上去:每一輪、每個代理、每位開發者,再乘上生產環境裡 90 多個工具,而不是 15 個。Demo 規模下只是四捨五入誤差,團隊規模下就會變成正式成本專案。


5. 關於 context meter 的誠實說法

這裡我得老實跟你說,因為大多數談這個主題的文章都不夠誠實。

在我的小型 demo 裡,Kiro 的 /context 工具預算只從 1.1% 變成 0.8%。這是真的,但幅度很小。15 個小工具相較於 200K 視窗還是很小,而共享的定價服務在兩個代理裡都一樣佔了大宗。

所以我不會硬把一個「72% 降到 8%」的震撼數字放上來,假裝那就是我的 demo。真正有拍到、而且現場錄下來的,是表格裡那些數字:7 次呼叫降到 2 次、15 個工具降到 4 個、schema 縮小 88%。

那些大的 context 數字(GitHub 伺服器的 55,000 token、在代理做出第一個動作前就吃掉 72% 上下文)是站得住腳的,但它們是以生產規模呈現的產業資料,這一點標示得很清楚。重點在方向:一個能在 15 個工具上省下 0.3% 的設計原則,在生產環境 90 多個工具上就能省下 20% 以上。你不會想等到上線後才發現這件事。


6. 連 AWS 自己也把工具列表維持得很小

最有力的證明不是我。AWS 自己託管的 AWS MCP Server,對整個 AWS 只暴露大約 8 個工具,而且在 2026 年 7 月,它還把 call_aws 工具淘汰,改成單一的 run_script 工具,讓介面再縮小一點。它的文件直接寫得很明白:「不要在 prompt 裡特別提到某個工具名稱,讓你的代理自己選擇適合的工具。」

精簡、以成果為導向的介面,加上按需載入的上下文,這不是我發明的技巧。這本來就是 AWS 在打造自家旗艦伺服器時的做法。這個 repo 只是讓你能自己證明這件事。


7. 你也可以自己試試看

全部都在 repo 裡,兩個伺服器並排放著。

git clone https://github.com/simplynadaf/aws-lean-mcp.git
cd aws-lean-mcp

不用代理也能先證明差異:

python3 scripts/smoke_test.py
# 15 -> 4 tools, 897 vs 7898 description chars (88% fewer), real IDs from both servers

接著把兩個版本各自接到 Kiro,用相同的 prompt 在兩邊跑一次 A/B 測試。repo 裡有代理用的 JSON 和只讀 IAM 指引。整個流程都是只讀:伺服器只會呼叫 Describe、Get 和 List。程式碼裡沒有任何寫入操作。

如果你想要有東西可以排查,scripts/create-demo-resources.sh 會建立幾個便宜、標籤清楚、刻意設成浪費的資源,而清除腳本會把它們 100% 刪除。


8. 部落格文章沒告訴你的事

這三件事,是我親自做完才學到的。

docstring 就是 schema。 在 FastMCP 裡,你的 Python docstring 和型別註記會變成模型看到的工具定義。所以你在寫每個工具時,其實都在程式碼層級做「臃腫 vs 精簡」的選擇。三段式的 docstring,等於每次呼叫都會載入三段文字。

把工具拆開,schema 反而可能更小,不一定更大。 這聽起來有點反直覺。但把合法值從冗長的描述裡抽出來,改成一個按需載入的獨立 describe_scope() 工具,會讓每一輪送進去的內容變少。永遠載入的 token 更少,代價只是當資訊真的需要時,多一次往返。

回應膨脹才是問題的一半,而且幾乎沒人談。 大家都在數工具定義,卻幾乎沒人在算工具回傳的肥大 JSON。預設回傳 5 個欄位,而不是 50 個,這是最便宜、最划算的優化,而且每次呼叫都會疊加。

你不需要更多 MCP 伺服器,你需要的是把你手上的那一個做好。

現在我也很好奇你那邊的情況。打開你最常用的 MCP 伺服器,數一下它暴露了多少工具。把那個數字丟到留言裡:是少於 10,還是已經超過 30?如果你曾經在第一個 prompt 之前量過 token 成本,也請告訴我你看到了什麼。我會回覆每一個數字。


追蹤我,獲得更多 AWS 架構、DevOps 與 AI 基礎設施相關內容:
Portfolio | LinkedIn | Dev.to | YouTube | Email | AWS Builder Center | X


原文出處:https://dev.to/aws-builders/mcp-token-cost-i-cut-my-mcp-server-from-15-tools-to-4-cek


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝7   💬1  
271
🥈
boluoji
📝5   ❤️3
94
🥉
mike
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
📢 贊助商廣告 · 我要刊登