Day 17 到 19 一路在講「誰能做什麼」:hooks 在事件層把規則寫死,subagent 在角色層用 tools 收邊界,skill 用一段描述讓模型決定要不要載入指引。今天講工具從哪裡來。答案幾乎都是 MCP,而它最近的變動不小,連協定本身都換了一個大版本
規格版本頁現在標示的最新版是 2026-07-28,不是 2025-11-25,而且是一次大改版。四個版本的重點如下,皆取自各版 changelog 的 Key Changes:
| 版本 | 重點 |
|---|---|
| 2025-03-26 | OAuth 2.1 授權框架、Streamable HTTP 取代 HTTP+SSE、tool annotations |
| 2025-06-18 | structured tool output、elicitation、resource links |
| 2025-11-25 | URL mode elicitation、sampling 可帶工具、Client ID Metadata Documents、實驗性 tasks |
| 2026-07-28 | 無狀態化、移除 initialize 握手與 session、server/discover、MRTR、tasks 移出核心 |
2026-07-28 改的是底層假設,值得拆開看:
initialize 握手與 Mcp-Session-Id,每個請求自己帶協定版本與 client 能力。需要跨呼叫狀態的 server,改用自己發的 handle,當一般工具參數傳。server/discover:server 必須實作,用來宣告支援的版本、能力與身分。tasks/get 輪詢取代會阻塞的 tasks/result,另加 tasks/update 讓 client 補輸入。規格同時新增 extensions 欄位,extension 預設關閉,要明確 opt-in。tools/list 等結果要帶 ttlMs 與 cacheScope,server 也應以固定順序回傳工具,利於 client 快取與 prompt cache 命中。同一版的棄用清單,寫 server 的人值得逐行讀:
| 棄用項目 | 官方遷移方向 |
|---|---|
| Sampling | 直接串接 LLM 供應商 API |
| Roots | 用工具參數、resource URI 或 server 設定傳目錄 |
| Logging | stdio 寫 stderr,觀測改用 OpenTelemetry |
| Dynamic Client Registration | Client ID Metadata Documents |
這四項的最早移除時間,是 2027-07-28 當天或之後發布的第一個版本。棄用不等於移除,官方的說法是它仍是規格的一部分,但新實作不該採用,既有實作應該遷移。HTTP+SSE 傳輸也在棄用表裡,最早可移除的時間是相關提案定案後三個月,實際何時移除由核心維護者在發版時決定。所以新寫的 server,不要再依賴 sampling。
Claude Code 這一側,2.1.232 起有 v2 MCP client,2.1.274 的 changelog 寫明部分安裝預設改用它並協商 2026-07-28(針對直連的 HTTP server),也可用環境變數退回舊行為。stdio server 要更新的版本,文件另有說明,且還在逐步推出,不要假設自己的 stdio server 已經走新協定。從 2.1.265 起,--transport http 遇到舊式 HTTP+SSE server 會自動退回 SSE。治理上,MCP 在 2025-12-09 成為 Linux Foundation 旗下 Agentic AI Foundation 的創始專案。

傳輸類型有三種。HTTP 是遠端 server 的建議選項,SSE 文件標為棄用但仍可用,stdio 用 -- 把 Claude 自己的旗標與 server 指令隔開。WebSocket 只能寫進 JSON 設定。
# 遠端 server,走 HTTP
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
# 本機 stdio server,-- 之後原封不動交給 server
claude mcp add --scope project wordcount -- python3 /絕對路徑/server.py
claude mcp list # 全部 server 與連線狀態
claude mcp get wordcount # 單一 server 詳情
範圍有三種,存放位置與共享方式不同:
| 範圍 | 載入範圍 | 團隊共享 | 存放位置 |
|---|---|---|---|
| Local(預設) | 當前專案 | 否 | ~/.claude.json |
| Project | 當前專案 | 是 | 專案根目錄 .mcp.json |
| User | 所有專案 | 否 | ~/.claude.json |
同一個 server 重複定義時的優先序,是 Local、Project、User、Plugin 提供、claude.ai connector,企業的 managed 設定排在全部之上。官方文件的說法是:使用最高優先序來源的定義,整筆 server 設定取代,欄位不會跨範圍合併。重複的判斷方式是三種範圍依名稱比對,plugin 與 connector 依 endpoint 比對。
.mcp.json 支援環境變數展開,語法是 ${VAR} 與 ${VAR:-預設值},可用在 command、args、env、url、headers。這樣憑證不用寫進要提交的檔案:
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${INTERNAL_API_TOKEN}" }
}
}
}
這份範例是依文件語法寫的示意,沒有實跑。文件另外規定,遠端 server 的 url 與 headers 裡,有一組固定名單的變數一律讀成空字串,連 :- 預設值也不生效,名單包含 ANTHROPIC_API_KEY、NPM_TOKEN、HTTPS_PROXY 這類。名單外的名稱,例如上面範例的 INTERNAL_API_TOKEN,會正常展開。

