docs(blueprint): mcp-single-server 设计定稿 + 拆卡 T1-T6
All checks were successful
Push & PR Check / check (push) Successful in 47s
All checks were successful
Push & PR Check / check (push) Successful in 47s
方案 B 双路由过渡:全局 /mcp 新路由与旧 /mcp/group/:gid 并存一个版本。 关键决策:工具层 resolve_project_root 去组化(组归属校验实测无隔离价值)、 迁移内建于重注入(reinject_all_mcp 即批量迁移器)、旧全局注册两种命名 格式(完整 UUID/短 8 位)都清理。webhook 路由已核实不受影响。
This commit is contained in:
parent
138a06aa17
commit
daed723438
@ -419,9 +419,10 @@ modules:
|
|||||||
- id: mcp-single-server
|
- id: mcp-single-server
|
||||||
name: MCP 单一服务器化
|
name: MCP 单一服务器化
|
||||||
area: backend
|
area: backend
|
||||||
status: concept
|
status: in_progress
|
||||||
progress: 0
|
progress: 0
|
||||||
note: "组级挂载 lian-jing-{group_id} 收敛为单一全局 lian-jing:授权/注册一次,项目数增长零客户端配置;liangjing.json 只需 project_id。L 级,先 /architect 再拆卡"
|
updated: 2026-07-06
|
||||||
|
note: "组级挂载 lian-jing-{group_id} 收敛为单一全局 lian-jing:授权/注册一次,项目数增长零客户端配置;liangjing.json 只需 project_id。已拆卡 T1-T6(双路由过渡方案),T6 删旧路由后置一个版本"
|
||||||
position: [1750, 500]
|
position: [1750, 500]
|
||||||
|
|
||||||
edges:
|
edges:
|
||||||
|
|||||||
@ -4,25 +4,100 @@
|
|||||||
|
|
||||||
## 为什么
|
## 为什么
|
||||||
|
|
||||||
- **摩擦随项目数复利增长,与飞轮方向相反**:当前每新增一个产品组 = 多一次 `claude mcp add` + 多一个授权单元 + 每个会话多一份重复工具清单(现状 12 个组 × 28 工具 ≈ 300+ 工具注册)。炼境的目标是"管理项目越多 → agent 辅助越强",客户端配置成本必须是 O(1)。
|
- **摩擦随项目数复利增长,与飞轮方向相反**:每新增一个产品组 = 多一次 `claude mcp add` + 多一个授权单元 + 每个会话多一份重复工具清单(现状 12 组 × 28 工具 ≈ 300+ 工具注册)。炼境目标是"管理项目越多 → agent 辅助越强",客户端配置成本必须是 O(1)。
|
||||||
- **组级挂载没有真正的隔离价值**:2026-07-06 实测,任意组的服务器可对任意项目执行 `inject_mcp`(工具全部显式传 `project_id`),组这一层只是命名空间,不是权限边界。
|
- **组级挂载没有真正的隔离价值**:2026-07-06 实测任意组服务器可对任意项目执行 `inject_mcp`;组归属校验只覆盖部分工具(半吊子状态)。
|
||||||
- **消除 group_id 身份卡的存在必要**:单一服务器后 `liangjing.json` 只需 `project_id`,group_id 缺失/过期/移组同步这一整类问题从根上消失(而非修复)。
|
- **消除 group_id 身份卡问题**:单一服务器后 `liangjing.json` 只需 `project_id`,group_id 缺失/过期/移组同步这一整类问题从根上消失。
|
||||||
|
|
||||||
## 改造范围(侦察结论,待 /architect 细化)
|
## 设计决策(2026-07-06 /architect)
|
||||||
|
|
||||||
- `mcp_server.rs`:`/mcp/group/{group_id}` 路由 → 新增全局 `/mcp` 路由;旧路由保留一段过渡期
|
### 方案选择
|
||||||
- `mcp_tools.rs`:工具已全部显式传 `project_id`,改动小;`list_group_projects` 等组上下文工具改为显式传参或从 project 反查 `project_group_map`
|
|
||||||
- `mcp_inject.rs`:settings.json 注入条目 + `claude mcp add` 收敛为单个 `lian-jing`;`liangjing.json` 去掉 group_id 依赖
|
|
||||||
- **存量迁移**:清理 ~/.claude.json 中 12 个旧 `lian-jing-*` 注册;已注入项目 settings.json 批量刷新(复用 `reinject_all_mcp` 机制)
|
|
||||||
- 接入包模板 / `docs/ai-context/git-workflow.md` 中 `lian-jing-{group_id}` 引用同步改
|
|
||||||
- 用户全局 `~/.claude/CLAUDE.md` 炼境按钮规则段(引用 `lian-jing-{group_id}`)需同步
|
|
||||||
|
|
||||||
## 风险
|
- A. 直接切换:加全局路由同时删旧路由 —— ❌ 所有存量会话立刻断链,故障静默
|
||||||
|
- **B. 双路由过渡(选定)**:新增全局 `/mcp` 路由,旧 `/mcp/group/:gid` 保留兼容;注入逻辑切到新名字;批量迁移后旧路由在后续版本删除
|
||||||
|
- C. 全局 alias 与组服务器并存 —— ❌ 不消除 O(N) 注册,白改
|
||||||
|
|
||||||
- 迁移期新旧服务器并存,agent 可能困惑——需设计干净的切换顺序(先加新、批量迁移、后删旧)
|
### 核心接口变更
|
||||||
- webhook 回调路径是否含 group_id 待核实(`mcp_webhook.rs`)
|
|
||||||
- 状态:concept,L 级——禁止直接写代码,先 `/architect` 输出设计文档,用户确认后 `/splitter` 拆 S/M 卡
|
1. **路由**(`mcp_server.rs`):新增 `POST/GET /mcp` + `POST /mcp/messages`;`process_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)
|
||||||
|
|
||||||
## 任务卡
|
## 任务卡
|
||||||
|
|
||||||
(待 /architect 设计确认后由 /splitter 生成)
|
### 📋 T1. 服务器层双路由:全局 /mcp + 组上下文 Option 化
|
||||||
|
- status: todo
|
||||||
|
- 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);旧路由 /mcp/group/{gid} 同请求仍 200(双路由并存)"
|
||||||
|
|
||||||
|
### 📋 T2. 工具层去组化:resolve_project_root 按 project_id 直查
|
||||||
|
- status: todo
|
||||||
|
- 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 全绿"
|
||||||
|
|
||||||
|
### 📋 T3. 注入层收敛:lian-jing 单 key + 旧配置清理 + liangjing.json 瘦身
|
||||||
|
- status: todo
|
||||||
|
- complexity: M
|
||||||
|
- files: src-tauri/src/mcp_inject.rs, src-tauri/src/mcp_tools.rs, src-tauri/src/commands/groups.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 键被删除;try_register_globally 注册单个 lian-jing 并对旧名(完整 UUID + 短 8 位两种格式)执行 claude mcp remove;remove_group_member 仅在项目不属于任何组时移除 key;cargo test 全绿"
|
||||||
|
|
||||||
|
### 📋 T4. 存量批量迁移执行 + 端到端验证
|
||||||
|
- status: todo
|
||||||
|
- complexity: S
|
||||||
|
- files: (执行操作,无新代码——复用 reinject_all_mcp)
|
||||||
|
- depends: T1, T2, T3(需先发版/重启炼境运行新二进制)
|
||||||
|
- acceptance: "[CLI] claude mcp list → lian-jing-* 旧条目清零、仅剩 lian-jing;[MCP] 抽查 3 个项目(含本项目 + enterprise-system)settings.json/liangjing.json 符合新格式;新 Claude 会话经 lian-jing 实调 get_diagnostics → 返回 JSON 无 error"
|
||||||
|
|
||||||
|
### 📋 T5. 文档/模板/技能/UI 寻址说明同步
|
||||||
|
- status: todo
|
||||||
|
- 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 通过;另提醒用户同步仓库外 ~/.claude/CLAUDE.md 炼境规则段"
|
||||||
|
|
||||||
|
### 📋 T6. 后置:删除旧 /mcp/group 路由与兼容层(下个版本)
|
||||||
|
- status: todo
|
||||||
|
- complexity: S
|
||||||
|
- files: src-tauri/src/mcp_server.rs, src-tauri/src/mcp_tools.rs
|
||||||
|
- depends: T4(迁移验证通过后至少隔一个发版周期)
|
||||||
|
- acceptance: "[HTTP] POST /mcp/group/{gid} → 404;cargo test 全绿;grep 'mcp/group' src-tauri/src/ 零命中"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user