Skip to content

修复MCP服务器的 stale 会话异常关闭传输层有关问题 - #105

Merged
0xsline merged 1 commit into
0xsline:mainfrom
yauntyour:main
Aug 24, 2026
Merged

修复MCP服务器的 stale 会话异常关闭传输层有关问题#105
0xsline merged 1 commit into
0xsline:mainfrom
yauntyour:main

Conversation

@yauntyour

Copy link
Copy Markdown
Collaborator

MCP 服务连接稳定性修复报告

问题描述

MCP(Model Context Protocol)服务的外部客户端连接频繁断开,表现为:

  • 客户端会话突然变为 stale,后续所有请求被拒绝
  • 编辑器被错误地标记为离线,导致 MCP 会话失效
  • 空闲会话无法被正确清理,占用内存

根因分析

通过审计 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.ts stale 会话关闭传输层、prune 异步化、setInterval try/catch
server/external-agent/broker.ts nextEditorCancellation 添加 touchEditor 调用
server/external-agent/broker-registry.ts ONLINE_MS 从 35s 增至 45s
server/external-agent/mcp.verify.ts 更新 stale 会话测试用例

详细修改

mcp.ts

  1. stale 错误后关闭传输层CallToolRequestSchema handler)

    • markMcpSessionStale 后通过 delayImmediate 延迟关闭 servertransport
    • 确保错误响应先发送,再关闭连接
  2. onsessioninitialized 异步化裁剪

    • pruneMcpSessions 调用包裹在 delayImmediate().then(...)
    • 避免初始化回调阻塞和并发竞态
  3. setInterval 添加 try/catch

    • 防止单次异常导致清理循环停止

broker.ts

  1. nextEditorCancellation 刷新在线租约
    • 在函数开头调用 touchEditor() 刷新 lastSeen
    • 防止空闲编辑器在等待取消通知时被标记为离线

broker-registry.ts

  1. 增大编辑器在线租约
    • ONLINE_MS35_000(35秒)增至 45_000(45秒)
    • 为慢网络和浏览器主线程阻塞提供 10 秒缓冲

测试验证

所有现有测试通过:

✓ mcp-check.verify.ts
✓ mcp-tool-exposure.verify.ts
✓ mcp.verify.ts
✓ broker.verify.ts
✓ broker-poll-refresh.verify.ts
✓ external-agent.verify.ts
✓ offline-mcp.verify.ts
✓ offline-mcp-process-recovery.verify.ts
✓ oxlint(无错误)

影响评估

  • 向后兼容:stale 会话行为变更(从持续返回 stale 错误变为关闭连接),客户端需要处理连接断开并重建会话
  • 性能影响nextEditorCancellation 每次调用增加一次 touchEditor 开销(轻量级内存操作)
  • 内存pruneMcpSessions 异步化后,极端情况下空闲会话清理延迟最多一个事件循环tick

@0xsline
0xsline merged commit 768eafc into 0xsline:main Aug 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants