Skip to content
FunCoding

Search

Search docs, Skills and MCP

MCP 连接池与生命周期

理解共享 transport、会话视图、重启以及空闲回收的实际条件。

This page has not been translated into English yet. The original Chinese version is shown below.

McpTransportPool 在同一工作区 ACP child 中共享 MCP transport,避免每个逻辑会话都启动一套相同服务。每个 workspace runtime 有独立池;未启动的未信任 secondary 不会拥有活动池。

连接与会话分开

共享键是 server name 加 config fingerprint。相同键的并发 acquire 共用 spawnInFlight promise;连接成功后,各 session 建立自己的 SessionMcpView 和工具/提示注册视图。

一个会话发现工具不会直接把工具注册到所有其他会话。includeTools/excludeTools 可在会话视图应用,而 transport 和 canonical snapshot 继续共享。键的具体字段见配置指纹。

默认共享 stdio 与 websocket。HTTP/SSE 默认不共享,因为 header 可能带会话 OAuth 状态;可通过 QWEN_SERVE_MCP_POOL_TRANSPORTS 明确选择。SDK MCP 不参与共享。

受 pool 管理的非共享连接生命周期随对应 session,最后 detach 时及时关闭;非共享不等于绕过 workspace budget。独立 CLI/SDK 的其他管理路径仍有自己的 manager 预算,见预算控制。

Entry 状态与反向索引

entry 维护 spawning、active、draining、closed、failed 状态、session refs 和 generation。sessionToEntries 反向索引让 releaseSession 只遍历该 session 引用的 entry,不扫描整个池。

初始化失败要回滚预算;已被关闭或失败的 entry 不能在迟到 connect/discovery 返回后重新变成 active。每个 await 后的生命周期检查用于防止向已经关闭的 session 注册工具。

两个空闲计时器

最后一个 ref 离开时,默认启动 30 秒 drain grace;再次 attach 会取消该 grace。另有从首次 idle 开始的 5 分钟 max-idle 计时器,普通 attach/detach 不会不断推迟它。

但“5 分钟硬期限”不能理解为到点强杀正在使用的连接:当前源码在计时器触发时重新检查 refs;若仍有活动 session,保留连接并清空 firstIdleAt,使下次 idle 有新的窗口。只有触发时没有 refs 才执行 max_idle 强制关闭。

restart 会清除两个旧计时器、重置 firstIdleAt,并将 draining 转回 active,避免重连过程中旧 timer 杀掉新 transport。官方总述中不带这一活动引用条件的“绝不重置”说法不宜照搬。

断线与重启

默认 stdio/websocket 重连策略为固定 5 秒、最多 3 次;HTTP/SSE 为从 1 秒到 16 秒的指数间隔、最多 5 次。具体配置可由 PoolEntryOptions 调整。

静默断线时先发 failed,再解除 subscriber view,使挂起 callTool 可收到 MCPCallInterruptedError,而不是永远等待。McpClient.lastTransportError 用于保留最近的传输失败原因,connect 开始会清空它。

restartByName 可选择 entryIndex;未指定时针对同名 entry。单项结果与多项 entries 数组形状不同,调用者应据 capability 和实际返回处理。generation 在重启时变化;entryIndex 是创建时分配的稳定标识,不是数组位置。

Drain 与子进程

drainAll 进入单向 draining 状态并拒绝新 acquire;继续工作需要新池。正常 ACP/IDE 连接结束和进程退出都应触发 drain,不只依赖 SIGTERM。

stdio 子进程的后代清理使用一次进程表快照加树遍历,必要时回退逐 PID 查询;最多 256 个后代、深度 8,属于有界清理而非无限进程追踪。snapshot.subprocessCount 只计 stdio,websocket/HTTP/SSE 连接远端服务,不等于本机子进程。