You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[code-review] MCPManager.Close kills the stdio clients but never unregisters their tools from the Handler-shared registry (the plugin path has the correct Unregister loop; #751's own comment says close prevents tools lingering but only fixed the process leak), and adapter RegisterTools silently skips on name collision - so after closing a session, any later session reusing the same server name (Zed sends MCPServers per tab) gets zero tools while dead-session tools stay exposed; session/load top-level path skips SetSaveDir unlike its three sibling registration sites, so Save writes <id>.json into the process CWD and the real store goes stale; process_other.go tags !unix but uses Windows-only syscall fields #1477
文件行号
internal/acp/mcp_bridge.goL81-91(Close() 只关 clients 清两个 slice——无任何 registry.Unregister;Adapter 亦无反注册方法——grepfunc (a *Adapter)仅 5 个方法)+ handler.go L49/L305/L348/L980(toolRegistry 为 Handler 级共享字段,同 ACP 连接所有 session 的 agent loop 共读);tool/tool.go L118-126(Register 重名报错)+ mcp/adapter.go L71-74("name collision is non-fatal" debug.Log 后 skip——注册方零感知)+ handler.go L703-707(session/close 调 Close)+ L972-979(#751 注释原文自称 Close 防 "its tools linger in the shared registry"——半吊子修复自证:只修了进程泄漏一半);handler.go L500-515(顶层 LoadSession 成功后只注册两 map,缺 session.SetSaveDir(sessionDir))vs 三对照点(L296 session/new 有 ✅ / L645 workspace 扫描有 ✅ / 顶层 ❌)+ L628-632(注释自证同款 bug 机理只修了扫描分支)+ agent_loop.go L186/387(Save(SaveDir()) 无空守卫)+ session.go L174(Join("",id) 相对路径写 CWD);process_other.go L1(//go:build !unix)+ L28-31(CreationFlags/HideWindow/CREATE_NEW_PROCESS_GROUP Windows 专属)问题
案 A(High,跨 session 永久失效):MCPManager.Close 不反注册工具 + 重名静默 skip——同名 MCP server 的后续 session 全部瘫痪
session/new带MCPServers:[{name:"github"}]→ mcp__github__* 入共享 registry → A close(client 死,工具残留)→ session B 同名 github → RegisterTools 逐个撞名 → adapter skip → B 的健康 client 零工具注册、A 的死工具原样暴露——调用即 "connection closed";即使 B 用不同 server 名,A 的死工具仍作为幻觉可用工具暴露给 Bm.registry.Unregister(tn)——plugin 路径做了,acp 路径没做;[code-review] ACP session MCP servers closed after first prompt instead of session close - MCP tools dead on prompt #2 #751 注释明说 tools linger 但修复只覆盖进程泄漏修:Close 先收集 ToolNames() 再逐个 Unregister;同 server 名已存在视为替换而非 skip。
案 B(Med,写错位置+stale):session/load 顶层路径漏 SetSaveDir——Save("") 把会话写进进程 CWD、正式存储永远 stale
<id>.json(旧布局遗留 + cwd 为空的历史会话也落顶层)→ load 命中 L500 → prompt → agent_loop.go:387Save("")→ CWD 创建<id>.json(daemon 场景可能是/或家目录——污染+信息泄漏);compaction checkpoint(L186)同理丢失——重载回退压缩前历史修:L508-516 补 SetSaveDir;session.go Save 对 dir=="" 直接报错(根因防御)。
案 C(Low,降级——代码卫生):process_other.go
!unixtag 含 Windows 专属 syscall 字段修:tag 改 windows(防未来移植踩雷)。
干净项与附注
output_tail.go 整文件无问题。process_unix.go:Pdeathsig 缺失为与 mcp 共有的已知取舍(仅记录)。session.go:prompt 并发互斥(TryBeginRun CAS+EndRun panic 释放)/cancel 全持锁/AddMessage 锁内/LoadSession 不恢复运行态字段/原子写均无问题;Save() 双锁 TOCTOU(check-then-act 窗口——现调用方串行为潜伏 LOW)与 resume 换 servers 后落盘旧清单(MCPServers 不同步,LOW)为附注。mcp_bridge:ConnectServers 部分失败保留成功者/connectServer 错误路径清理/无缓存失效问题均无碍。
严重程度
High + Med + Low
独立复核确认:Close 原文与 Adapter 方法全集 grep、共享 registry 三引用点、#751 注释原文、plugin/mcp_loader.go:532 对照组、撞名 skip 链、三注册点对照与 L628-632 注释自证、SaveDir 消费点无守卫、Join("",id) 机理、四 GOOS 交叉编译矩阵(windows 过/其余依赖先炸)。修正初审一处不实:全仓 Unregister 调用实有 ~49 处,核心事实是 acp/MCP 路径零反注册。