MCP 无状态化:Agent 集成的分水岭
2026 年 7 月 28 日的 MCP 规范更新,改动看起来非常技术化: 删掉了协议级会话,删掉了初始化握手。但它的后果远超一个协议细节 —— 远程 MCP 服务器从此和任何普通 HTTP 服务没有区别, 可以放在标准负载均衡器后面,任意实例都能处理任意请求。
这让 MCP 真正进入了"可以按普通后端服务来运维"的阶段。 同时也推翻了此前大量实现里关于状态、鉴权和生命周期的一整套假设。
先理解它原来是什么形状
MCP 用 JSON-RPC 2.0 通信,定义了三个角色:Host(承载模型的宿主应用)、 Client(宿主为每个服务器创建的连接器)、Server(暴露能力的一方)。
服务器对外提供三类能力,按"谁来决定使用"划分:
| 原语 | 由谁控制 | 说明 |
|---|---|---|
| Tools | 模型 | 模型可主动调用的函数,输入由 JSON Schema 描述 |
| Resources | 应用 | 用 URI 标识的只读数据,由宿主决定是否附加为上下文 |
| Prompts | 用户 | 可复用的模板,通常呈现为斜杠命令 |
旧规范里,客户端与服务器之间必须先握手建立会话,之后所有请求都挂在那个会话上。 好处是状态明确;坏处是服务器必须记住这个会话 —— 一旦部署多个实例,就要么做会话粘滞,要么把会话状态外置到 Redis。
改了什么
新规范的核心变化可以归纳为四件事:
1. 会话与初始化握手消失
每个请求自带协议版本和客户端能力声明,服务器不需要记住任何跨请求的状态。
这是"可水平扩容"的直接前提。与之配套的是新增的 server/discover:
客户端在做任何实质操作之前,先查询服务器支持的版本与能力。
2. 列表结果可缓存
工具列表、资源列表这类元数据变化不频繁,允许缓存。 对客户端来说这减少了启动时的往返;对服务器来说减少了无意义的重复计算。
3. 服务器主动请求被 Multi Round-Trip Requests 取代
这是最容易被低估的一条。原先服务器可以主动向客户端发请求 (典型场景是 elicitation:任务中途需要用户补充参数或确认)。 但"服务器主动发请求"天然依赖长连接和会话 —— 无状态服务器做不到。
新方案把这类交互改成多轮往返:服务器返回一个"需要补充信息"的结果, 客户端完成收集后再发起下一次请求,带上完整上下文。 语义上等价,但控制流反过来由客户端驱动,因而兼容无状态部署。
4. Tasks 移入扩展
长任务(Tasks)从核心规范移到扩展中。原因是早期采用者的反馈表明这套抽象还需要迭代, 放在核心里会限制演进速度。用的话要显式启用。
如果你的 MCP 服务器实现里维护了"连接 → 会话 → 上下文"的映射表, 这个表在新规范下就是多余的,而且会成为扩容的瓶颈。 改造的方向是:把每个请求需要的一切信息都放进请求本身。
鉴权:从浏览器授权到工作负载身份
无状态化之后,鉴权成为最棘手的问题。旧模型的默认假设是"有个人坐在浏览器前批准访问", 这对交互式客户端成立,但越来越多的调用方是以云工作负载身份运行、代表一个不在场的用户的代理。
这次规范在鉴权方面的改动:
issuer校验(RFC 9207),防止签发方混淆- 签发方绑定的客户端凭据
- 用 Client ID Metadata Documents(CIMD)取代动态客户端注册,成为首选的注册路径
- Enterprise-Managed Authorization 作为扩展提供,并已稳定
- 弃用 Roots、Sampling、Logging,以及旧的 HTTP+SSE 传输(给出至少 12 个月的下线窗口)
路线图里还明确了下一步方向:DPoP(持有证明)的定稿与推广, 以及通过 Workload Identity Federation、企业托管授权背后的 ID-JAG 授权、 标准令牌交换来定义代理身份与委托的路径。
如果你在 2026 年上半年实现了 MCP 服务器,很可能用了动态客户端注册和旧 HTTP+SSE 传输。 这两条都进了弃用流程。虽然给了至少 12 个月窗口,但新接入的客户端可能已经不再支持旧路径 —— 兼容层需要同时维护两套,或者干脆只留新的。
代码层面的变化
对绝大多数用官方 SDK 的开发者,改造集中在两处:不再维护会话、把能力声明放进每个请求。 下面是新规范下一个工具服务器的骨架(TypeScript SDK):
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import {
ListToolsRequestSchema,
CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// 注意:没有会话对象,没有 initialize 处理
const server = new Server(
{ name: "notes", version: "1.2.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
{
name: "search_notes",
description: "在笔记库中按关键词检索",
inputSchema: {
type: "object",
properties: {
query: { type: "string", description: "检索关键词" },
limit: { type: "number", description: "返回条数,默认 10" },
},
required: ["query"],
},
},
],
}));
server.setRequestHandler(CallToolRequestSchema, async (req) => {
const { name, arguments: args } = req.params;
if (name !== "search_notes") {
// 未知工具按协议返回错误,不要抛异常
return { isError: true, content: [{ type: "text", text: `unknown tool: ${name}` }] };
}
const query = String(args?.query ?? "");
const limit = Number(args?.limit ?? 10);
const rows = await db.search(query, Math.min(limit, 50));
return {
content: [{ type: "text", text: JSON.stringify(rows) }],
};
});
如果你用 Streamable HTTP 部署远程服务器,无状态化之后请求处理就变成一个普通 handler, 不需要再为每个连接分配实例:
import express from "express";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const app = express();
app.use(express.json());
app.post("/mcp", async (req, res) => {
// 每个请求独立处理:不读会话、不写会话
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // 关键:无状态模式
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
// 因为无状态,直接放在负载均衡后面即可,任意实例都能处理
app.listen(8080);
对现有集成的影响
按影响程度,可以把改动分成三档:
| 影响 | 涉及内容 | 需要做什么 |
|---|---|---|
| 必须改 | 会话管理、初始化握手、旧 HTTP+SSE 传输 | 移除会话状态,改 Streamable HTTP |
| 可能需要改 | 服务器主动请求(elicitation 等) | 改为多轮往返模式 |
| 建议关注 | 动态客户端注册、Roots / Sampling / Logging | 迁到 CIMD;弃用项规划下线 |
为什么说这是分水岭
MCP 最初的价值主张是"把 M 个应用与 N 个工具的集成数量从 M×N 降到 M+N"。 这个主张在开发阶段成立得很早,在生产阶段却一直有个软肋: 它看起来像一套 API,运维起来却不像。
无状态化改变的就是这一点。当 MCP 服务器不再需要粘滞会话、 不再需要为长连接单独设计扩缩容策略时,它就可以放进任何已有的 API 网关、限流层、可观测体系里 —— 不需要为它单独建一套基础设施。
一个协议能不能被广泛采用,往往不取决于它设计得多优雅, 而取决于它能不能被塞进现有的运维体系里。这次的改动正是朝这个方向。
- MCP 官方文档(角色划分、三类原语、传输方式、2026-07-28 规范变更)
- MCP 官方博客《The New MCP Roadmap》(会话与握手移除、
server/discover、列表缓存、Tasks 扩展化、鉴权改进) - MCP 规范迁移说明(CIMD 取代动态客户端注册、RFC 9207 issuer 校验、弃用项与 12 个月下线窗口)
- 生态采用情况综述(企业采用比例、SDK 下载量、各厂商支持情况)