Files

6.3 KiB
Raw Permalink Blame History

迭代复盘:18-QMTBridgeMCP内建

复盘日期:2026-09-08 | 迭代状态:验收通过(2026-09-08 —— 口径:服务端自动化验收全绿 + MCP 工具端到端实测 + UI 接线核验(构建产物含新控件)+ 真实调用顺带确认(老师参与验收:重启宿主 / 指令修正 / MCP 实测) 关联需求:R-020(已定稿,2026-09-08)| 关联计划:PLAN-018

结果

迭代 18 达成(R-020 全范围):QMT Bridge MCP 能力内建——神之一手在 apply 内动态挂载 DSH 官方 @deepseek-ai/dsh-mcp-clientserverName 固定 QMT_Bridge_MCPurl 自动派生自激活连接 baseUrl+/mcp;挂载/切换/卸载/状态全由神之一手插件内管理);三方依赖移除dsh-skill-mcp-panel 卸载 + 宿主 cordis.patch.yml 受管块清空);MCP 生命周期随 QMT 连接配置增删改与激活切换联动;状态出口 ×2(设置页「QMT 连接配置」MCP 状态条 + 会话头部指示灯区新增「MCP」灯);失败不崩(failOnStartupError:false + reconnect + 挂载 catch)。REST 直连架构不变(技术约束-003)。

验收证据(2026-09-08 实测)

# 验收项 结果
1 移除宿主受管块后工具仍可用 cordis.patch.yml 清空 []、panel 已卸载;mcp__QMT_Bridge_MCP__qmt_list_apis 实际调用成功(QMT Bridge v2.0.0 返回)
2 MCP url 随激活自动派生 100.110.38.78:8610/mcp(激活 baseUrl+/mcpQ3
3 激活切换联动 切 QMT_CYY → 192.168.3.43:8610/mcp connected;切回 GEMWIN 恢复
4 删除激活自动切默认 + MCP 重挂 删死地址连接 → 自动切默认 GEMWIN → MCP 恢复 connected + 10 工具
5 失败不崩(Q5 激活死地址 → state=errorfetch failed),插件其余功能正常
6 mcp-statusrefresh=检测按钮语义) refresh:true 即时探测 connected + 10
7 sync-status.mcp 域(头部灯数据源) state/url/mounted/toolCount/latencyMs/checkedAt 齐全
8 客户端接线 build 产物含「MCP」指示灯 + 设置页「检测 MCP」按钮 + header.actions/settings.section 注册
9 MCP 工具端到端实测 qmt_kline 取 000333.SZ 近一个月日 K30 根 OHLCV,区间 -4.27%
10 构建 typecheck + pnpm build 通过(lib/mcp/QmtMcpManager.js 产出)

过程事实

  1. 需求讨论定稿:老师指令(2026-09-08)→ R-020 登记 → Q1-Q6 逐项拍板(只挂激活连接 / 移除三方 / url 自动派生 / 双状态出口 / 失败重连采纳 / 不做通用 MCP 管理);
  2. 老师指令修正(关键):AI 一度把「动态挂载官方 dsh-mcp-client」误读为要自研协议,先撤依赖后澄清——老师明确:不要的是三方 dsh-skill-mcp-panel官方 @deepseek-ai/dsh-mcp-client 可以依赖;文档同步更正(R-020 / PLAN-018 / 迭代目标 / 索引);
  3. 依赖可行性实证(PLAN-018 步骤 1)@deepseek-ai/dsh-mcp-client@0.1.1-rc.2registry 有)加为 dependencies,从插件 lib 实证可 import,模块导出 {name:mcp-client, inject:[tools], apply, Config} → ctx.plugin() 动态挂载可行(mcp_router 同款路径);@modelcontextprotocol/sdk@1.30.0 供独立状态探测(dsh-mcp-client 不暴露状态 API);
  4. 实现src/mcp/QmtMcpManager.js(挂/卸/resync/probe/getStatus/dispose);index.js 接线(start + dispose + registerApi runtime);api/qmt-connections.jsmcp-status + activate/update/remove 三热切换点 resync);api/market.jssync-status.mcp 域);客户端 SyncIndicators(四灯 + MCP+ SettingsSectionMCP 状态条 + 检测按钮);tsdown 增 mcp 域入口;
  5. 宿主迁移(老师执行,验收方确认)cordis.patch.yml 受管块清空 + dsh-skill-mcp-panel 卸载 + 宿主重启 → 神之一手实例接管;
  6. 验收:服务端 8 项 + MCP 实测 + 构建全绿(上表);
  7. 提交推送c700f2f(迭代1816 files+ 9382ace(迭代17 遗留文档补提交)→ origin/main。

经验教训(复盘沉淀)

1. 「去掉对三方插件的依赖」要先问清:依赖边界到底指哪一层

AI 把老师「不希望依赖三方插件来加入 MCP 能力」误推到「也不能依赖 DSH 官方 mcp-client → 要自研 MCP 协议」,先动手撤了官方依赖、准备重造轮子;老师澄清后回撤。沉淀:需求里「不依赖 X」先精确定位 X 是谁(管理面板 vs 执行插件),并确认官方能力是否允许复用;架构岔路口先问一句,别先动手拆

2. 动态挂载子插件 = ctx.plugin(module, config),前提是模块在插件依赖树内可解析

mcp_router 实证了「import 官方模块 → ctx.plugin()」路径;one-divine-lot 照做时关键前置是把官方模块加进自己的 dependencies(而非 peer 裸声明),并用 createRequire 从插件 lib 路径实证解析成功再动代码。沉淀:动态挂载依赖模块时,先验证「插件运行路径能解析到模块」这个前置条件(技术约束-003 语义外的新增实践)

3. 状态查询与连接管理分离:dsh-mcp-client 不暴露状态 API

官方插件只管连接与工具注册,无状态查询口 → 用 @modelcontextprotocol/sdk 独立只读探测(initialize + tools/list 拿工具数/延迟),与官方自管连接互不干扰。沉淀:外部能力库若不开状态口,用协议级只读探测补状态出口,不试图扒内部字段

4. 验收期间临时造数要小心「先清后补」

用死地址测失败语义时两次 add 同名 TEST-DEAD 未清理(返回结构读错导致 id 取空),留下两条残留连接;发现后立即清理、用正确返回结构重测。沉淀:验收脚本对临时数据的增删要成对且校验返回值;测试前后核对连接列表与激活态

关联

  • R-020(已定稿 → 已实现 → 本迭代验收通过);宿主三方 dsh-skill-mcp-panel 已移除(其「技能/MCP」设置菜单与受管块职责移交完成)
  • 新增依赖:@deepseek-ai/dsh-mcp-client@0.1.1-rc.2、@modelcontextprotocol/sdk@1.30.0
  • 若需新增设计约束条目(如「插件内建 MCP 客户端注册规范」)——本迭代未新增,留待后续讨论(R-020 定稿时标注"如需…于定稿时补充"未触发)