ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Claude API 接入 MCP Server 实操:settings.json 配置与 JSON-RPC 验证指南

Claude API 接入 MCP Server 实操:settings.json 配置与 JSON-RPC 验证指南 1. 为什么 Claude API 接 MCP Server 总在握手阶段翻车如果你正在本地把 Claude API 和 MCP Server 串起来做联调大概率遇到过这几类现象客户端初始化没报错但一调用工具就返回-32601 Method not found或者settings.json里明明写了mcpServersClaude 却像没看见一样完全不触发工具再或者 stdio 传输跑着跑着连接静默断开日志里连个异常都没有。这些问题的根子通常不在模型而在配置骨架和 JSON-RPC 握手这两步。MCPModel Context Protocol本质上是让模型通过一套标准的 JSON-RPC 2.0 消息去调用外部工具Claude API 负责推理和决定调哪个工具MCP Server 负责真正执行。两者之间靠initialize→tools/list→tools/call这条握手链路串起来。只要其中任何一环的字段名、协议版本、传输方式对不上整条链路就断。这篇面向本地开发联调场景交付三样可以直接复制的东西一份能跑的settings.json骨架、一段 SDK 初始化片段、一组用 curl 和 Python 验证 JSON-RPC 握手的动作。走完之后你能确认「配置写对了」和「链路真的通了」这两件事而不是靠猜。适合已经在写 Claude API 调用、手里有一个本地或内网 MCP Server、想把它接进 Claude 工具调用流程的开发者。2. 接入前的统一通道准备在动settings.json之前先把 API 通道这件事定下来。Claude API 的调用需要一个base_url和一个 API Key本地联调阶段最怕的是网络链路本身不稳定导致你把网络问题误判成配置问题。我一般会先把通道换成国内可直连的地址把变量隔离掉后面排查就只剩配置和协议两层。TaoToken 在这里的角色是统一 Key / API 通道你不需要改任何已经写好的 MCP 对接代码只把客户端初始化时的base_url和api_key换掉即可其余参数保持原样。它的接口格式和官方规范一致所以settings.json里的字段、SDK 里的mcpServers结构都不用做特殊转换。控制台里生成的 Key 直接填进配置就行充值走人民币通道本地调试阶段不用折腾支付环节。需要提前拿到的两样东西一个 API Key在控制台的 API Keys 页面生成格式和官方一致直接当ANTHROPIC_API_KEY用。一个可用的base_url指向统一通道地址填到 SDK 的base_url或环境变量里。提示本地联调建议把 Key 放进环境变量而不是硬编码进settings.json避免误提交。下面配置里用${ANTHROPIC_API_KEY}占位。通道准备好之后MCP Server 本身要先能独立跑通。不管你是用FastMCP封装的本地 stdio 服务还是已经部署好的 HTTP 服务先确认它能正常返回工具列表再往 Claude 这边接。这一步没过后面所有报错都会指向错误的方向。3. 可复制的 settings.json 骨架与 SDK 初始化3.1 settings.json 骨架Claude 读取 MCP 配置的入口是settings.json项目级放在.claude/settings.json用户级放在~/.claude/settings.json。下面这份骨架同时覆盖了 stdio 和 HTTP 两种传输方式你可以按需删掉不用的那段。{ mcpServers: { local-filesystem: { command: npx, args: [ -y, modelcontextprotocol/server-filesystem, /Users/yourname/project ], env: { LOG_LEVEL: debug } }, remote-tools: { type: http, url: http://127.0.0.1:8765/mcp, headers: { Authorization: Bearer ${MCP_TOKEN} } } } }几个容易写错的字段逐个说清楚commandargs是 stdio 传输的写法command必须是可执行程序args是参数数组不要把整条命令塞进一个字符串。type: http是远程传输的写法url要指向 MCP Server 的/mcp端点不是根路径。env里的变量会注入到 MCP Server 进程调试阶段把LOG_LEVEL打开很有用。注意stdio 传输的 MCP Server 里绝对不要用print()往标准输出打调试信息。stdout 是 JSON-RPC 的消息通道任何非 JSON 的输出都会污染消息流导致连接静默断开。调试信息一律写日志文件或 stderr。3.2 SDK 初始化片段如果你是在代码里直接初始化客户端并挂载 MCP用下面这段。核心是把base_url指向统一通道mcpServers结构和settings.json保持一致。import asyncio from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage async def main(): options ClaudeAgentOptions( mcp_servers{ local-filesystem: { command: npx, args: [ -y, modelcontextprotocol/server-filesystem, /Users/yourname/project, ], }, remote-tools: { type: http, url: http://127.0.0.1:8765/mcp, }, }, allowed_tools[mcp__local-filesystem__*, mcp__remote-tools__*], ) async for message in query( prompt列出当前项目根目录下的文件, optionsoptions, ): if isinstance(message, ResultMessage) and message.subtype success: print(message.result) asyncio.run(main())allowed_tools里的通配符mcp__server名__*表示允许该 Server 下的所有工具server名必须和mcpServers里的键名完全一致大小写敏感。这一步写错模型会「看不到」工具表现就是完全不触发调用。3.3 环境变量与 base_url把通道信息通过环境变量注入SDK 会自动读取export ANTHROPIC_API_KEYsk-你的统一通道密钥 export ANTHROPIC_BASE_URLhttps://taotoken.net/apiANTHROPIC_BASE_URL指向统一通道后SDK 里所有请求都会走这个地址你不需要在每处调用里单独改。如果是在settings.json里配置可以加一个env段{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY} }, mcpServers: { remote-tools: { type: http, url: http://127.0.0.1:8765/mcp } } }4. JSON-RPC 握手验证从 initialize 到 tools/call配置写完不代表链路通了。MCP 的握手是标准 JSON-RPC 2.0你可以脱离 Claude 直接用 curl 打一遍确认 Server 端行为正确再回到 Claude 这边排查。4.1 initialize 握手第一步永远是initialize客户端和 Server 交换协议版本和能力声明curl -s -X POST http://127.0.0.1:8765/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 1, method: initialize, params: { protocolVersion: 2025-06-18, capabilities: {}, clientInfo: {name: curl-test, version: 1.0.0} } }正常返回里应该有result.protocolVersion、result.capabilities、result.serverInfo三个字段。如果返回-32602 Invalid params八成是protocolVersion写成了旧的测试版换成当前正式版再试。如果返回-32601 Method not found说明你打的端点不对检查url是不是漏了/mcp。4.2 tools/list 拉取工具清单握手成功后紧接着拉工具列表确认 Server 真的注册了工具curl -s -X POST http://127.0.0.1:8765/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 2, method: tools/list, params: {} }返回的result.tools是一个数组每个元素有name、description、inputSchema。这里要重点看name因为 Claude 侧allowed_tools里的名字必须和它对应。如果tools是空数组说明 Server 端工具没注册成功回到 MCP Server 代码里查mcp.tool()装饰器有没有生效。4.3 tools/call 实际调用最后一步真正调一次工具验证参数传递和返回值curl -s -X POST http://127.0.0.1:8765/mcp \ -H Content-Type: application/json \ -H Accept: application/json, text/event-stream \ -d { jsonrpc: 2.0, id: 3, method: tools/call, params: { name: search_documents, arguments: {query: settings, limit: 5} } }result.content里是工具返回的内容数组。如果返回-32602检查arguments的字段名和inputSchema是否一致如果返回isError: true那是工具内部逻辑报错看 Server 端日志。4.4 用 Python 脚本串起完整握手curl 适合单步排查日常联调建议写个小脚本一次跑完三步import json import httpx MCP_URL http://127.0.0.1:8765/mcp HEADERS { Content-Type: application/json, Accept: application/json, text/event-stream, } def rpc(method, params, req_id): payload {jsonrpc: 2.0, id: req_id, method: method, params: params} resp httpx.post(MCP_URL, headersHEADERS, jsonpayload, timeout10) resp.raise_for_status() return resp.json() init rpc(initialize, { protocolVersion: 2025-06-18, capabilities: {}, clientInfo: {name: py-test, version: 1.0.0}, }, 1) print(initialize:, init.get(result, {}).get(serverInfo)) tools rpc(tools/list, {}, 2) names [t[name] for t in tools.get(result, {}).get(tools, [])] print(tools:, names) if names: call rpc(tools/call, { name: names[0], arguments: {}, }, 3) print(call result:, json.dumps(call.get(result), ensure_asciiFalse)[:200])三步都返回正常说明 MCP Server 侧的 JSON-RPC 链路是通的。这时候再回到 Claude API如果工具还是不触发问题就锁定在 Claude 侧的配置或allowed_tools命名上。5. 本篇常见报错排查5.1 -32601 Method not found最常见的原因是端点路径不对。HTTP 传输的 MCP 端点是/mcp不是根路径也不是/sse。另一个原因是协议版本用了旧的测试版Server 不认。把protocolVersion换成当前正式版端点补全/mcp基本能解决。5.2 工具列表为空tools/list返回空数组说明 Server 端没注册上工具。检查mcp.tool()装饰器是否加在函数上、函数是否有类型注解和 docstring。FastMCP 依赖类型提示生成inputSchema缺了类型注解工具会被跳过。5.3 stdio 连接静默断开这是最隐蔽的一类。stdio 传输下stdout 是 JSON-RPC 专用通道任何print()、进度条、第三方库的 banner 输出都会污染消息流。表现是连接建立后没有任何报错就断了。解决办法是把所有调试输出改到 stderr 或日志文件检查依赖库有没有往 stdout 打东西。5.4 allowed_tools 命名不匹配Claude 侧的工具名格式是mcp__server名__工具名三段用双下划线连接。server名必须和mcpServers的键名完全一致。写错一个字符模型就看不到工具表现是对话正常但从不调用。建议先用tools/list拿到真实工具名再拼allowed_tools。5.5 协议版本字段识别失败不同版本的 MCP 协议对字段的要求有差异。用旧版 SDK 配新协议或者反过来都会出现字段识别失败。统一原则SDK 升级到支持 MCP 的最新版protocolVersion用当前正式版两边对齐。报错现象大概率原因处理动作-32601 Method not found端点路径错 / 协议版本旧补/mcp换正式版协议tools 为空数组工具未注册检查装饰器、类型注解、docstring连接静默断开stdout 被污染调试输出改 stderr 或日志文件工具不触发allowed_tools 命名错按mcp__server__tool对齐字段识别失败SDK 与协议版本不匹配升级 SDK对齐协议版本6. 联调闭环与后续动作走到这里你应该已经完成了三件事settings.json骨架落地、SDK 初始化挂载 MCP、用 JSON-RPC 三步握手确认链路通。本地联调阶段最值得养成的习惯是每次改完配置先跑一遍initialize→tools/list→tools/call把配置问题和协议问题分开定位而不是一上来就怀疑模型。如果你在排障过程中需要重新生成或核对 Key可以直接到 API Keys 页面处理接入字段和端点细节对照接入文档确认。想先验证模型本身在统一通道下的响应是否正常用模型对话跑一轮最快。如果接下来要把这套 MCP 配置用于长期编码或 Agent 任务Coding Plan 更适合承载持续调用。
返回列表