十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Qwen Code Daemon MCP 强制重连机制详解:让外部写入的 OAuth 凭据即时生效

Qwen Code Daemon MCP 强制重连机制详解:让外部写入的 OAuth 凭据即时生效 Qwen Code Daemon MCP 强制重连机制详解让外部写入的 OAuth 凭据即时生效【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code导读Qwen Code 的 daemon 服务通过POST /workspace/mcp/reload重载持久化的 MCP 设置但该接口默认只做增量调和——设置未变化的 MCP 服务器会保留既有传输连接导致其他进程如另一个 Qwen Code 实例新写入的 OAuth 凭据迟迟无法被读取。本文围绕 docs/design/2026-07-22-daemon-mcp-force-reconnect.md 的设计方案结合路由、ACP bridge 与 daemon 核心实现源码完整讲解forceReconnectAll/forceReconnectWhich两个强制重连参数的设计动机、HTTP API 契约、底层执行路径与测试验证帮助你掌握凭据外部更新后如何让 MCP 服务器立即重连生效的实战方法。一、问题背景增量调和为何读不到新凭据1.1 默认 reload 的增量语义daemon 的 MCP reload 接口默认行为是重新读取持久化设置settings 文件中的mcpServers、mcp.allowed/mcp.excluded等然后将这些设置增量地同步到 workspace 配置、活动会话配置与 discovery 配置中。核心执行逻辑位于 packages/cli/src/acp-integration/acpAgent.ts 的reloadWorkspaceMcpDiscovery重新loadSettings读取最新设置将this.config、所有活动会话的 config 以及 workspace discovery config 汇总为liveConfigs集合逐个调用config.reinitializeMcpServers(mcpServers)做设置调和对已初始化的 LLM client 刷新工具集llmClient.setTools?.()。关键点在于设置没变的服务器其传输连接transport保持不变。调和只更新配置对象不会主动断开已有连接。1.2 典型故障场景OAuth 凭据被外部写入后不生效文档明确指出该缺陷某个 MCP 服务器启用了 OAuth 认证而 OAuth 凭据由另一个 Qwen Code 进程或外部工具通过 daemon 的 token storage 持久化写入。此时第一个进程的 MCP 服务器传输仍持有旧的或空的凭据状态调用POST /workspace/mcp/reload只会做设置调和由于该服务器设置未变化传输不会重建新写入的凭据要等到该传输自然重连如进程重启后才会被读取。这正是设计文档所描述的缺陷OAuth credentials written by another Qwen Code process are therefore not read until that transport reconnects.二、设计核心在调和之后显式触发重连2.1 两个互斥的可选参数设计文档给出的方案非常克制不改变默认 reload 行为而是为两条 reload 路由及其 SDK/ACP bridge 方法新增两个可选字段字段类型默认值含义forceReconnectAllbooleanfalse调和后强制重连 workspace 内所有已配置的 MCP 服务器forceReconnectWhichstring[]未提供调和后仅重连列表中指定的服务器名两个字段互斥同时提供时返回400错误码conflicting_force_reconnect_options。forceReconnectWhich只接受非空字符串数组任何元素类型不合法或为空字符串都返回400。2.2 执行顺序先调和再重连当任一重连选项被提供时daemon 的执行顺序是先执行正常的设置调和与默认 reload 完全一致再执行强制重连对池化服务器transport pool 中有条目按服务器名通过 workspace transport pool 重启一次随后刷新所有 live config 的模型工具快照setTools对没有池条目的服务器走既有的 per-config discovery 路径该路径会先断开连接、再重新连接、最后重新发现工具。2.3 刻意不做的事设计文档特别强调强制重连不会主动发起 OAuth 授权流程。它只是建立一个新连接而新连接会读取 daemon token storage 中当前已持久化的凭据。也就是说该机制解决的是凭据已写入、但连接未感知的同步问题而不是凭据尚未获取的授权问题。三、HTTP API 契约3.1 两条 reload 路由设计文档明确POST /workspace/mcp/reload与POST /workspaces/:workspace/mcp/reload均接受新参数且响应保持202 { accepted: true }——因为实际工作是排队异步执行的。全部重连示例curl -X POST http://127.0.0.1:port/workspace/mcp/reload \ -H Authorization: Bearer token \ -H Content-Type: application/json \ -d { forceReconnectAll: true }按名称选择性重连curl -X POST http://127.0.0.1:port/workspace/mcp/reload \ -H Authorization: Bearer token \ -H Content-Type: application/json \ -d { forceReconnectWhich: [github, jira] }多 workspace 形态daemon 运行多个 workspace runtime 时将路径替换为/workspaces/:workspace/mcp/reload语义与请求体完全一致。3.2 参数校验与错误码从 packages/cli/src/serve/routes/workspace-mcp-control.ts 的parseMcpReloadOptions可以拿到完整校验规则非法输入HTTP 状态错误码说明forceReconnectAll不是 boolean400invalid_force_reconnect_all_flag仅接受true/falseforceReconnectWhich不是数组或含非字符串/空字符串元素400invalid_force_reconnect_which必须是非空服务器名数组同时提供forceReconnectAll: true与forceReconnectWhich400conflicting_force_reconnect_options两字段互斥值得注意的细节forceReconnectAll: false与forceReconnectWhich同时提供时由于只有true才算启用互斥因此false与forceReconnectWhich可以共存forceReconnectWhich: []空数组虽然能通过结构校验但语义上是不选择任何服务器。另外 workspace runtime 形态workspace-runtime-mcp.ts使用同一套校验规则仅错误消息措辞略有不同Reconnect options cannot be combined错误码保持一致。3.3 响应语义两条路由以及 runtime 变体成功时均返回202 { accepted: true }202 Accepted而非200明确表示任务已被接收并排队执行调用方需要通过 workspace MCP status 接口观察重连与工具发现的最终结果。四、源码级实现剖析4.1 ACP bridge 接口强制重连选项通过 ACP bridge 的reloadWorkspaceMcp方法下发给 daemon 子进程接口定义位于 packages/acp-bridge/src/bridgeTypes.ts/** Reload persisted MCP settings into workspace and active session configs. */ reloadWorkspaceMcp(options?: { forceReconnectAll?: boolean; forceReconnectWhich?: string[]; }): Promise{ accepted: boolean };HTTP 层解析出的选项被直接透传给该方法路由本身不做业务判断保证 HTTP 契约与 bridge 协议严格对齐。4.2 路由层解析与转发workspace-mcp-control.tsPOST /workspace/mcp/reload先做 generation guard 与 workspace 信任校验未信任的 workspace 返回403 untrusted_workspace再解析选项并调用bridge.reloadWorkspaceMcp(options)同文件 L401-L423POST /workspaces/:workspace/mcp/reload通过 workspace registry 解析对应 runtime调用runtime.bridge.reloadWorkspaceMcp(options)workspace-runtime-mcp.tsruntime 形态的POST /workspace/runtime/mcp/reload需要 runtime coordinator 支持否则501 workspace_runtime_not_supported并通过runMcpRuntimeMutation串行化 MCP 变更。两条 workspace reload 路由共用parseMcpReloadOptions确保校验逻辑单一来源。4.3 daemon 核心forceReconnectWorkspaceMcp真正的重连逻辑在 acpAgent.ts 的forceReconnectWorkspaceMcp收集服务器名集合遍历 discovery config、主 config 与所有活动会话 config 的getMcpServers()得到全量服务器名筛选目标若提供了requestedServerNames去重后仅保留在集合中的名称否则重连全部逐服务器执行池化路径通过mcpPool.getSnapshot().byName[serverName]?.entryCount 0判断是否有池条目有则调用mcpPool.restartByName(serverName)重启传输同文件 L4124-L4141若返回结果中存在restarted: false则抛出错误重启成功后对getLiveMcpConfigs(serverName)中的每个已初始化 LLM client 调用setTools()刷新工具快照discovery 路径无池条目时调用reconcileMcpServerAcrossLiveConfigs(serverName, discover)走既有的断开→重连→重新发现流程错误聚合任何服务器失败都会被收集最终以AggregateError抛出消息为Failed to force reconnect one or more MCP servers保证部分失败不会静默吞掉。同时reloadWorkspaceMcpDiscoveryL4093-L4098确保强制重连一定发生在设置调和成功之后只有当options.forceReconnectAll true或options.forceReconnectWhich ! undefined时才进入重连阶段且调和阶段任何 config 同步失败都会先抛错中止。4.4 与其他重连能力的边界本项目还存在POST /workspace/mcp/:server/restart按 entryIndex 重启单个服务器返回200与POST /workspace/runtime/mcp/:server/restart等接口。与它们相比force reconnect 是reload 语义的扩展保持202异步排队、先调和后重连、以服务器名为粒度两者适用场景不同restart 面向单服务器单条目的精细控制force reconnect 面向凭据/设置刷新后让一批服务器整体重建连接的批量场景。五、测试验证5.1 路由层测试packages/cli/src/serve/server.test.ts 的forwards reconnect options and rejects invalid values覆盖了完整矩阵空请求体 →202bridge 收到{ forceReconnectAll: undefined, forceReconnectWhich: undefined }默认转发语义{ forceReconnectAll: true }→202bridge 收到true{ forceReconnectWhich: [docs] }→202bridge 收到对应数组{ forceReconnectWhich: [docs, 1] }混入非字符串→400 invalid_force_reconnect_which且不会调用 bridge{ forceReconnectAll: true, forceReconnectWhich: [docs] }互斥冲突→400 conflicting_force_reconnect_options同样不调用 bridge。5.2 ACP/daemon 层测试packages/cli/src/acp-integration/acpAgent.test.ts 验证了从workspaceMcpReload扩展方法到实际重连行为的传播链路传入{ forceReconnectWhich: [runtime] }后forceDiscover(runtime)被调用discovery 路径传入{ forceReconnectAll: true }后对集合中的secondary服务器也触发forceDiscover(secondary)。同一测试文件还覆盖了 safe/bare 模式下的守卫行为L28211 起reload 路径不会把settings.mcpServers/mcp.allowed泄漏进已运行的 safe/bare 会话保证强制重连不会绕过安全模式对本地设置的信任边界。六、实战建议与注意事项6.1 推荐使用时机外部凭据写入后当另一个 Qwen Code 进程或外部工具通过 daemon token storage 更新了某服务器的 OAuth 凭据调用 reload 时带上forceReconnectWhich: [该服务器名]将重连影响面收敛到最小批量刷新设置文件批量变更、或不确定哪些服务器依赖新凭据时使用forceReconnectAll: true一次性重建全部连接自动化脚本集成配合202 { accepted: true }的异步语义脚本应在调用后轮询 workspace MCP status 端点确认目标服务器mcpStatus恢复为connected且工具列表已刷新而不是假设重连立即完成。6.2 注意事项不触发授权该机制只建立新连接以读取已持久化的凭据不会弹出 OAuth 授权流程若凭据本身尚未获取请先走POST /workspace/mcp/:server/authenticate流程部分失败可见任一服务器重连失败会以AggregateError形式暴露在队列任务中生产环境应关注 daemon 日志中的Failed to force reconnect one or more MCP servers聚合错误互斥约束forceReconnectAll与forceReconnectWhich不可同时使用接口层会在 400 响应中明确告知冲突原因。结语从设计文档到实现Qwen Code 的 daemon MCP 强制重连是一套克制的增量扩展默认 reload 语义完全不变仅在显式传入forceReconnectAll/forceReconnectWhich时于设置调和之后按服务器名粒度重建连接并复用 transport pool 与 discovery 两条既有路径。配合完整的 400 校验矩阵与路由/ACP 双层测试它为OAuth 凭据被外部写入后立即生效这一真实工程场景提供了清晰、可验证的解决方案。深入阅读 设计文档、路由实现 与 daemon 核心逻辑即可完整掌握其内部机制。【免费下载链接】qwen-codeAn open-source AI coding agent that lives in your terminal.项目地址: https://gitcode.com/GitHub_Trending/qw/qwen-code创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表