news 2026/10/5 12:36:33

MCP 的 initialize 握手真的没了?67 行标准库实测 2026-07-28 规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MCP 的 initialize 握手真的没了?67 行标准库实测 2026-07-28 规范

刷 MCP 更新说明的时候看到一句话:2026-07-28 修订把initialize 握手和协议层会话整个删掉了——那套每个教程都在教的「先 initialize、再发 initialized 通知」的连接仪式,从规范层面不存在了。教程没骗人,只是过时了。我不信邪,用 Python 标准库写了一个 67 行的最小 server(不装任何 SDK),按新规范把 discover、tools/list、tools/call 全流程跑通,连「版本不支持该报什么错」都实测了一遍。结论:协议比 SDK 让你以为的要轻得多——这也解释了为什么它能在一年内被每家厂商采纳、又在 2025-12 被捐进 Linux 基金会下的 Agentic AI Foundation。

目录

    • 一、删掉的是握手,不是能力协商
    • 二、67 行标准库 server:协议只剩 JSON-RPC
    • 三、10 条消息实测:全流程 1,528 字节
    • 四、三个坑:都是 stdout 惹的祸

一、删掉的是握手,不是能力协商

背景一句话:MCP 已经是 Agent 生态的事实连接标准——官方 server 注册表 2025 年 9 月进入预览,到 2026 年社区与厂商维护的 server 以千计;对要给模型接工具的人来说,这是绕不开的一层。先补时间线:2024-11-05 首发时是 stdio + HTTP+SSE;2025-03-26 换成 Streamable HTTP;2025-06-18 加了 elicitation;2025-11-25 是最后一代「握手 + 会话」基线;2026-07-28(现行)改为无状态核心——SEP-2575 删掉 initialize/initialized 握手,SEP-2567 删掉 Mcp-Session-Id 会话头。版本号、客户端信息、能力声明,改放在每个请求的params._meta里随行;客户端想提前了解 server 端支持哪些修订版本,调server/discover。这一改动是给部署解锁的:任何实例都能应答任何请求,负载均衡不再需要会话粘滞。这次修订一共动了五块:无状态核心(上述两条删除);Extensions 框架(扩展第一次成为一等公民,Tasks 长任务与 MCP Apps(由 server 渲染界面)是头两个官方扩展);授权加固(对齐 OAuth 2.1 与 OIDC 部署,含 issuer 校验);工具 schema 升级到完整 JSON Schema 2020-12(oneOf、anyOf、条件引用都能用了);以及一条正式的功能生命周期——每个特性标注 Active/Deprecated/Removed,被弃用的特性至少保留十二个月。一句话:2024 年那个「最小可用协议」正式长成了企业级标准。

二、67 行标准库 server:协议只剩 JSON-RPC

核心逻辑就一个handle函数,先看精简骨架(完整 67 行在文末仓库式清单里可复用):

importjson,sys REVISION="2026-07-28"defreply(req_id,result):result=dict(result,resultType="complete")return{"jsonrpc":"2.0","id":req_id,"result":result}defhandle(req):rid,method=req.get("id"),req.get("method","")ver=(req.get("params")or{}).get("_meta",{}).get("io.modelcontextprotocol/protocolVersion")ifver!=REVISION:return{"jsonrpc":"2.0","id":rid,"error":{"code":-32022,"message":f"unsupported:{ver!r}"}}ifmethod=="server/discover":returnreply(rid,{"supportedRevisions":[REVISION],"capabilities":{"tools":{}},"serverInfo":{"name":"min-stdio","version":"0.1.0"}})ifmethod=="tools/list":returnreply(rid,{"tools":TOOLS})ifmethod=="tools/call":ifreq["params"].get("name")=="fx_rate":returnreply(rid,{"content":[{"type":"text","text":"HKD/USD = 7.80"}]})return{"jsonrpc":"2.0","id":rid,"error":{"code":-32602,"message":"unknown tool"}}return{"jsonrpc":"2.0","id":rid,"error":{"code":-32601,"message":"not found"}}

三个实现决策都来自规范原文:stdio 传输下消息逐行分隔、行内禁止换行,所以序列化用紧凑分隔符;诊断信息只准写 stderr,stdout 是纯协议流;现代规范的成功结果必须带resultType(本 server 统一放 complete,多轮往返的inputRequired是另一条路径,本文未覆盖)。

三、10 条消息实测:全流程 1,528 字节

探针脚本做的事很朴素:以子进程拉起 server,往 stdin 写 JSON-RPC,每写一行就从 stdout 读一行应答,把方向、字节数、完整消息记进 transcript,stderr 单独收着做断言。它与本机 server 子进程完整对话五条路径——discover、tools/list、tools/call、坏版本(2025-06-18)、缺_meta版本——每条消息的方向、字节数、内容全部落盘:

tr=json.load(open("原始返回/mcp_transcript.json",encoding="utf-8"))assertlen(tr)==10# 五问五答assert[t["dir"]fortintr]==["C->S","S->C"]*5assertall(t["msg"].get("jsonrpc")=="2.0"fortintr)asserttr[1]["msg"]["result"]["serverInfo"]["name"]=="min-stdio"asserttr[5]["msg"]["result"]["resultType"]=="complete"# 两条错误路径:版本不支持统一 -32022asserttr[7]["msg"]["error"]["code"]==-32022asserttr[9]["msg"]["error"]["code"]==-32022total=sum(t["bytes"]fortintr)asserttotal==1528andmax(t["bytes"]fortintr)==273print(f"10 条消息 /{total}B / 最大单条 273 B / -32022 两条路径实测")

