Claude Code、Codex 等 AI Coding Agent 如何呼叫 MCP Tools?JSON-RPC、Tool Schema 與執行權限完整解析
協議對比文寫過 Schema 和 Function Calling 的分工。本篇只落到 Coding Agent:模型填參數,宿主發 JSON-RPC。接伺服器、列工具、過 Schema、再評權限,是四步,不是一句「連上 MCP」。
閱讀前速覽
| 步 | 鎖什麼 | 誰執行 |
|---|---|---|
| 配置 | .mcp.json / config.toml | stdio 或 http;url 必須帶 type |
| 发现 | tools/list + inputSchema | 宿主列工具,模型看不見傳輸 |
| 调用 | tools/call 的 arguments | 模型填 JSON,宿主發 RPC |
| 权限 | mcp__server__tool / enabled_tools | 連上 ≠ 自動執行 |
MCP 是宿主和伺服器的協議。模型只看見工具名和參數 Schema。
調 MCP 的是宿主,不是模型
Claude Code、Codex、Cursor 都是 MCP 用戶端。會話開始後,宿主連上伺服器,發 JSON-RPC 2.0 的 tools/list,把每條工具的 inputSchema 交給模型。模型只產出一段參數 JSON。真正發 tools/call、跑副作用的是宿主。沒有宿主這一跳,MCP 只是設定檔。
- 設定:伺服器怎麼啟動。stdio 跑本地行程,http 連遠端。兩邊都是物件,不要口頭約定。
- Schema:
order_id必須過inputSchema。寬 object 等於請模型發明鍵。 - 權限:Claude 用
mcp__伺服器__工具寫規則。Codex 用enabled_tools和審批檔。Cursor 用mcpAllowlist。連上伺服器,不等於這些門已經開。
協議層的 Schema 和 Function Calling,見 MCP Tool Schema vs Function Calling。Coding Agent 自己的工具 JSON,見 AI Coding Agent 與 JSON 工具呼叫。Schema 為什麼是門,見 AI 為什麼需要 JSON Schema。本篇不再定義那三個詞,只寫宿主怎麼把 MCP 跑起來。
第一張物件:伺服器設定
Claude Code 的專案設定是倉庫根的 .mcp.json,可進版本庫。本機私有的寫進 ~/.claude.json。有 url 就必須寫 type:http(streamable-http 是別名)或 sse / ws。只寫 url、不寫 type,官方會當成壞掉的 stdio,伺服器被跳過。虛構訂單服務,不要貼真實金鑰:
{
"mcpServers": {
"orders": {
"type": "stdio",
"command": "node",
"args": ["./servers/orders-mcp.js"]
}
}
}
Codex 把同一件事寫進 ~/.codex/config.toml 或可信專案的 .codex/config.toml,表名是 [mcp_servers.orders]。stdio 用 command / args,遠端用 url。Cursor 用 .cursor/mcp.json 或使用者級檔案,編輯器和 CLI 共用。專案裡新出現的伺服器,Claude Code 會停在待批准,不是自動連。
第二張物件:tools/list 和 inputSchema
宿主連上之後,先問有哪些工具。這是 JSON-RPC,不是模型自己發的 HTTP:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}
伺服器回一張表。每一行是名字、說明、一份 JSON Schema。規範要求宣告 tools 能力。列表可以隨授權變,但不應隨連線抖動。Coding Agent 把這張表轉成模型能看的工具。Claude Code 裡,可呼叫名是 mcp__orders__lookup_order。外掛帶來的伺服器還要嵌外掛名。工具太多時,官方會延後載入,用工具搜尋按需展開,不要預設把整表塞進上下文。
{
"name": "lookup_order",
"description": "Look up an order by ID. Confirm before any refund.",
"inputSchema": {
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
}
第三張物件:模型填參,宿主 tools/call
模型看見的是宿主給的工具名。Claude Code 會話裡,一次呼叫長這樣:
{
"type": "tool_use",
"id": "call_3c91",
"name": "mcp__orders__lookup_order",
"input": { "order_id": "A-1042" }
}
宿主校驗 input 對上 inputSchema,再翻譯成發給伺服器的 RPC。名字用伺服器註冊名 lookup_order,不再帶 mcp__ 前綴:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "lookup_order",
"arguments": { "order_id": "A-1042" }
}
}
成功就回 content。失敗把 isError 設真,原因寫成物件,不要只丟一句散文。模型讀的是回寫,不是通訊端。
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{ "type": "text", "text": "{\"order_id\":\"A-1042\",\"status\":\"paid\"}" }
],
"isError": false
}
}
第四張物件:執行權限
MCP 規範寫明:工具呼叫應當能被拒絕。Coding Agent 把拒絕寫成規則,不寫成提示。Claude Code 用完整可呼叫名:
{
"permissions": {
"allow": ["mcp__orders__lookup_order"],
"ask": ["mcp__orders__create_note"],
"deny": ["mcp__orders__refund_order"]
}
}
官方順序仍是 deny、ask、allow。光桿 mcp__* 作 deny,會把 MCP 從上下文摘掉。Codex 用 enabled_tools 做白名單,disabled_tools 做隨後的黑名單,預設審批是 auto / prompt / approve,也可按工具覆蓋。Cursor 預設每次問;permissions.json 的 mcpAllowlist 寫成 orders:lookup_order。Shell / Git / 檔案那三道門,見 Coding Agent 權限模型。MCP 是第四張表,不是那三道門的替代。
五步把 MCP 收成物件
不要從「幫我接一個 MCP」開始。按物件寫:
- 先寫伺服器設定。stdio 或 http 選一個。url 帶 type。金鑰走環境變數,不進倉庫。
- 自己跑一遍 tools/list。記下名字和 required。沒有 Schema 的工具不要交給模型。
- 收緊 inputSchema。pattern、enum、
additionalProperties: false。查單不要帶退款鍵。 - 按工具寫權限。唯讀查單 allow。寫盤 ask。退款 deny。Codex 用 enabled_tools 先裁表。
- 把一次成功呼叫存成三份 JSON:tool_use、tools/call、result。能對上,才算接通。
Schema 怎麼當門,見 Agents API + JSON Schema。本篇只要求:Coding Agent 上,MCP 的每一步都有物件,而且由宿主發。
複盤 MCP,先攤開三份 JSON
一次失敗,多半是名字、Schema、權限沒對齊,不是模型不會調。
- 把
inputSchema和arguments格式化,看缺欄位和多餘鍵。 - 用 JSONPath 提取 抽出
$.params.name、$.input.order_id。 - 一次過門和一次被拒 JSON Diff。先改規則和 Schema,再改提示。
- 核對宿主名
mcp__orders__lookup_order和 RPC 名lookup_order。外掛伺服器還要帶外掛段。 - 設定、權杖、會話日誌不要貼進公共格式化站。JSONSort 在瀏覽器本地跑。
三份軌跡都能按 Schema 重建,你才是在收 MCP,不是在收「我點過連線」。
常見誤區
- 以為連上就等於會調。連上只是行程或 HTTP 通了。沒有 list、沒有 Schema、沒有權限,模型仍調不成。
- 把 MCP 當成 Function Calling。對模型都是填 JSON。對宿主,MCP 多一跳 JSON-RPC。協議對比文寫過分工,這裡只要求你看見那一跳。
- url 不寫 type。Claude Code 會按壞 stdio 跳過。遠端伺服器就此失蹤。
- 只配伺服器,不裁工具。一張大表進上下文。官方用延後載入和 enabled_tools,就是怕這個。
- 用一句話「請自動批准所有 MCP」當預設。Cursor 的一鍵全批、Claude 的 bypass、Codex 的 auto 全開,官方留給隔離環境。日常按工具寫。
- 專案 .mcp.json 當成本機私貨。它會進版本庫,別人打開倉庫會看到待批准。金鑰放使用者級設定。
FAQ
Coding Agent 會自己發 JSON-RPC 嗎?
不會。模型只填工具名和 arguments。JSON-RPC 的 id、method、params 由宿主拼。你在日誌裡看到 tools/call,那是用戶端,不是模型。
inputSchema 和權限哪個先評?
先形狀,再執行。Schema 不過,不要發 RPC。過了 Schema,仍可能 ask 或 deny。兩道門鎖的不是同一件事。
stdio 和 http 怎麼選?
要碰本機檔案或本機行程,用 stdio。要連託管服務,用 http。Claude Code 推薦遠端走 http;SSE 已標過時。WebSocket 適合伺服器主動推事件。
工具太多怎麼辦?
Claude Code 可延後 MCP 工具,按搜尋再展開。Codex 用 enabled_tools 裁表。不要把五十個工具一次塞進會話。
Subagent 能用這些 MCP 嗎?
看產品。Claude Code 的權限和 allowed-tools 要用完整可呼叫名。Agents API 的子代理繼承 MCP、不繼承你的 function。不要假設一張表自動傳給所有子會話。
結論
Coding Agent 調 MCP,不是模型直接打伺服器。宿主列工具,模型填 JSON,宿主再 tools/call。Schema 和權限是兩道門。
先寫清 A-1042 會走哪一個工具名、哪一份 Schema、哪一條權限。能指到三份物件,MCP 才算接通。模型會換。這三份應該先穩定。
延伸阅读
- MCP Tool Schema vs Function Calling 協議對比,不是 Coding Agent 怎麼調
- Coding Agent 为什么需要权限控制 Shell / Git / 檔案系統三道門
- AI Coding Agent 如何用 JSON 调工具 內建工具的 JSON,還沒接到 MCP
- Agents API + JSON Schema 实战 穩定、可驗證、可執行
- 为什么 AI 需要 JSON Schema Schema / Function Calling / Structured Output
- JSONSort 本地工具箱 格式化、校驗、Diff
- 全部文章 更多 JSON 與 AI 開發筆記
更新紀錄: 首次發布