MCP 最小 Server 实测:3 个 JSON-RPC 报错与修法

先给结论:MCP(Model Context Protocol)的 Server 本质就是一个监听标准输入输出的 JSON-RPC 2.0 程序 ,握手只有三步------initialize → notifications/initialized → tools/list / tools/call。我用 Python 标准库手写了一个最小实现,跑了 7 次往返,把新手最常撞的 3 类报错全部复现了一遍 :-32002(没初始化就调工具)、-32602(参数或工具名不对)、-32601(方法名不存在)。实测在这台机器上,除进程首包 24.8ms 外,之后每次往返只要 0.02~0.15ms。

如果你正在接 AI Agent 的工具调用,或者刚听说 MCP 想搞明白它到底在传什么,这篇可以让你用两个文件、零第三方依赖把它跑通,并知道报错该往哪查。

为什么偏偏是这三个报错

MCP 把"能调工具"拆成了一套有顺序的会话。顺序错了、参数错了、名字错了,都会在 JSON-RPC 层被直接拒绝。协议里最重要的几条:

阶段 客户端发什么 服务端应该怎么应答
1. 握手 initialize(带 protocolVersion / clientInfo) 返回支持的 capabilities 和 serverInfo
2. 确认 notifications/initialized(通知,无 id) 不返回响应,服务端把状态置为已初始化
3. 发现 tools/list 返回工具数组,每个工具带 inputSchema
4. 调用 tools/call(name + arguments) 返回 content 结果,或错误

对应的 JSON-RPC 错误码也有明确分工:

错误码 含义 典型触发
-32700 Parse error 发过去的不是合法 JSON
-32601 Method not found 方法名拼错,如 foo/bar
-32602 Invalid params 缺必填参数、类型不对、工具名不存在
-32002 Server not initialized 没握手就直接要工具(自定义码,本文实现采用)

记住这张表,90% 的"连不上/调不通"都能对号入座。

怎么手搓一个最小 MCP Server

说明在先:下面不是官方 SDK ,而是照着 MCP 的 initialize + tools 流程写的最小 JSON-RPC 实现,目的是让你看清协议本身。生产环境仍建议用官方 mcp SDK。

服务端核心逻辑就一个循环:逐行读 JSON,按 method 分发。

python 复制代码
state = {"initialized": False}

if method == "initialize":
    state["initialized"] = False
    send({"jsonrpc": "2.0", "id": mid, "result": {
        "protocolVersion": "2024-11-05",
        "capabilities": {"tools": {}},
        "serverInfo": {"name": "mini-mcp", "version": "0.1.0"},
    }})
elif method == "notifications/initialized":
    state["initialized"] = True
elif method == "tools/list":
    if not state["initialized"]:
        err(mid, -32002, "Server not initialized")
    else:
        send({"jsonrpc": "2.0", "id": mid, "result": {"tools": TOOLS}})

工具定义里最关键的是 inputSchema,它决定了客户端能不能"照着 schema 拼参数":

python 复制代码
TOOLS = [{
    "name": "add",
    "description": "两数相加,返回和",
    "inputSchema": {
        "type": "object",
        "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
        "required": ["a", "b"],
    },
}]

调用阶段,服务端必须自己再校验一遍参数,不能迷信客户端:

python 复制代码
missing = [k for k in ("a", "b") if k not in args]
if missing:
    err(mid, -32602, f"Missing required argument(s): {','.join(missing)}")

客户端则是一个简单的子进程管道,发一行、读一行、计时:

python 复制代码
p = subprocess.Popen([sys.executable, "-X", "utf8", "mini_mcp_server.py"],
                     stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                     text=True, encoding="utf-8", bufsize=1)

三类报错:现象、原因、修法(实测)

我把错误场景写进客户端,一次跑出 4 个错误、归并为 3 类:

# 现象 实测错误码 原因 修法
1 一上来就 tools/list -32002 Server not initialized 没走 initialize / 没发 notifications/initialized 先握手,再发通知,然后才请求工具
2 tools/call 少传 b -32602 Missing required argument(s): b 参数不符合 inputSchema.required 按 schema 补全;服务端做必填校验
2 调用不存在的 mul -32602 Unknown tool: mul 工具名写错 先 tools/list 拿准确名字
3 调 foo/bar -32601 Method not found: foo/bar 方法名不在协议里 对照协议方法表,别自己发明

第一类最常见:很多人以为"发了 tools/call 就该有结果",但没握手时服务端连工具清单都没准备好,只能拒绝。第二类多见于自己拼参数时漏字段。第三类则是把方法名当普通函数名随手写。

实测数据

环境:Windows + Python 3.15.2,客户端逐条发请求并计时。

步骤 耗时(ms) 结果
tools/list before initialize 24.781 错误 -32002
initialize 0.150 成功,返回 mini-mcp 0.1.0
tools/list 0.134 返回 1 个工具
tools/call add(19,23) 0.064 返回 42
tools/call missing b 0.034 错误 -32602
tools/call unknown tool mul 0.027 错误 -32602
unknown method foo/bar 0.023 错误 -32601

汇总:7 次往返、捕获 4 个错误(归为 3 类)、最快 0.023ms、最慢 24.781ms、平均 3.602ms。最慢那一次是进程/管道首包,属于一次性开销,不是协议本身慢。

怎么复现

只需要两个文件,零第三方依赖:mini_mcp_server.py 和 mini_mcp_client.py,然后在本机执行:

bash 复制代码
python -X utf8 mini_mcp_client.py

日志会同时打印到终端并写入 run_log.json,错误码和你看到的表一致。

结论与下一步

  • MCP 排障先查三件事:握手顺序、错误码、inputSchema。
  • 如果服务端"没反应",先看是不是缺了 notifications/initialized;如果"参数无效",先核对 tools/list 里的 schema。
  • 下一步可以做的:把这三类错误码映射进客户端日志;给 tools/call 加超时和重试;再接官方 SDK 做一次对照,看自定义实现和标准实现的行为差异。

先把最小协议跑通,再去接真实工具,比一上来就啃 SDK 快得多。

相关推荐
用户4993350250714 分钟前
一人VIP账号多人共用:Web 代理里的会话共享怎么实现
前端
用户老李15 分钟前
无线电自学教程 05:第一台收音机——从矿石机到 SDR
前端
IPIPD23 分钟前
Node.js请求遇到503怎么重试?先解析Retry-After,再做有上限退避
前端
葡萄城技术团队29 分钟前
dsh-spreadjs-editor 的集成链路:把 SpreadJS Designer 嵌进 Agent 工作台
前端
FlyWIHTSKY1 小时前
vue2和vue3有什么区别,用法上有哪些区别
前端·javascript·vue.js
码云之上1 小时前
10 颗一模一样的「Edit」:中后台 Web Agent 怎么找到对的那一行
前端·人工智能·浏览器
量化分析码农2 小时前
【Python量化多因子实战 04】因子暴露不是 alpha:市值与行业中性化实战
前端·后端
不可能片场2 小时前
Electron 发布 正文写入的三条通道与读回口径
前端·electron
jerrywus3 小时前
让 AI 帮你部署 Vercel,报错了也不用手动搬日志
前端·agent·mcp