MCP无状态核心配置怎么调:让服务端不依赖会话也能稳定工作
MCP 服务端默认可能依赖会话(session)来维持客户端连接状态。
当你要做多实例部署、负载均衡或容器弹性伸缩时,这种有状态模式会让请求落到不同实例后找不到原会话。
MCP 无状态核心配置的目标,就是让每个请求独立完成认证和上下文传递,服务端不保存会话状态。
什么情况下需要把 MCP 配成无状态
有状态模式适合单实例、长连接、工具调用需要连续上下文的场景。
但以下情况建议改成无状态:
- 服务端前面挂了负载均衡,请求可能落到任意实例
- 用容器编排做水平扩容,实例随时创建和销毁
- 客户端是短生命周期进程,不保证复用同一连接
- 希望服务端重启后客户端无需重新初始化会话
判断标准很简单:如果请求离开某个实例后无法在其他实例上继续处理,就说明会话状态被绑定在了服务端,需要改成无状态。
服务端 transport 与鉴权配置要点
无状态配置的关键在 transport 层和鉴权层,不在工具代码本身。
以常见的 Streamable HTTP 传输为例,服务端初始化时要显式关闭会话管理,并让每次请求自带认证信息。
from mcp.server.fastmcp import FastMCP
# stateless_http=True 表示不创建、不校验会话
mcp = FastMCP("my-server", stateless_http=True)
如果使用其他框架或自行实现 transport,需要确认两点:
- 不生成 session id:响应头里不再返回
Mcp-Session-Id,或服务端不要求客户端回传该头。 - 每次请求独立鉴权:认证 token 放在请求头(如
Authorization)中,服务端按请求校验,而不是在初始化时绑定到会话。
配置文件里常见的错误是只改了 transport 类型,却保留了会话校验中间件。
检查服务端启动日志,如果仍然出现 session 创建或查找记录,说明无状态没有真正生效。
客户端配置怎么配合
客户端侧要避免依赖会话保持。
以 JSON 配置为例,连接无状态 MCP 服务时不要启用会话复用选项,并确保每次请求都带上认证头:
{
"mcpServers": {
"my-stateless-server": {
"type": "streamable-http",
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer "
}
}
}
}
不同客户端对 type 字段的命名可能不同,有的叫 transport,有的叫 streamableHttp,以客户端实际文档为准。
关键是不要把 token 只放在初始化请求里,无状态模式下每个请求都需要独立携带。
验证无状态是否真正生效
改完配置后,用两个检查确认:
- 连续发两次请求,第二次不带任何 session 相关头,服务端仍能正常返回工具列表或执行结果。
- 重启服务端进程后,客户端不重新初始化也能继续调用。
如果第二次请求返回 400 或提示会话无效,说明服务端仍在强制校验会话,回到 transport 初始化处检查 stateless_http 或等价参数是否传入。
常见坑与边界
无状态不等于无认证。 关闭会话后,鉴权必须靠每个请求自带的 token 完成,不能因为去掉会话就把认证也省掉。
工具本身有状态时不能简单无状态化。 如果某个工具需要跨请求保存中间结果,应把状态放到外部存储(如 Redis)并按请求 ID 读取,而不是依赖 MCP 会话。
日志里出现 session 相关报错时,先确认负载均衡是否改写了请求头,再检查服务端版本是否支持无状态模式。
部分旧版本可能没有该参数,升级前先查对应版本文档。
无状态配置适合横向扩展场景,单机小规模使用不必强改。
确认你的部署形态确实需要多实例后再动手,改完按上面的方法验证一次,比只看配置项更可靠。