.mcp.json 會跟著 repo 走,所以 Claude Code 對專案範圍的 server 有核准機制。官方文件的說法是互動式 session 在使用前會先詢問核准,要重設選擇用 claude mcp reset-project-choices。三個設定鍵:enableAllProjectMcpServers、enabledMcpjsonServers、disabledMcpjsonServers,拒絕優先於前兩者。
實跑結果:
claude mcp add --scope project 加完 server,claude mcp list 與 get 都顯示 ⏸ Pending approval (run claude to approve)。.claude/settings.local.json 同時列進 enabledMcpjsonServers 與 disabledMcpjsonServers,狀態變成 ✘ Rejected (see disabledMcpjsonServers in settings),拒絕確實優先。enabledMcpjsonServers 時,claude mcp get 仍顯示 Pending。文件說明 list 與 get 的專案核准判斷需要先信任該資料夾,我沒有進一步拆開驗證。claude -p(無頭模式)請 haiku 呼叫這個 server 的工具:設定檔裡只有 permissions.allow 的規則、沒有任何核准鍵時,回傳 4;只有 enabledMcpjsonServers、沒有 allow 規則時,也回傳 4。前者說明專案 server 不經核准就被載入,後者說明這個唯讀工具在無頭模式下沒被權限擋下,我沒有進一步查原因。文件對前者的說法是無頭模式無法顯示核准提示。每組只跑一次。無頭模式不問就載入這件事,對 CI 很重要:在 CI 裡跑 Claude Code,等於預設信任 repo 裡的 .mcp.json。要擋可以用 disabledMcpjsonServers、--setting-sources 或 --strict-mcp-config。另外要分清楚:從 2.1.196 起,未信任的資料夾裡,提交進 repo 的 settings 無法替自己核准 server,但 changelog 寫的範圍是 claude mcp list 與 get 不再啟動這類 server,也就是狀態顯示與互動核准,不會讓 -p 多一層攔截。
遠端 server 走 OAuth:加好 server 後在 Claude Code 內用 /mcp 登入,token 由 Claude Code 保存並自動更新。也可以用 claude mcp login <name>。如果 server 不支援動態 client 註冊,錯誤訊息會要求預先設定憑證,用 --client-id 與 --client-secret。文件也寫明支援改用 Client ID Metadata Document 的 server,並會自動探索。這正好對上前面棄用清單裡 DCR 的遷移方向。
MCP 工具的名稱格式是 mcp__<server>__<tool>,權限規則依此寫:
| 規則 | 效果 |
|---|---|
mcp__github 或 mcp__github__* |
該 server 全部工具 |
mcp__github__search_issues |
單一工具 |
deny 的 mcp__* |
全部 MCP 工具 |
allow 的萬用字元只能放在字面的 mcp__<server>__ 前綴之後,沒有錨定的 mcp__* 寫在 allow 會被略過並警告,不會自動核准任何東西。另外,帶括號的 mcp__ 規則在載入設定時會被略過,所以寫在 settings 檔的規則沒辦法依參數比對。要依參數擋,得在啟動時用 --disallowedTools 傳 deny 規則。
server 端也能主動要求把關:在 tools/list 的 _meta 設 anthropic/requiresUserInteraction 為 true,每次呼叫都會跳提示,連 bypassPermissions 也一樣,allow 規則無效,文件在同一節標示 2.1.214,另外在 dontAsk 模式下這類呼叫會直接被拒絕。組織層級則有 managed-mcp.json 獨占控制、managedMcpServers、allowedMcpServers 與 deniedMcpServers,denylist 優先於 allowlist。
信任是整件事最重的部分。Claude Code 文件寫的是「Verify you trust each server before connecting it」,安全頁則說 Anthropic 審查 connector 的上架條件,但「does not security-audit or manage any MCP server」。安全頁還有一句容易漏掉:看 .mcp.json 看不出一個 session 能載入的全部 server,plugin、其他範圍與 claude.ai connector 也會帶 server 進來。實跑時 claude mcp list 列出的,除了專案那一個,還有 plugin、使用者範圍與 claude.ai connector 帶來的好幾個。
協定本身的安全要求有兩條值得記住。第一,工具呼叫應該有人在迴路中,規格寫的是 SHOULD 有能拒絕的人;第二,client 必須把 tool annotations 視為不可信,除非來自可信 server。我的範例 server 標了 readOnlyHint,但 client 不該因此就放行,那個標記是 server 自己說的。MCP 的 Security Best Practices 頁也點名 token passthrough 是反模式,server 禁止接受不是發給自己的 token,另外本機 server 若被入侵,攻擊者能以 client 的權限執行任意指令。
關於 tool poisoning,把惡意指令藏在工具描述裡,只有模型看得到,我沒有查到 Anthropic 的專門文章,定義來自第三方 Invariant Labs 的部落格,所以只當成風險類型,不當成官方結論。
先把「通則」和「Claude Code 現況」分開。Anthropic 2025-11 的工程文章指出多數 client 把所有工具定義預載進 context,並舉了一個範例:改成讓 agent 以程式碼探索工具檔案,只讀需要的定義,用量從 150,000 tokens 降到 2,000,節省 98.7%。這是文中單一情境的範例,不是通則,而且同一篇也承認執行 agent 產生的程式碼需要沙箱,增加維運與安全成本。
Claude Code 現行預設已經延後載入:官方文件寫的是開場只載入工具名稱與 server instructions,所以多接幾個 server 影響很小,官方沒有給省多少的百分比,社群流傳的數字我不採用。調整方式:
| 設定 | 效果 |
|---|---|
ENABLE_TOOL_SEARCH 未設定 |
全部延後 |
auto 或 auto:N |
定義總量低於 context 的 10%(或 N%)就全載入 |
false |
全部預載 |
server 設 "alwaysLoad": true |
該 server 的工具啟動即載入 |
每個工具描述與每個 server 的 instructions 預設截斷在 2,048 字元,2.1.280 起可用 CLAUDE_CODE_MAX_MCP_DESCRIPTION_LENGTH 調整,官方建議關鍵資訊放前面。這跟 Day 19 講的 skill 描述是同一個道理,名單裡的文字每輪都在付成本。
輸出也有上限:超過 10,000 tokens 會警告,預設上限 25,000,可用 MAX_MCP_OUTPUT_TOKENS 調,超過的結果會存成檔案,對話裡改放路徑。server 端可以用 anthropic/maxResultSizeChars 個別放寬,上限 500,000 字元。逾時方面,啟動預設 30 秒(MCP_TIMEOUT),主對話裡的 MCP 呼叫超過兩分鐘會自動轉成背景任務(2.1.212 起)。