结果:10 条消息合计 1,528 字节,最大单条是 tools/list 的应答(273 B,带完整 inputSchema)。两个错误路径都按预期返回-32022——坏版本号和压根不带版本号,本 server 统一按「不支持」处理;这是实现者自己的选择,规范只规定了错误码语义。最贵的洞见是字节数本身:一次完整的能力发现加工具调用,双向不到 1.6 KB,协议开销小到可以忽略。字节的分布也有信息量:最贵的一条是 tools/list 应答(273 B),因为 inputSchema 的完整 JSON 要逐字段传;最便宜的一条只有 58 B(不带 _meta 的裸请求,代价是被 -32022 拒掉)。换句话说,这个协议里真正占重量的只有 schema 和元数据,信封本身轻得可以忽略——SDK 们包装出来的复杂度,不是协议本身的重量。


四、三个坑:都是 stdout 惹的祸

坑一:调试 print 是新手第一杀手。stdio 模式下 stdout 就是协议流,print 调试语句会直接插进 JSON-RPC 流,client 的逐行解析立刻崩——而且症状是「client 报格式错误」,你根本想不到是自己的日志。所有日志一律print(..., file=sys.stderr),规范白纸黑字。

坑二:行内禁止换行。一条消息一行;json.dumps默认不带换行,但格式化输出(indent=2)或者消息文本里混入裸换行都会断流。发送前用「序列化结果里不允许出现\n」做断言,一行代码买断这类事故。

坑三:resultType 的位置。现代规范要求它长在result 对象里,不是 JSON-RPC 响应的顶层——我第一版放错位置,探针立刻抓住。对着规范实现协议时,「字段在哪个对象里」和「字段叫什么」同等重要。顺带一提,探针脚本本身也是回归测试:server 每改一行,重跑五条路径十一个断言,十五秒内就知道有没有改坏——协议实现最怕的「看起来能跑」,靠的就是这种土办法。

边界四条说在前面:本次实测只覆盖stdio 传输、单工具、无多轮往返的最小面——Streamable HTTP 的 Mcp-Method 路由头、Multi Round-Trip 的 InputRequiredResult、以及 Extensions 注册机制都没有跑,别把本文当成全量合规测试;规范细节(尤其错误码的精确语义)以官方文档为准,本文的 -32022 行为是「规范允许范围内的实现选择」;2025-11-25 及更早的 legacy 客户端怎么兼容,官方给的是「先探 discover,失败再回落旧握手」的双 era 模式,本文的 server 只实现了现代侧;最后,demo 工具返回的是写死的汇率,别当真。

这 67 行 server 和探针脚本可以直接搬走当测试床,收藏备用;如果这篇帮你省下读 SDK 源码的一晚上,收藏+点赞。吐槽与安利各一句:吐槽 MCP 的 Python SDK 把一个 67 行能说清楚的事包了十几层抽象;安利规范本身写得极其克制——删功能比加功能更需要勇气。你升级到无状态版了吗?旧握手的 server 还打算撑多久?评论区聊聊。MCP/Agent 实测系列开更,关注不迷路。

参考链接

  1. https://blog.modelcontextprotocol.io/posts/2026-07-28-release-candidate/
  2. https://modelcontextprotocol.io/specification/latest

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 12:35:50

大模型与Agent工程实践:从基础理论到多智能体协作

1. 今日聚焦:大模型与Agent工程实践1.1 大模型基础理论正在走向实用化2026年9月25日的AI圈,最明显的一个变化是:讨论大模型的人不再只聊参数量和榜单,而是真正开始聊基础理论的工程落地。热搜里持续挂着“ai大模型基础理论”和“a…

作者头像 李华
网站建设 2026/10/5 12:35:09

Qt坦克大战开发指南:QGraphicsView与碰撞检测实战

简介:面向高校C课程设计场景的Qt坦克大战游戏项目,适合需要完成射击类大作业的学生,也适合希望借助完整实例入门Qt游戏开发的开发者。项目基于Qt 5.14.1与gcc 7.3.0构建,实现了35个关卡、每关20个敌方坦克、3条生命值以及大本营守…

作者头像 李华
网站建设 2026/10/5 12:34:59

多智能体持久化编排:AI Agent协作与状态管理实战指南

我们团队从上个季度开始,把所有零散的AI Agent逐步收拢到一套统一的编排框架里,这套框架就是我们内部命名为OpenRig的项目。起因很直接——单跑的Agent多了以后,代码重复不说,最头疼的是每个Agent都是“失忆体质”,用户…

作者头像 李华
网站建设 2026/10/5 12:34:57

OpenRig:将离散AI Agent编织成持久化协作系统

做多智能体编排这件事,我在OpenRig这个项目里折腾了快一个季度。最开始的想法非常简单:把已经造好的几个AI Agent用起来,让它们配合干活。结果一开始跑真实业务,就撞上了状态丢失、上下文割裂、任务分配混乱这些尴尬问题。单个Age…

作者头像 李华
网站建设 2026/10/5 12:34:55

Unity Shader实现Logo流光效果:从UV坐标到扫光Shader全解析

简介:面向Unity开发者的Logo流光Shader特效资源包,适合有一定Shader基础或希望快速实现动态光线效果的游戏UI、视觉设计师。资源完整覆盖两种实现路线:纯代码方式基于ShaderLab编写表面函数与顶点/片段着色器,利用时间变量与Lerp/…

作者头像 李华
网站建设 2026/10/5 12:33:26

AI Agent可靠性实践:把四道人工回路组件化,告别人工盯日志

我接手过一套已经跑了三个月的AI客服系统,那段时间最累的不是模型调优,而是每天凌晨三点被人叫醒去看日志。系统里负责处理退款申请的那个AI Agent,在遇到地址模糊、金额对不上、客户语气特别差、外部仓储接口超时这四种情况时,会…

作者头像 李华