首页 >  科技周边 >  人工智能

MCP 2026-07-28 怎么迁移:无会话请求、MRTR 与工具调用验收

来源:17golang原创

时间:2026-08-16 18:08:48 407浏览 收藏

把 MCP 服务器从单实例部署迁移到普通负载均衡集群后,最容易暴露的问题往往不在工具逻辑本身,而是旧实现偷偷依赖了 Mcp-Session-Id:第一次请求落到 A 实例,用户补充信息后重试却跑到了 B 实例,服务端找不到上一次的上下文。MCP 2026-07-28 的协议核心正是针对这个问题做的改造——请求可以自描述,按普通 HTTP 规则路由,工具调用需要用户补充内容时,再通过 MRTR 返回可重试的输入请求。

要点速览
  • 迁移重点不是直接把会话字段删掉,而是把跨请求依赖的状态改成显式句柄或者可回放的请求状态。
  • Streamable HTTP 请求要让 Mcp-MethodMcp-Name 与 JSON-RPC 方法、工具名保持一致。
  • input_required 不是最终业务结果,客户端收集用户答案后要带回 requestState 再次提交原工具调用。
  • 灰度验收至少覆盖跨实例重试、重复提交、用户拒绝和旧客户端兼容四条路径。

先看迁移场景:为什么“有会话”会卡在负载均衡后

旧实现常把连接或者会话 ID 当成上下文索引:工具调用开始时在内存里记下当前步骤,服务端再通过长连接等待用户确认。这种方式在单机部署时逻辑很直观,但一旦前面换成轮询负载均衡,第二个请求就可能被送到另一台实例;如果实例之间没有做共享状态,用户的确认信息就完全接不回原流程。

MCP 2026-07-28 的设计方向是让每个请求尽量做到自描述。客户端可以先做 server/discover,也可以直接发送具体请求;服务端不再把协议级会话作为每次调用的隐含前提。应用层仍然可以保留业务状态,但要把状态句柄放进工具参数或者请求状态里,让它能被记录、重试和审计。

三类改动要分开:协议、网关和应用状态

改动面迁移前常见做法迁移后验收点
协议请求依赖 initialize、initialized 和会话头请求携带版本与调用信息,可被任意实例接收
网关路由按连接或粘性会话转发Mcp-MethodMcp-Name 路由,并检查头体一致
业务状态服务端内存保存“下一步”流程状态用显式句柄或 requestState 承接重试

这里别着急一次性重写所有工具。先把网关日志补全方法头、工具名、请求 ID 和实例名字段,再从一个需要用户确认的工具开始做双实例灰度。能证明第二次请求完全不依赖第一台机器的内存状态,迁移才算过了第一关。

MCP 2026-07-28 从会话粘滞迁移到无会话请求的实例路由证据图

请求头和请求体怎么对齐:先在网关挡住错路由

新的 Streamable HTTP 路由信息可以放在 Mcp-MethodMcp-Name 里。它们不是多余的装饰字段:网关不需要解析完整 JSON 报文,就可以直接把 tools/call 分到对应服务;但这也意味着头和请求体的对应字段必须互相校验。

POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search

{"jsonrpc":"2.0","id":17,"method":"tools/call",
 "params":{"name":"search","arguments":{"q":"mcp"}}}

建议在网关和服务端各做一次一致性判断:头里的方法必须等于 JSON-RPC 的 method,头里的名称必须等于工具或资源名称。任何一处不一致都返回明确的参数错误,同时记录请求 ID;不要让网关自动猜测“哪个字段更可信”。

MRTR 的关键路径:input_required 之后要重试原调用

工具运行过程中可能需要用户确认后续操作,例如“是否删除选中的 3 个文件”。MRTR 不要求服务端一直挂着一条流等待用户答案,而是先返回一个 input_required 结果。客户端把请求内容展示给用户,等用户接受或者拒绝后,再把用户选择和 requestState 带回原来的工具调用。

// 第一次 tools/call 的业务结果
{
  "resultType": "input_required",
  "inputRequests": {
    "confirm": {
      "type": "elicitation",
      "message": "删除 3 个文件?",
      "schema": {"type": "boolean"}
    }
  },
  "requestState": "opaque-state-from-server"
}

重试的时候,客户端不要新建一个没有关联关系的独立工具调用。原始工具名、业务参数、用户答案和请求状态需要能被服务端正常关联;服务端也不能只信任客户端传回的“已确认”字段,仍然要重新校验资源范围、操作权限和当前状态。

MCP tools/call 返回 input_required 后携带 requestState 重试的确认链路证据图

灰度验收清单:四个测试比“能调用工具”更重要

  1. 跨实例:第一次请求固定到实例 A,第二次重试固定到实例 B,仍能得到同一个预期业务结果。
  2. 重复提交:客户端因为网络超时重复发送答案,服务端不会重复执行删除、扣款或创建资源等副作用操作。
  3. 用户拒绝:拒绝、取消和过期状态都能返回稳定结果,不会被误判为确认操作。
  4. 头体冲突:篡改 Mcp-Name 或 JSON-RPC 方法时,网关和服务端都能正常拒绝并留下完整日志。

如果工具有副作用,最好给每次确认操作绑定一次性幂等键,并把“待确认、已确认、已拒绝、已过期”写入可查询的状态表。无会话不等于完全无状态;它只是把之前隐藏在连接里的状态移到可观察的业务边界上。

旧客户端怎么过渡:能力协商和回滚要先写出来

迁移期间通常会同时存在旧版和新版客户端。服务端可以根据客户端声明的能力选择兼容路径,但不要把“支持新协议”等同于“所有扩展能力都支持”。对 MRTR、Elicitation 和 Tasks 这类能力要分别记录开关,遇到不支持的客户端时返回可解释的降级结果。

回滚逻辑也要保持单向可理解:新网关能识别旧请求,旧网关不一定识别新头字段。因此灰度发布时要保留旧入口,先让新客户端只访问一小组无副作用工具,再逐步放开需要用户确认的工具;日志中同时记录协议版本、客户端能力和实例名,出现异常可以快速按版本切回原有逻辑。

相关问题

MCP 2026-07-28 还需要 initialize 吗?

协议核心不再把 initialize/initialized 交换和 Mcp-Session-Id 作为必需前提;客户端仍可以先发现服务能力,具体实现要看对应的协议版本和兼容策略。

requestState 可以直接存用户密码吗?

不应该。它应是不可读的服务端状态句柄或者经过保护的请求状态,敏感凭据要走独立的安全交互流程,不要塞进可回放的普通请求里。

MRTR 能解决所有长任务吗?

不能。MRTR 解决的是一次客户端请求中途需要补充输入的往返场景;长时间运行的任务应该使用明确的任务生命周期、查询和取消机制。

最小迁移顺序是什么?

先补齐请求头体一致性校验和跨实例全链路日志,再将一个确认型工具改成 input_required 重试模式,最后扩大到有副作用的工具并加入幂等与回滚逻辑。

把协议变化落到工程验收

MCP 2026-07-28 的价值不只是删掉一段会话握手流程,而是让工具调用更像普通可路由、可重试、可观测的 HTTP 请求。真正迁移完成的标志,是请求可以落到任意实例,用户补充输入可以安全回到原调用,网关能在请求进入业务逻辑前发现方法与工具名冲突,副作用操作也有对应的幂等和拒绝路径。按这个顺序做灰度,协议升级才不会变成一次难以回滚的全量切换。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>