先记住这个答案
MCP 连接先由客户端发送 initialize,携带自己支持的 protocolVersion、客户端能力和实现信息。服务端返回选择的协议版本、自己的能力及实现信息。若支持客户端请求的版本,应返回同一版本;否则返回自己支持的另一个版本,客户端必须检查是否也能处理。能力声明描述双方各自提供的可选功能,不是把两个对象做交集后互相复制。下面按 2025-11-25 规范讨论;工程上还应把版本兼容与当前任务所需能力分别作为连接准入条件。
- 协议日期与软件包版本是不同概念
- 客户端检查服务端实际返回的版本
- 同版本连接仍可能缺少必要能力
请求里声明的是客户端实际能够提供什么
假设桌面宿主能够向服务端提供工作区根目录,但没有接入模型采样,就只声明 roots。不能因为宿主自己的聊天窗口能够生成回答,就随手声明 sampling;后者还需要一个可以接收并处理服务端请求的协议处理器。
clientInfo.version 表示该客户端的软件版本,与 protocolVersion 的协议日期分别记录。排查兼容问题时应同时保存二者,避免把升级应用软件误当作已经切换了所有服务器连接的协议版本。
{
"jsonrpc": "2.0",
"id": "init-1",
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": { "roots": {} },
"clientInfo": { "name": "workspace-host", "version": "1.2.0" }
}
}这是客户端发出的完整初始化请求示例,roots 空对象表示支持根列表,但未承诺列表变化通知。服务端返回的是自己的能力,不能直接照抄这份客户端对象。
版本兼容通过后仍需检查任务依赖
例如一个界面要求读取资源并订阅变更,而服务端只返回 tools,那么协议版本即使一致,也无法完成这个界面的订阅功能。可以禁用对应入口或切换到明确的替代流程,不能继续发送尚未声明支持的资源订阅请求。
这种准入策略由宿主按业务要求制定,失败记录应指出缺少 resources.subscribe,避免只显示“连接失败”。也不要要求服务端拥有宿主用不到的全部可选能力,否则一个正常的只读工具服务会被不必要地拒绝。
不兼容需要结束本次连接或明确降级
收到不支持的返回版本后不应继续解释业务消息。若产品支持多个协议版本,可以为每个版本准备经过测试的编解码与能力规则;如果没有实现旧版本,就不能仅修改日期字符串假装完成降级。客户端应把版本检查作为连接准入条件,避免未经验证的报文进入业务层。
HTTP 后续请求还要携带协商后的 MCP-Protocol-Version 头。它说明消息所用的协议版本,并不承担身份认证。重连建立的新会话应重新确认版本与能力,不能把之前另一台实例的握手缓存直接当成当前事实。
容易答错的地方
- initialize 是在双方能力对象里找同名字段
- 客户端与服务端提供的功能方向不同,同名交集无法表达这种关系;应分别记录并在发起相应操作前检查接收方能力。
- 把协议日期改成对方返回值就完成兼容
- 日期只标识契约,不会自动升级解析器、传输行为和功能实现;必须先确认实际代码支持该版本,才能按它继续通信。
面试官还会怎么问?
服务端软件版本相同,能力一定相同吗?
不一定,部署配置、插件启用状态和授权范围可能不同。应以当前连接的握手与后续发现结果为依据,不能只按软件版本猜测。
是否必须支持最新协议才能连接?
只要双方能够使用同一个受支持版本即可。应测试实际协商结果及所需功能,不要把新旧日期本身当成全部兼容性判断。
初始化成功后可以直接把所有工具交给模型吗?
还需要完成就绪流程、发现工具并执行宿主的工具选择和授权策略。握手成功说明协议连接成立,不代表每个动作都获得执行许可。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。