工具設計方面,Anthropic 2025-09 的文章給了幾條,都是官方明載:工具要少而精,重疊的工具會分散 agent 的策略;功能相近的操作整合成一個工具;用共同前綴做命名空間;回傳只給高訊號資訊,別塞 uuid 這類低階識別碼;提供分頁、篩選與截斷,並給合理預設;錯誤訊息要讓 agent 知道下一步怎麼修,而不是只丟錯誤碼。這些原則我認為值得直接當成寫 server 的檢查清單。
Claude Code 對其他能力的呈現:prompts 變成斜線指令,格式是 /mcp__server__prompt,參數用空白分隔;resources 用 @server:protocol://path 引用;elicitation 不用設定,server 要求時會自動跳出對話框,有表單與開網址兩種模式;server 發出 list_changed 時,互動模式會重新抓取清單。Channels 讓 server 把訊息推進 session,但官方標示還是 research preview,也要用啟動旗標明確指定,不要當成穩定功能。
Day 18 提過 subagent 有 mcpServers 欄位,今天補上用法。官方文件的建議是:想讓某個 server 完全不出現在主對話、不佔工具描述的 context,就把它內聯定義在 subagent 裡,而不是放進 .mcp.json。內聯的 server 在 subagent 啟動時連線、結束時斷線;用字串引用既有 server 則共用父 session 的連線。放在專案 .claude/agents/ 的 agent 檔,內聯 server 要等資料夾被信任才會載入,否則會被略過。
---
name: researcher
description: 查閱外部文件並回報重點,只在需要時連線文件 server。
mcpServers:
- docs-search:
type: http
url: https://example.com/mcp
---
這是依文件格式寫的示意,沒有實跑,網址是占位用。兩個限制要知道:plugin 提供的 subagent 會忽略 mcpServers;主 session 的限制,例如 --strict-mcp-config 與組織的 allowlist,同樣適用於內聯 server。
官方自己就建議優先用 CLI:成本頁寫「Prefer CLI tools when available」,理由是 gh、aws 這類工具不增加逐工具的列表,最佳實務頁更直說 CLI 是與外部服務互動「most context-efficient」的方式。延後載入後差距縮小了,但方向沒變。官方也建議用 /mcp 停用不用的 server。
MCP 與 skill 的關係,官方說的是互補而非取代:「MCP connects Claude to external services. Skills extend what Claude knows」,組合起來就是 MCP 提供連線,skill 教模型怎麼用好。我沒有查到任何官方說某個場景該用 skill 取代 MCP,所以不要把這種說法當官方立場。
另一個判準是副作用。會發文、寄信、部署的 server,建議不要交給沒人看著的自動化 session,只在能當場核准的互動環境裡接。權限規則可以收斂,但發出去的東西收不回來,這是 Day 17 講的事前攔截要處理的那一類。
.mcp.json 裡的憑證一律用 ${VAR},不要寫死。.mcp.json 是你信任的,必要時用 --strict-mcp-config。claude mcp list 看實際載入了哪些 server,別只看 .mcp.json。--disallowedTools。alwaysLoad;工具描述把關鍵資訊放前面。工具能力放得越開,越需要先決定誰有資格接、誰能核准、出事時誰能擋。MCP 這半年的變動多半在協定細節,但那條信任邊界,還是得靠自己寫下來。