Streamable HTTP session lifecycle can retain unreachable sessions and serialize session creation behind slow requests

这个报错/问题通常出现在使用 Python SDK 的 stateful Streamable HTTP transport 时,短生命周期客户端(如 readiness probe)反复连接、断开或初始化被拒绝/中断,导致服务端会话注册表保留无法被任何客户端访问或关闭的 session。优先排查

快速结论:这个报错/问题通常出现在使用 Python SDK 的 stateful Streamable HTTP transport 时,短生命周期客户端(如 readiness probe)反复连接、断开或初始化被拒绝/中断,导致服务端会话注册表保留无法被任何客户端访问或关闭的 session。优先排查 SDK 版本是否低于修复版本,以及是否有慢请求阻塞了新会话创建。

适用环境:Issue 中确认在 mcp==1.27.1 观察到;修复版本为 2.2.0(PR #3395)以及 backport 到 1.30.0(PR #3426)。Issue 未提供操作系统、Python、CUDA、显卡等其他环境信息。

最快修复方案:升级到 1.30.0 或 2.x。评论中明确说明三处生命周期问题已在该版本修复:DELETE 立即移除 session;开启请求被拒/失败/取消时丢弃新建 session;创建锁仅覆盖准入阶段,慢客户端不再阻塞其他客户端。

注意事项:升级后仍存在“initialize 成功但客户端在使用 session id 前死亡”的 case,依赖默认 30 分钟空闲过期(session_idle_timeout=)和并发 session 上限(max_sessions=)来兜底。若升级后回归测试仍能捕获残留 session,应按评论建议开新 Issue 反馈。Issue 中的应用层 orphan cleanup 属于临时方案,不是认证或资源配额机制。

问题场景

在使用 MCP Python SDK 的 stateful Streamable HTTP transport 时,服务端对真实 MCP readiness probe 或普通短生命周期客户端提供有状态会话。用户发现在以下场景会出现 session 生命周期异常:客户端通过 DELETE 关闭会话后条目仍留在 session manager 的内部注册表中;开启请求(如使用非法 Host)在注册 session 之后被校验拒绝,客户端拿不到 session id;初始化过程中被中断或超时;以及某个慢/卡住的开启请求长时间占用会话创建路径,阻塞其他无关客户端的初始化。

报错原文

Streamable HTTP session lifecycle can retain unreachable sessions and serialize session creation behind slow requests

原因分析

根据 Issue 与评论,可能原因有三类,均已在后续版本修复:

  • 会话关闭路径未同步清理:客户端发送 DELETE 后 session 被标记关闭,但未从 session manager 的内部注册表中移除,短生命周期会话反复出现时会累积。
  • 注册时机过早:新 session 可能在开启请求最终通过校验之前就被注册到服务端,一旦请求随后失败、被拒(如非法 Host)或被取消,客户端拿不到 session id,也就无法发送 DELETE,服务端保留了一个任何客户端都无法清理的会话。
  • 创建路径使用共享同步:慢请求或停滞的开启请求会长时间持有会话创建路径,延迟其他客户端的 session 创建。

环境排查

  • 确认 MCP Python SDK 版本:Issue 中复现版本为 mcp==1.27.1;修复版本为 2.2.0(PR #3395)与 1.30.0(backport PR #3426)。
  • 确认为 stateful Streamable HTTP transport(stateless 模式不涉及 session 注册表)。
  • 确认服务端是否自行实现了 session 清理 / orphan cleanup 逻辑。
  • 确认是否存在可能触发初始化失败的外部条件:反向代理 Host 头、readiness probe 超时或被杀、客户端在 initialize 完成前断开。
  • 确认是否有慢客户端在上传或停滞,可能占用会话创建路径。
  • Issue 未提供操作系统、Python 版本、CUDA、PyTorch、显卡等信息,无需在这些维度上比对。

解决步骤

  1. 将 MCP Python SDK 升级到 1.30.0 或 2.x,这两个版本包含了针对上述三类行为的修复。
  2. 确认修复点生效(对照 PR #3395 与 #3426 的描述):DELETE 后 session 立即从 manager 移除;开启请求被拒/失败/取消时丢弃其创建的 session;创建锁仅覆盖准入阶段,开启请求在锁外处理。
  3. 针对“initialize 成功但客户端在使用 session id 前死亡”的残留场景,依赖 SDK 自带的空闲过期与并发上限兜底:默认 session_idle_timeout= 为 30 分钟(无 in-flight 请求的 stateful session 会被关闭),并可通过 max_sessions= 限制并发会话数。
  4. 升级后移除应用层的 orphan cleanup workaround,以及专门用于检测 SDK 保留已关闭 session 的回归测试。
  5. 若回归测试在升级后仍能捕获残留 session,按评论建议开新 Issue 并附上该测试。

验证方法

按 Issue 中评论描述的三个修复点逐项验证:

  • 客户端发送 DELETE 后,session manager 的内部注册表中不再存在该 session。
  • 使开启请求被拒绝、失败或被取消(例如非法 Host、初始化中途中断),确认服务端不再保留该 session。
  • 制造一个慢/停滞的开启请求,确认其他客户端创建 session 不受其阻塞。
  • 对“initialize 成功但客户端未使用 session id”的场景,确认默认 30 分钟空闲过期会关闭该 session,且并发数达到 max_sessions= 时有上限保护。
  • 将应用层 orphan cleanup 关掉后,原回归测试应不再触发残留告警。

参考来源

modelcontextprotocol/python-sdk #3605

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 27667

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注