dev-manager-tauri/.blueprint/modules/mcp-single-server.md
lanrtop df7d52a084
All checks were successful
Push & PR Check / check (push) Successful in 1m6s
Push & PR Check / check (pull_request) Successful in 49s
feat(mcp): T6 删除旧 /mcp/group 路由与兼容层——提前并入本次发版
原计划后置一个版本,经评估提前:迁移在新版启动时自动重写全部
客户端配置(settings.json/liangjing.json/全局注册),旧路由的实际
消费者只剩升级前的存量会话,而服务重启后它们本就断开重连。
单人环境下双路由过渡的保留价值趋近于零,一次收口减少一轮发版。

- tools_call 签名去 Option 组上下文,process_rpc 单参数化
- list_group_projects 的 group_id 改为 required 参数
- grep 'mcp/group' src-tauri/src/ 零命中,cargo test 93 全绿
2026-07-06 19:34:51 +09:00

8.8 KiB
Raw Blame History

MCP 单一服务器化

将组级挂载的 lian-jing-{group_id}(每产品组一个 MCP 服务器)收敛为单一全局 lian-jing 服务器。

为什么

  • 摩擦随项目数复利增长,与飞轮方向相反:每新增一个产品组 = 多一次 claude mcp add + 多一个授权单元 + 每个会话多一份重复工具清单(现状 12 组 × 28 工具 ≈ 300+ 工具注册)。炼境目标是"管理项目越多 → agent 辅助越强",客户端配置成本必须是 O(1)。
  • 组级挂载没有真正的隔离价值2026-07-06 实测任意组服务器可对任意项目执行 inject_mcp;组归属校验只覆盖部分工具(半吊子状态)。
  • 消除 group_id 身份卡问题:单一服务器后 liangjing.json 只需 project_idgroup_id 缺失/过期/移组同步这一整类问题从根上消失。

设计决策2026-07-06 /architect

方案选择

  • A. 直接切换:加全局路由同时删旧路由 —— 所有存量会话立刻断链,故障静默
  • B. 双路由过渡(选定):新增全局 /mcp 路由,旧 /mcp/group/:gid 保留兼容;注入逻辑切到新名字;批量迁移后旧路由在后续版本删除
  • C. 全局 alias 与组服务器并存 —— 不消除 O(N) 注册,白改

核心接口变更

  1. 路由mcp_server.rs):新增 POST/GET /mcp + POST /mcp/messagesprocess_rpc 的组上下文改为 Option<String>(旧路由 Some(gid),新路由 None
  2. 工具层mcp_tools.rs
    • resolve_project_root(project_id) 去组化——直查 project_workspaces,删除 JOIN project_group_map 的归属过滤
    • get_project_mentor_context / append_project_note / get_project_snapshots 三处 membership check 删除(改为项目存在性检查)
    • list_group_projects 新增可选参数 group_id:显式参数 > 挂载上下文(旧路由)> 报错提示传参;tools_list_result schema 同步
  3. 注入层mcp_inject.rs
    • inject_project_mcp(project_id) 去掉 group_id 参数settings.json 写入 key "lian-jing"、URL http://127.0.0.1:{port}/mcp
    • 注入时顺手删除同文件中所有 lian-jing:group-* 旧 key迁移内建于重注入reinject_all_mcp 即批量迁移器)
    • liangjing.json 只写 project_id + mcp_port主动删除已有 group_id 键(避免过期数据)
    • 全局注册收敛为一次 claude mcp add lian-jing;新增迁移函数清理旧注册——遍历 product_groups,对完整 UUID 名和短 8 位名两种格式各尝试 claude mcp remove -s user(幂等,失败仅记日志)
    • remove_group_member 语义修正:项目退出某组时,仅当它不再属于任何组才移除 "lian-jing" key
  4. 附带收益inject_mcp 不再要求项目必须属于产品组("未加入任何产品组"报错可移除),未分组项目也能接入

受影响文件

  • 修改:src-tauri/src/mcp_server.rs — 新增全局路由process_rpc 组上下文 Option 化
  • 修改:src-tauri/src/mcp_tools.rs — resolve_project_root 去组化、3 处校验删除、list_group_projects 参数化、schema 更新、inject_mcp 分支简化
  • 修改:src-tauri/src/mcp_inject.rs — key/URL/注册收敛、旧 key 清理、liangjing.json 瘦身、全局旧注册迁移函数
  • 修改:src-tauri/src/commands/groups.rs — inject 调用签名、remove_group_member 条件移除
  • 修改:src/components/settings/SettingsPage.tsx:537 — URL 展示改为 /mcp
  • 修改:docs/ai-context/git-workflow.md + src-tauri/resources/onboarding/git-workflow.md.tmpl — 寻址说明改写
  • 修改:.claude/skills/retro-catchup/SKILL.md — 解析 lian-jing:group- 前缀的逻辑改为 lian-jing
  • 修改:.blueprint/modules/mcp-config-inject.md — 补注记:组级 key 方案已被本模块取代
  • 仓库外(执行阶段处理):~/.claude.json 12 条旧注册清理、~15 个项目 settings.json/liangjing.json 批量重注入、用户全局 ~/.claude/CLAUDE.md 炼境规则段改写

