dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
DSH 插件:一块设置面板管理 @deepseek-ai/dsh-mcp-client 的 MCP 行——列出、新增、改写、启停,不必再手写 cordis.patch.yml;零构建、零运行依赖。
简体中文 | English
DSH 插件:在 设置 → 侧栏 提供「MCP 客户端」面板,用来管理挂在 @deepseek-ai/dsh-mcp-client 下的 MCP 服务器行 —— 列出 / 添加 / 改写 / 启停 / 删除,点保存才写盘,写完不重启宿主。
本插件最初为作者自用而写;现已发布到 npm(@yiyunet/dsh-mcp-client-manager),源码 MIT、按需自取。能力边界与已知限制全部写在本文档里,不承诺文档之外的行为。
版本 · 变更 1.0.4 · 修表格横向溢出(实测反馈):根因是 1.0.3 给操作列加的 min-width: 300,把表格最小宽度顶过容器 → 尾部横线溢出卡片。改法:① 去掉该强制宽度,列宽回归内容自适应(修改|禁用|不可删仍同排,因为行内 flex 仍 nowrap);② 表格外套一层 overflow-x: auto 兜底——万一再超也只在本卡片内横向滚动;③ 服务名 / 行 id 加 ellipsis 截断(max-width: 200,悬停看全文);④ 文案:不可删(手写) → `不可删`(悬停解释保留:手写行不能删、可改用禁用) 1.0.3 · ① 操作列强制单行(后于 1.0.4 取消强制宽度);② 修正 1.0.2 挪位编辑引入的括号配平错误;③ 端点/命令不在列表显示(会撑宽首列)——只保留在「修改」表单的 url 提示 + 悬停 title;首列小字恢复为仅「原手写行」 1.0.2 · ① 脱敏:回传浏览器的路径改为符号化($DSH_HOME\…),不再出现含用户名的绝对路径(list/state 均适用,单测加断言);② 表格规整:删除「端点 / 命令」整列,单元格禁折行;③ 手写行的「不可删」提示移到「禁用/启用」按钮之后(受管行为 修改 | 禁用 | [撤销覆盖] | 删除,手写行为 修改 | 禁用 | 不可删 | [撤销覆盖]) 1.0.1 · 修 F6:状态列误读官方字段(应读 fiberPhase,且 FiberState 是数字枚举)→ 正常行被误报成"挂载/重连中";状态口径改大白话(已启用 / 已启用·未发现工具 / 已禁用 / 加载失败 / 未加载 / 配置冲突),工具数收进悬停提示;顶部备注重写为普通用户可读,并动态显示受管行的写入路径(list 回传 paths.homePatch) 1.0.0 · 首发:受管行(自有层)+ 手写行(官方通道)、三级 id 冲突检测、serverName 查重、漂移检测与两个逃生口、撤销覆盖、密钥永不出宿主
层 · 文件 · 谁写 · 作用 真源(受管清单) · $DSH_HOME/mcp-manager/servers.json · 本插件 · 面板管理的服务器清单(含 url / env 等密钥字段,0600) 生成物(自有层) · $DSH_HOME/cordis.patch.yml · 本插件,全量重写 · 把受管行渲染成 MCP 行;home 层在 HMR 监听范围内 → 落盘即热生效 手写层 · profiles//cordis.patch.yml · 手工编辑 / DSH 官方配置编辑器 · 不由本插件直接改写:改写与启停走官方通道(ctx.configEditor / ctx.pluginManager),而官方的写入落点就是本文件(见下)
两条写回路径,互不越界
🔎 找文件时别找错地方(本条最常被问)
本面板添加/删除的行写在 `$DSH_HOME\cordis.patch.yml`($DSH_HOME= DSH 安装/数据根,即%USERPROFILE%.dsh)——
不在 profiles\\cordis.patch.yml 里。profiles\\cordis.patch.yml 只会有:① 你手写的那两行;② 面板改写它们时由 DSH 官方配置编辑器追加的覆盖行。面板顶部显示的就是这个符号化路径(不显示含用户名的绝对路径)。
mcpx-):新增 / 改写 / 启停 / 删除 → 写自有层文件。mcp-sorftime、mcp-myserver):只能改写凭据族字段与启用/禁用;不能删除、不能改 serverName / transport(要改请手工编辑 profile patch)。 改写走 ctx.configEditor.edit()(原子写 + 失败回滚 + 被更高层覆盖则拒写), 启停走 ctx.pluginManager.setPluginEnabled()。
⚠️ 手写行改写的落点(实测过一次,务必知道):官方配置编辑器只认顶层 - id: 行,且明确排除 insert 行 (DSH 源码 packages/boot/config-editor/src/index.ts:117-128)。我们的两行嵌在 - insert: [...] 里 → 于是:
profiles//cordis.patch.yml 末尾追加一条顶层覆盖行(- id: … / name: … / config: …),原 insert 行保持不变;覆盖行在同文件内靠后 → 优先级更高 → 生效的是它。
已覆盖 标记,并多出一个「撤销覆盖」按钮 ——它调用官方语义(next === inherited 时移除覆盖行),把该行还原成 insert 行的原值。
insert 行立刻生效;已被面板覆盖的行,改 insert 行不生效(被覆盖行压住),要先「撤销覆盖」。为什么不让面板直接改 profile patch:官方编辑服务够不着嵌在 - insert: [...] 里的行, 自写 YAML 要自带解析器,而且文件写坏 = 下次启动起不来;自有层既避免解析(我们只写自己生成的内容), 又天然被 HMR 监听。
协议//主机/…,不含路径、查询串或任何 key 片段。url、command、env 属此类。serverName 保存前查重(活动行 + 受管清单 + 本次草稿);重复会让后加载的那条加载失败。mcpx- 前缀 + 三级 id 冲突检测(活动行 / 受管清单 / 手写层文本弱扫)——同 id 双声明会让官方把该行判成 unaddressable 并锁死开关。
mcp____* 计数),不代表链路健康(断线重连期间工具仍会列出、调用才失败,这是 mcp-client 的既定行为)。
已发布 npm(最省事):dsh plugin --profile web add @yiyunet/dsh-mcp-client-manager;下列方式任选。方式 A · 本地目录(推荐:你手上这份 clone / 解压出来的目录)
侧栏 插件 → 添加插件 → 粘贴本仓库所在目录的本地绝对路径 → 安装
# 若偏爱命令行(<本仓库> = 本插件目录的绝对路径)
dsh plugin --profile web add "<本仓库>"方式 B · 直接从 GitHub 源安装
dsh plugin --profile web add github:yiyunet/dsh-mcp-client-manager本包没有任何 `prepare` / 构建脚本,因此 git 源安装不会触发"构建脚本批准"那一关。
⚠️ 推测(未实测):方式 B 的可用性取决于你的包管理器版本与 dsh plugin 对 git 说明符的解析;失败请回方式 A。本 profile patchReload: live,且 bundles 变化在 HMR 监听范围内 → 通常无需重启; 若设置里没出现「MCP 客户端」,重启一次宿主。
若dsh不在 PATH:可用 DSH 检出内的 CLI 入口node /apps/cli/lib/bin.js plugin …,
或用 npx -p @deepseek-ai/dsh dsh plugin … 之类的等价形式(同样推测,未实测)。# · 动作 · 预期观察 1 · 打开 设置 → 侧栏 · 出现「MCP 客户端」 2 · 打开面板 · 列出手写行(来源=手写,服务名下注「原手写行」),状态=已启用或已启用 · 未发现工具;端点掩码/命令已收进"服务名"格的悬停提示(表格只留 5 列:服务名 / 行 id / 来源 / 状态 / 操作) 3 · 添加(http 三字段)→ 保存 · $DSH_HOME/cordis.patch.yml 出现;列表新增 mcpx-*;MCP 工具在该行挂载后可用 4 · 添加(stdio,command/args/env)→ 保存 · 同上;env 值落盘但不回显 5 · 改手写行 url → 保存 · 来源列变「手写 + 已覆盖」;profiles/web/cordis.patch.yml 末尾多出一条顶层 `- id: … / config: …` 覆盖行(官方行为),原 insert 行不动;值立即生效 6 · 再改同一行一次 · 覆盖行原地更新,不新增第二条 7 · 点该行「撤销覆盖」 · 覆盖行被移除,值回到 insert 的原值;来源列恢复「手写」 8 · 禁用/启用手写行 · profile patch 出现/更新 disabled 覆盖 9 · 删除受管行 · 自有层文件该行消失,工具消失(手写行的"删除"按钮不存在) 10 · 漂移演练:手工编辑 $DSH_HOME/cordis.patch.yml · 面板转只读 + 两个处置按钮(重建 / 清空清单)
只读核对(⚠️ 输出含 key,别外传):
dsh --profile web --dump-config纯函数自测 + 集成冒烟(不需要 DSH、不需要网络、不碰真实 $DSH_HOME):
cd <本仓库>
# 先做语法预检(零副作用,几秒钟;这一步能拦住任何手写笔误)
node --check plugin-src/host/index.mjs
node --check plugin-src/host/store.mjs
node --check plugin-src/host/validate.mjs
node --check plugin-src/host/adapter.mjs
node --check plugin-src/client/client.js
# 再跑三份测试(⚠️ 必须点明文件:Node 24 下 `node --test test` 会把 test 当模块加载而报 MODULE_NOT_FOUND)
node --test test/validate.test.mjs test/store.test.mjs test/host-smoke.mjshost-smoke.mjs 会造一个假宿主(临时目录当 DSH_HOME)真跑一遍:list / 新增 / 查重 / 启停 / 删除 / 手写行改写 / 漂移与逃生口 / RPC 信封与乐观锁,并断言密钥(url 与 env 取值)绝不出现在回传载荷里。
契约与发布前自检(本仓库自带):
npm test # 同上三份测试
npm run verify # 包契约断言(补齐 CLI 版本,见 scripts/verify-package.mjs)GUI:侧栏 插件 → 找到本组合包 → 卸载。
CLI:
dsh plugin --profile web remove "@yiyunet/dsh-mcp-client-manager"
# 2) 清受管层(受管 MCP 全消;手写行不受影响)
Remove-Item "$env:USERPROFILE\.dsh\cordis.patch.yml"
# 3) 清受管数据(可选)
Remove-Item -Recurse "$env:USERPROFILE\.dsh\mcp-manager"显示 · 含义 · 悬停提示 已启用 · 行已加载,且发现了该服务器的工具(这是"确实连上了"的唯一证据) · 已发现 N 个工具,例如 … 已启用 · 未发现工具 · 行已加载,但没有发现工具(服务端本来就没有工具,或连接尚未完成) · 同上说明 已启用 · 加载中 · 行刚写入/重载,还没走完加载 · — 已启用 · 停止中 · 行正在卸载 · — 已禁用 · 该行被关掉,不会连接 · — 加载失败 · 行加载/连接失败(看宿主日志) · — 未加载 · 配置在,但当前进程里没有这一行 · — 配置冲突 · 该行 id 被多层声明,官方已锁其开关,需手工处理 · —
状态只说明"这行有没有加载、有没有发现工具",不代表对方服务健康:断线重连期间工具仍会列出、调用才失败
(mcp-client 的既定行为)。因此本面板不做探活。
已被覆盖的行再改 insert 不生效,需先点「撤销覆盖」(详见 §1)。「撤销覆盖」只删 config,不会动同一行上的 disabled 等其他键。
headers、reconnect、toolCallTimeoutMs、maxInstructionBytes 等字段仍以文件为准(面板不动它们,改写时按"整段替换但带上现有键"处理)。
node:* 与 ctx 服务,浏览器半侧用官方 module-loader 工厂格式。遇到问题或想要新功能,提一个 issue。 报问题时写上 DSH 版本和插件版本,修起来最快。
模板会问「哪一段」——若说不清,留空即可,但「装了没生效」与「配置被写坏」是两条完全不同的排查线, 能分清就分开报。
贴配置片段前请先删掉 token、API key 与内网地址:MCP 服务器的配置天然带凭证。
你想知道… · 看这里 装完一步步怎么确认它在工作 · docs/安装与验证.md 它到底怎么写盘:两层文件、两条写回路径、RPC 接口表、漂移与撤销覆盖 · docs/架构与写回模型.md 每个版本改了什么 · CHANGELOG.md 文档总索引 · docs/README.md
MIT,见 LICENSE。问题与建议走本仓库 Issues。