All checks were successful
Push & PR Check / check (push) Successful in 49s
验证:~/.claude.json 仅剩 lian-jing(12 条旧注册清零)、3 项目抽查 新格式通过、新路由握手 + get_diagnostics 实调通过、旧路由 404。 T4 暴露 git-bash 硬编码存量 bug 已修(0d1427f)。 遗留:同路径重复登记(legacy id 与 uuid id 并存)待登记卫生清理。
9.6 KiB
9.6 KiB
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_id,group_id 缺失/过期/移组同步这一整类问题从根上消失。
设计决策(2026-07-06 /architect)
方案选择
- A. 直接切换:加全局路由同时删旧路由 —— ❌ 所有存量会话立刻断链,故障静默
- B. 双路由过渡(选定):新增全局
/mcp路由,旧/mcp/group/:gid保留兼容;注入逻辑切到新名字;批量迁移后旧路由在后续版本删除 - C. 全局 alias 与组服务器并存 —— ❌ 不消除 O(N) 注册,白改
核心接口变更
- 路由(
mcp_server.rs):新增POST/GET /mcp+POST /mcp/messages;process_rpc的组上下文改为Option<String>(旧路由Some(gid),新路由None) - 工具层(
mcp_tools.rs):resolve_project_root(project_id)去组化——直查project_workspaces,删除 JOINproject_group_map的归属过滤get_project_mentor_context/append_project_note/get_project_snapshots三处 membership check 删除(改为项目存在性检查)list_group_projects新增可选参数group_id:显式参数 > 挂载上下文(旧路由)> 报错提示传参;tools_list_resultschema 同步
- 注入层(
mcp_inject.rs):inject_project_mcp(project_id)去掉group_id参数;settings.json 写入 key"lian-jing"、URLhttp://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
- 附带收益:
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.json12 条旧注册清理、~15 个项目 settings.json/liangjing.json 批量重注入、用户全局~/.claude/CLAUDE.md炼境规则段改写
迁移顺序(切换编排)
- 代码落地(双路由并存,零破坏)→ cargo test + curl 冒烟新路由
- 全局注册
lian-jing+ 清理旧注册(新会话立即可用单服务器) reinject_all_mcp批量刷新存量项目(settings.json 换 key、liangjing.json 去 group_id)- 文档/模板/技能/用户全局规则同步
- 抽查验证:3 个项目文件内容 +
claude mcp list只剩lian-jing+ 新会话实调get_ci_status走通 - (后置卡,下个版本)删除旧
/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_workspaces;3 处组归属校验替换为 ensure_project_exists;list_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 仅在项目不属于任何组时移除 key;cargo test 全绿"
- done_note: 2026-07-06 完成。额外实现 migrate_to_single_server 启动时一次性迁移(标记位 mcp_single_migrated,claude CLI 缺失时不落标记等重试);delete_group/remove_group_member 加"仍属其他组则保留"判断;文件实测归入 T4
✅ T4. 存量批量迁移执行 + 端到端验证
- status: done
- complexity: S
- files: src-tauri/src/mcp_inject.rs(迁移暴露 git-bash 探测 bug,修复见 0d1427f)
- depends: T1, T2, T3, T6
- acceptance: "[CLI] claude mcp list → lian-jing-* 旧条目清零、仅剩 lian-jing;[MCP] 抽查 3 个项目 settings.json/liangjing.json 符合新格式;经 /mcp 实调 get_diagnostics → 返回 JSON 无 error;[HTTP] POST /mcp/group/{gid} → 404"
- done_note: 2026-07-06 完成。端到端验证暴露真 bug:CLAUDE_CODE_GIT_BASH_PATH 回退路径硬编码 Program Files,Scoop 安装的 Git 导致 claude mcp add/remove 全挂(存量 bug,组级时代即存在)——修复为多位置探测 + already exists 视为成功 + 迁移标记位以注册成功为条件(0d1427f)。首次迁移的全局注册部分手动补齐(本会话 claude mcp remove ×12 + add lian-jing),文件迁移由 migrate_to_single_server 自动完成。验证:~/.claude.json 仅剩 lian-jing、3 项目(dev-manager-tauri/enterprise-system/life-memo)配置全部新格式、新路由握手 + get_diagnostics 实调通过、旧路由 404。遗留:同路径重复登记(legacy id "dev-manager-tauri" 组 0001 与 2c5b54ef 并存)导致批量重注入时 liangjing.json project_id 翻转,待用户决定是否 unregister legacy 条目
✅ 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 参数