Files
ycode/docs/mcp-implementation-20261016.md

79 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 自定义 MCP 后端与连接器页面实施(2026-10-16)
本轮已实现 YCode 自有 stdio/Streamable HTTP MCP host、凭据加密、配置批准、服务/逐工具启停、连接释放、稳定工具快照以及可用的连接器/MCP 管理界面。受控真实 SDK、独立 Electron 重启和实际 App UI 验证通过。**没有实现 WorkBuddy 云目录、账号 OAuth、内置 QQ 邮箱等业务服务,也没有完成连接器全状态像素 1:1 验收。**
## 修改文件与边界
- `src/main/capabilities/mcp.ts`:自有 host/registry、凭据和运行连接/工具快照。
- `src/renderer/src/capabilities/ConnectorsPage.tsx`:连接器内容页与 toolbar portal、详情、MCP 管理、单服务 JSON/Monaco 编辑、批准/开关/工具/删除/重连。
- `connectors-source.css`:固定 REA 源规则正文,增加页面作用域;`connectors-adapters.css`:YCode 宿主/错误/可用性/编辑适配。
- `ConnectorSourceIcons.tsx`:隔离的原 SVG/静态图标正文;`connectors-helpers.ts`:单服务 JSON 解析、凭据 metadata 占位与原图标颜色规则。
- `package.json`、`package-lock.json`:增加 `@modelcontextprotocol/sdk@1.32.1`、`yaml@2.9.1`、`fflate@0.8.3`,后两项由技能实施共享使用。普通 npm install 遇既有 electron-vite 5/Vite 8 peer 范围冲突,采用 `--legacy-peer-deps`,没有降级现有版本;全项目 typecheck/统一 build 另验。
- `scripts/test-mcp-server.mjs`、`test-mcp-backend.mjs`、`test-mcp-helpers.mjs`、`test-mcp-source-ui.mjs`、`test-mcp-native-ui.mjs`;本报告。
Worker 未编辑 shared capabilities/IPC/preload/App/chat runtime。Root 负责注册上述后端函数、startup initialize、能力中心统一顶栏、会话工具快照/审批/真实内核接线。Root 随后在 snapshot 上补了 `describe(name) → {serverName,toolName}`,将 identity 放入 tool metadata,审批与已有 REA `mcp_call_tool` 专用视图使用可读 server/tool 名;稳定 namespace 和 generation 检查保留。该跨模块集成为 Root 工作,不能算 worker 独立 fixture 已覆盖。
## SDK 与原版依据
实施前查询了官方 [TypeScript SDK v1 Client](https://ts.sdk.modelcontextprotocol.io/client)、[Server](https://ts.sdk.modelcontextprotocol.io/server) 和 [v1 protocol source](https://github.com/modelcontextprotocol/typescript-sdk/blob/v1.x/src/shared/protocol.ts)。本轮使用已安装 1.32.1 的 Client、StdioClientTransport、StreamableHTTPClientTransport 与 request signal;没有以手写假 MCP 协议替代 SDK。
所有原版观察来自 WorkBuddy **5.8.2** 的 REA 归档,不直接读取原版安装路径或 CDP/evaluate。完整源码锚点见 `assessment-connectors-2026-10-16.md`。主要证据:
- JS:`ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb`,`skills-panel-CvMlV3m8.js` SHA `b30c43c11ec476db639d6be58065d927411845487d34b0ea8e839d1c6eb7a238`。McpConfigEditor UTF-16 offset 20816,McpPanel 27216,ConnectorPanel 62950。
- CSS:`ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94`,`skills-panel-CsnIUki4.css` SHA `c1d5c5de51554a886fde0399c5202cd45063fa091b213b842014bea91dbb69a0`;源规则正文保留,selector 作用域为 `.ycode-connectors`。共享 button/input/CB search 原规则来自 4 份已校验样式,记录在 `.tmp/mcp-source-ui/recovery.json`。
- 商店静态:`ev_e91bdc6e46275f4460985cfff25fd7f7bc334afc45f49fac1935de1249f4cb22`,`.tmp/rea-market-connectors-static-20261016`;原 pencil SVG 为 node 821。
- 稳定 MCP 管理:`ev_b89281177f6a1cf2e4697887d576b8ddf7d811a8fa2d1148b7024a4ec898906f`,`.tmp/rea-custom-connectors-static-20261016`;用于 modal 几何、add/Hub/close/search/clear SVG 和样式依据。最初半透明过渡帧未用作稳定基线。
- QQ 邮箱详情:`ev_b898a87832d1e800810d391145a6ec6c6999e98b5cea6c7f382a3fc19aa7b3ac`,操作 steps 完成、cleanup failed,整 probe 为 partial;没有授权/连接。这里只提供详情结构参照。
恢复脚本只解析固定工作区 REA export 的 CSS/AST/SVG,不执行原版全局初始化。源样式包含 640×700 最大尺寸、list/search/tools/trust/error/warning/toggle/modal 动效;这不等于所有原版交互已逐一实测。
## 后端行为
Registry 为隔离 app userData 下 `mcp-servers.json`,串行更新、临时文件 rename 持久化;同名服务拒绝覆盖、输入字段校验。服务 env/headers 合并规则是:未提供 map 保留,显式 map 的已有空值保留,省去某 key 可移除;环境变量和 Headers 只经 Electron safeStorage 密文保存,无法安全加密时拒绝写入,**不采用明文 fallback**。IPC view 只返回 key 名,不返回值;错误字符串不透传上游 URL/凭据,stdio stderr 丢弃,工具结果/metadata 中的已知配置凭据回显会屏蔽。
configHash 覆盖实际配置与凭据。新配置未批准;变更 command/args/cwd/name/url/env/headers 会清除 trust 和已发现工具并关闭旧连接。读取外部手改的 registry 时重新规范化与计算 hash,不能保留旧 hash 假装批准;未知字段不会进 IPC view。批准携带 hash,陈旧批准被拒绝。没有实现原版企业策略或 OAuth 授权。
stdio 用 SDK 启动 command/args/cwd,只继承 SDK 默认环境与明确配置 env,不把主进程所有变量灌给服务;Streamable HTTP 保留完整 MCP endpoint,固定配置 origin 并禁止重定向携带凭据。`listTools` 读取所有页、去重工具/重复 cursor 拒绝,最多 10,000 工具;握手和单页请求超时 20s、tool call 超时 120s。连接状态来自真实生命周期,disconnect/disable/remove/config 变更会关闭 SDK client,HTTP 会 best-effort terminateSession。
服务与工具 enabled 持久化;开启服务先要求当前配置已批准。`initializeMcpServers()` 在 startup 后台重连已启用且批准的服务;`snapshotMcpTools()` **只取当前 connected 连接,不等待不可用 MCP 握手**,普通发送不会因为坏服务停在不可取消的 preflight。
每个 supplier tool name 为 `mcp_<截断清理工具名>_<serverID+toolName hash>`,长度不超过 64、无跨服务碰撞,重连不改 namespace。快照捕获具体 client/generation/configHash;execute 再验证同连接、同配置、当前 trust/enabled/tool enabled。配置/连接变化使旧调用失败,不自动把旧回合映射到新服务/新密钥。
取消保持区别:**外部 turn signal abort 才抛 AbortError**;运行中 disable/remove/config 关闭 runtime 返回 `ok:false` 配置/连接变化错误。两条路径都有受控实际服务验证。普通 tool isError/上游异常也按 tool failure 返回。
## 界面行为与已知差异
统一三 tab 属于 Root CapabilityCenter,页面搜索/管理按钮 portal 到其 toolbar;MCP/detail portal 到 `.yc-capability-center .expert-center-page`,继承 scoped light/dark tokens,避免 body portal 丢颜色/尺寸。
没有 WorkBuddy 目录服务时显示实际可用性状态与自有 MCP 卡片,不画出已成功连接的 QQ 等内置业务。MCP 列表使用真实 host 返回值,支持搜索、状态点、展开工具、逐工具开关、信任审批、超 80 工具提示、重连、复制安全错误、删除确认;Hub 链接使用归档 source 公共 fallback URL。没有伪造插件 readonly 来源、OAuth 已授权或安装成功。
单服务编辑仍使用原 `mcpServers` JSON 形状,实际复用已恢复 Monaco source wrapper 的 editable/onChange;已有 env/header 仅 key+空值占位,保留契约明确。保存仅更新这一个服务,不隐式删除其他配置。与原版全配置路径/批量原子保存仍有差异,这是当前 McpApi 范围,Root 已确认先稳定单服务编辑。
Monaco 的 `webContents.insertText` 属于 typing/IME 路径,可能自动括号/缩进;不能当真实 paste 验收。本轮自身 QA 用 native focus/Ctrl+A 后受控 ClipboardEvent+DataTransfer 走真实 Monaco paste handler,未直接改 model/store、未触系统 clipboard;没有关闭自动补全来迁就测试。加载编辑器失败才使用 textarea fallback。
## 验证结果
| 命令 / 证据 | 实际范围与结果 |
|---|---|
| `npm run typecheck` | node/web 均退出 0 |
| `node scripts/test-mcp-source-ui.mjs` | 源 SHA 复验、10 个隔离函数 SVG 与 6 个 DOM SVG、4 份 primitive sheet 恢复;PASS |
| `node scripts/test-mcp-helpers.mjs` | 12/12 PASS,`.tmp/mcp-helpers-NuJUou/report.json`;单服务/rename/凭据占位/JSON/type/args/headers/multi-server/empty 防误删 |
| `node scripts/test-mcp-backend.mjs` | `.tmp/mcp-backend-7PNwXc`:exercise **36/36**、全新 Electron reload **7/7**、外部配置 tamper **2/2** PASS |
| `node scripts/test-mcp-native-ui.mjs` | `.tmp/mcp-native-ui-PWWVz4/report.json` **13/13 PASS**;真实 App/preload/IPC、主题 portal、源几何、Monaco 粘贴保存,无模型/上游请求 |
| Root `.tmp/capability-flows-ZJYiyj/report.json` | main **13/13** + restart **6/6** PASS;真实 App UI → OMP → 受控 supplier → MCP +技能,属于 Root 跨模块集成验证 |
| Root `.tmp/capability-gateway-QNP0Ek/report.json` | **16/16 PASS**;Root 后续补可读 MCP identity/tool view 后的真实 Gateway 验收 |
Backend 受控服务均使用真实官方 SDK:stdio 为真实子进程、HTTP 为 loopback stateful StreamableHTTP,真实两页 list、callTool、鉴权存在/匹配、SDK cancellation notification 到达服务、HTTP DELETE session 释放。运行中 wait 时 disable/remove 返回 tool failure;外部 turn signal 取消在两个 transport 中均为 AbortError。服务关闭/重连/变更后旧快照不能再次调用,新快照使用新 generation。重启检验 tools/disabled/approval/secret metadata,外部改 args 保留旧 hash 也会失信。
Native UI 稳定 modal bounds 为 **[348,115.5,640,700]**,与 V4 modal 几何一致;light background `rgb(255,255,255)`、dark `rgb(31,31,31)`,原 secondary button foreground `rgba(0,0,0,0.9)`,两主题按钮高 **32px**。报告没有宣称所有 computed properties 相等;modal 容器继承 text color 当前 light rgb(0,0,0),原归档部分祖先为 rgb(59,59,59),仍应按实际叶节点/同内容继续比对。截图/报告保留在目录,原版 dark 动态像素没有对应新证据。
Native UI 报告 build SHA `53b6eb3d586aa0bca613507761a5943fd67953ad113e82cbe73ea27bb0210774` 是当前 UI 的已测构建;最后 runtime failure-vs-cancel 语义修正经独立后端回归,Root 将统一最终 build/OMP/restart 复验,不把旧 build hash 当作新构建已经验收。脚本父进程检查实际 report 存在、非空 checks 与 PASS,不能仅凭 Electron exit 0。
早期 `.tmp/mcp-backend-4VPd0j` 的 CLI argv 错把 switch 当 phase,只有错误命名的 exercise 报告,不能用于重启结论;已修 phase 取最后参数和强制每阶段报告,最终以 7PNwXc 三阶段为准。Native UI 首次测到 transform 入场中的缩小尺寸,改为等待实际 animation.finished 后测稳定原几何,没有改生产动效。
## 剩余边界
尚未实现:WorkBuddy 官方/企业动态目录、内置业务连接器、OAuth/device-code/QR 授权、Token schema 特殊表单、包分发/自动安装、旧 HTTP+SSE、MCP prompts/resources/resourceTemplates 与 MCP Apps/Widgets 运行时。当前 JSON 编辑不是原版全文件原子 bulk;现有接口不含 plugin readonly/enterprise policy/source metadata。健康状态为连接生命周期/操作结果,未实现原版所有自动修复/授权刷新策略。
受控 MCP 成功不代表任意第三方 server 可用、真实账号授权成功或原版 daemon 等价。完整目录/详情/错误/信任/所有工具/窄宽/暗色/hover/动效/字体的同内容像素验收仍未完成。Root 后续可读 identity 专用视图也需继续做 source 实测,不能以函数/编译/通路通过代替全量 1:1。