迁移顺序(切换编排)

  1. 代码落地(双路由并存,零破坏)→ cargo test + curl 冒烟新路由
  2. 全局注册 lian-jing + 清理旧注册(新会话立即可用单服务器)
  3. reinject_all_mcp 批量刷新存量项目settings.json 换 key、liangjing.json 去 group_id
  4. 文档/模板/技能/用户全局规则同步
  5. 抽查验证3 个项目文件内容 + claude mcp list 只剩 lian-jing + 新会话实调 get_ci_status 走通
  6. (后置卡,下个版本)删除旧 /mcp/group/:gid 路由与 Option 兼容层

风险点

  • 存量会话断链 → 双路由并存规避,旧路由删除后置一个版本
  • claude mcp remove 部分失败 → best-effort + 日志,输出手动清理命令清单兜底
  • 误删用户自有 mcpServers 配置 → 只删 lian-jing:group- 前缀 key沿用现有精确删除机制
  • webhook 已核实不受影响(路由 /webhook/gitea/:project_id 不含 group_id

任务卡

T1. 服务器层双路由:全局 /mcp + 组上下文 Option 化

  • status: done
  • complexity: M
  • files: src-tauri/src/mcp_server.rs
  • acceptance: "[HTTP] POST http://127.0.0.1:{port}/mcp (initialize) → 200 且 serverInfo.name=炼境GET /mcp 返回 SSE 事件流endpoint 指向 /mcp/messages"
  • done_note: 2026-07-06 完成。process_rpc 驻军测试覆盖握手路径cargo test 全绿HTTP 层实测归入 T4需新二进制运行。注T6 随后并入同一发版,双路由过渡态只存在于中间 commit

T2. 工具层去组化resolve_project_root 按 project_id 直查

  • status: done
  • complexity: M
  • files: src-tauri/src/mcp_tools.rs
  • depends: T1
  • acceptance: "[HTTP] 经 /mcp 调 get_project_blueprint(project_id) → 返回 manifest 内容,无'不属于产品组'错误list_group_projects(group_id=xxx) 显式传参 → 返回成员列表cargo test 全绿"
  • done_note: 2026-07-06 完成。resolve_project_root 直查 project_workspaces3 处组归属校验替换为 ensure_project_existslist_group_projects schema 改 required group_id。HTTP 实测归入 T4

T3. 注入层收敛lian-jing 单 key + 旧配置清理 + liangjing.json 瘦身

  • status: done
  • complexity: M
  • files: src-tauri/src/mcp_inject.rs, src-tauri/src/mcp_tools.rs, src-tauri/src/commands/groups.rs, src-tauri/src/commands/projects.rs, src-tauri/src/lib.rs
  • depends: T1
  • acceptance: "[Tauri command] inject_project_mcp(pid) → 项目 settings.json 含 key "lian-jing"URL 以 /mcp 结尾)且无 lian-jing:group-* 残留liangjing.json 含 project_id+mcp_port 且 group_id 键被删除remove_group_member 仅在项目不属于任何组时移除 keycargo test 全绿"
  • done_note: 2026-07-06 完成。额外实现 migrate_to_single_server 启动时一次性迁移(标记位 mcp_single_migratedclaude CLI 缺失时不落标记等重试delete_group/remove_group_member 加"仍属其他组则保留"判断;文件实测归入 T4

📋 T4. 存量批量迁移执行 + 端到端验证

  • status: todo
  • complexity: S
  • files: (执行操作,无新代码——迁移在新版启动时自动执行)
  • depends: T1, T2, T3, T6需先构建 + 重启炼境运行新二进制)
  • acceptance: "[CLI] claude mcp list → lian-jing-* 旧条目清零、仅剩 lian-jing[MCP] 抽查 3 个项目(含本项目 + enterprise-systemsettings.json/liangjing.json 符合新格式;新 Claude 会话经 lian-jing 实调 get_diagnostics → 返回 JSON 无 error[HTTP] POST /mcp/group/{gid} → 404"

T5. 文档/模板/技能/UI 寻址说明同步

  • status: done
  • complexity: S
  • files: docs/ai-context/git-workflow.md, src-tauri/resources/onboarding/git-workflow.md.tmpl, .claude/skills/retro-catchup/SKILL.md, src/components/settings/SettingsPage.tsx, .blueprint/modules/mcp-config-inject.md
  • depends: T3
  • acceptance: "[Bash] grep -rE 'lian-jing-\{group_id\}|lian-jing:group-' docs/ src/ src-tauri/resources/ → 零命中mcp-config-inject.md 保留历史注记除外pnpm typecheck 通过"
  • done_note: 2026-07-06 完成。grep 零命中、typecheck 通过;用户全局 ~/.claude/CLAUDE.md 炼境规则段已同步改为单一 lian-jing 寻址

T6. 删除旧 /mcp/group 路由与兼容层

  • status: done
  • complexity: S
  • files: src-tauri/src/mcp_server.rs, src-tauri/src/mcp_tools.rs
  • depends: T3
  • acceptance: "cargo test 全绿grep 'mcp/group' src-tauri/src/ 零命中;[HTTP] POST /mcp/group/{gid} → 404归入 T4 实测)"
  • done_note: 2026-07-06 完成。原计划后置一个版本经评估提前并入本次发版迁移在新版启动时自动重写全部客户端配置旧路由的实际消费者只剩升级前的存量会话服务重启后本就断开单人环境保留价值趋近于零。tools_call 签名去 Option 化list_group_projects 改 required 参数