环境
- octop 0.9.28(self-hosted,TencentOS)
- 连接器:GitHub Copilot MCP(builtin
github)+ 自定义 stdio MCP
现象
日志里 mcp.client.streamable_http 每 ~10 秒循环刷:
INFO httpx — POST https://api.githubcopilot.com/mcp/ "HTTP/1.1 200 OK"
INFO mcp.client.streamable_http — Received session ID: d1d45fa5-...
INFO httpx — GET https://api.githubcopilot.com/mcp/ "HTTP/1.1 405 Method Not Allowed"
INFO mcp.client.streamable_http — GET stream disconnected, reconnecting in 1000ms...
INFO httpx — DELETE https://api.githubcopilot.com/mcp/ "HTTP/1.1 204 No Content"
(~10s 后新 session,循环)
每次新建 MCP session(agent 加载连接器/工具缓存失效/探针)都会重复:2 次注定失败的 GET + 重连退避 + 误导性的「disconnected」日志,看起来像网络故障,实际服务器行为完全符合 spec。
根因
GitHub Copilot MCP 端点不支持 GET SSE(对 GET 返回 405,这是 Streamable HTTP spec 里服务器声明「无 server→client SSE 流」的标准方式)。mcp SDK 的 handle_get_stream 把 405 当普通断线重试,而不是终态。
已向 python-sdk 提交修复 PR:**https://github.com/modelcontextprotocol/python-sdk/pull/3420**(405 → 记一条日志、禁用本 session 的 GET 流,不再重试;其他错误保持原有有界重试)。
建议
- 跟进合并上游 mcp SDK 的 405 修复(PR #3420)后升级依赖即可根治;
- 过渡期缓解:可考虑在 octop 初始化 MCP 客户端时对
mcp.client.streamable_http logger 降级(WARNING),或在连接器健康详情里标注「该服务器不支持 GET SSE(正常)」,避免用户误判为网络故障。
另外报告一个同一台机器上观察到的相关但独立的问题(有需要我再展开):自定义 stdio MCP 的调用被 mcp_tool_cache.wrap_tools_for_shared_use 的用户级锁串行化,一个长调用(如 600s 的任务)会阻塞该用户所有聊天窗口的所有 MCP 工具调用,且 MCP 客户端无请求级超时;回合被取消后共享 stdio session 被杀,但缓存的工具包装器仍指向死会话,后续调用全部 McpError: Connection closed,直到缓存失效或重启。
环境
github)+ 自定义 stdio MCP现象
日志里
mcp.client.streamable_http每 ~10 秒循环刷:每次新建 MCP session(agent 加载连接器/工具缓存失效/探针)都会重复:2 次注定失败的 GET + 重连退避 + 误导性的「disconnected」日志,看起来像网络故障,实际服务器行为完全符合 spec。
根因
GitHub Copilot MCP 端点不支持 GET SSE(对 GET 返回 405,这是 Streamable HTTP spec 里服务器声明「无 server→client SSE 流」的标准方式)。mcp SDK 的
handle_get_stream把 405 当普通断线重试,而不是终态。已向 python-sdk 提交修复 PR:**https://github.com/modelcontextprotocol/python-sdk/pull/3420**(405 → 记一条日志、禁用本 session 的 GET 流,不再重试;其他错误保持原有有界重试)。
建议
mcp.client.streamable_httplogger 降级(WARNING),或在连接器健康详情里标注「该服务器不支持 GET SSE(正常)」,避免用户误判为网络故障。另外报告一个同一台机器上观察到的相关但独立的问题(有需要我再展开):自定义 stdio MCP 的调用被
mcp_tool_cache.wrap_tools_for_shared_use的用户级锁串行化,一个长调用(如 600s 的任务)会阻塞该用户所有聊天窗口的所有 MCP 工具调用,且 MCP 客户端无请求级超时;回合被取消后共享 stdio session 被杀,但缓存的工具包装器仍指向死会话,后续调用全部McpError: Connection closed,直到缓存失效或重启。