修复MCP服务器的 stale 会话异常关闭传输层有关问题 - #105
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
MCP 服务连接稳定性修复报告
问题描述
MCP(Model Context Protocol)服务的外部客户端连接频繁断开,表现为:
根因分析
通过审计 MCP 服务的会话管理、传输层生命周期和编辑器注册机制,发现以下关键问题:
1. Stale 会话不关闭传输层(主因)
markMcpSessionStale()只标记会话为 stale 并取消挂起的调用,但不关闭底层传输层。客户端继续发送请求,每次都收到 stale 错误响应,表现为"连接活着但不能用"。2. 编辑器在线租约过短
ONLINE_MS = 35_000(35秒)与轮询预算EDITOR_POLL_BUDGET_MS = 25_000(25秒)过于接近。在慢网络或浏览器高负载时,lastSeen刷新可能延迟,导致编辑器被错误标记为离线。3. 取消通知轮询不刷新租约
nextEditorCancellation()不调用touchEditor(),空闲编辑器在等待取消通知时在线租约过期。4. 会话清理缺少异常防护
pruneMcpSessions()在setInterval中直接调用,无 try/catch。一次异常会导致清理循环永久停止,空闲会话无法回收。5. 初始化回调中的竞态
onsessioninitialized回调中同步调用pruneMcpSessions(),并发初始化可能导致刚创建的会话被意外淘汰。修复内容
文件变更
server/external-agent/mcp.tsserver/external-agent/broker.tsnextEditorCancellation添加touchEditor调用server/external-agent/broker-registry.tsONLINE_MS从 35s 增至 45sserver/external-agent/mcp.verify.ts详细修改
mcp.ts
stale 错误后关闭传输层(
CallToolRequestSchemahandler)markMcpSessionStale后通过delayImmediate延迟关闭server或transportonsessioninitialized异步化裁剪pruneMcpSessions调用包裹在delayImmediate().then(...)中setInterval添加 try/catchbroker.ts
nextEditorCancellation刷新在线租约touchEditor()刷新lastSeenbroker-registry.ts
ONLINE_MS从35_000(35秒)增至45_000(45秒)测试验证
所有现有测试通过:
影响评估
nextEditorCancellation每次调用增加一次touchEditor开销(轻量级内存操作)pruneMcpSessions异步化后,极端情况下空闲会话清理延迟最多一个事件循环tick