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 开发笔记
更新记录: 首次发布