🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

MCP 管理面板 Imzl-zl/dsh-toolbox-ui

DeepSeek Harnessv1.9.0
Imzl-zl2 天前有提交已提供中文文档扫描:含敏感能力ui

DeepSeek Harness Web 的 MCP 服务管理界面——浮动面板、JSON 导入,配置档持久化。

47.8/100
综合分
38
GitHub 星标
732
npm 周下载
—/5
用户评分

数据截至 2026/10/30 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add dsh-toolbox-ui
npm 源 · dsh-toolbox-ui 的发布者账号已校验与本仓库一致

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · market
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 2 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查✓ 自动检查通过
展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-toolbox-ui @ 1.9.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 00:25:48

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 51 处,展示前 41 条)
  • 读取本地文件
    lib/index.js:210
    const [content, info] = await Promise.all([readFile(path, "utf8"), stat(path)]);
  • 读取本地文件
    lib/index.js:210
    const [content, info] = await Promise.all([readFile(path, "utf8"), stat(path)]);
  • 读取本地文件
    lib/index.js:472
    return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version ?? "";
  • 读取本地文件
    lib/index.js:484
    return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).name ?? "";
  • 发起网络请求
    lib/index.js:510
    const response = await fetch(endpoint, {
  • 读取本地文件
    lib/index.js:789
    const info = await stat(path);
  • 读取本地文件
    lib/index.js:791
    return readFile(path, "utf8");
  • 删除本地文件递归
    lib/index.js:2190
    await rm(staging, { recursive: true, force: true });
  • 写入剪贴板
    lib/client.js:1803
    await navigator.clipboard.writeText(String(text));
  • 读取本地文件
    lib/skills-registry.js:53
    return toSlashes(await realpath(path).catch(() => path))
  • 读取本地文件
    lib/skills-registry.js:146
    entries = await readdir(root)
  • 读取本地文件
    lib/skills-registry.js:153
    const real = await realpath(join(root, entry)).catch(() => undefined)
  • 读取本地文件
    lib/skills-registry.js:526
    await access(path)
  • 读取本地文件
    lib/skills-registry.js:535
    return (await stat(path)).isDirectory()
  • 读取本地文件
    lib/skills-file-ops.js:44
    await stat(path)
  • 读取本地文件
    lib/skills-file-ops.js:126
    return (await stat(path)).isFile()
  • 写入本地文件
    lib/skills-file-ops.js:202
    await rename(target.path, enabledPath)
  • 读取本地文件
    lib/skills-file-ops.js:205
    const text = await readFile(target.path, 'utf8')
  • 读取本地文件
    lib/skills-file-ops.js:249
    const { mode } = await stat(path)
  • 读取本地文件
    lib/skills-file-ops.js:276
    entries = await readdir(root, { withFileTypes: true })
  • 读取本地文件
    lib/skills-file-ops.js:285
    const isDirectory = await stat(join(root, entry.name)).then((info) => info.isDirectory()).catch(() => false)
  • 删除本地文件递归
    lib/skills-file-ops.js:423
    await rm(item, { recursive: true, force: true })
  • 删除本地文件
    lib/skills-file-ops.js:426
    await rm(item, { force: true })
  • 删除本地文件
    lib/skills-file-ops.js:428
    await rm(`${item}${DISABLED_SUFFIX}`, { force: true })
  • 写入本地文件
    lib/skills-file-ops.js:571
    await mkdir(root, { recursive: true })
  • 写入本地文件
    lib/skills-file-ops.js:605
    await mkdir(root, { recursive: true })
  • 删除本地文件递归
    lib/skills-file-ops.js:612
    if (staging !== undefined) await rm(staging, { recursive: true, force: true })
  • 写入本地文件
    lib/skills-file-ops.js:626
    await writeFile(temp, text)
  • 写入本地文件
    lib/skills-file-ops.js:627
    await rename(temp, destination)
  • 删除本地文件
    lib/skills-file-ops.js:629
    await rm(temp, { force: true })
  • 写入本地文件
    lib/skills-file-ops.js:648
    await mkdir(holder, { recursive: true })
  • 删除本地文件递归
    lib/skills-file-ops.js:656
    await rm(holder, { recursive: true, force: true })
  • 写入本地文件
    lib/skillhub.js:268
    await pipeline(source, createWriteStream(target))
  • 读取本地文件
    lib/workspace-runtime.js:1032
    info = await stat(filePath);
  • 读取本地文件
    lib/workspace-runtime.js:1043
    const config = await readWorkspaceConfig(wsPath, (path) => readFile(path, "utf8"));
  • 写入本地文件
    lib/workspace-runtime.js:1053
    (path, options) => mkdir(path, options),
  • 读取本地文件
    lib/tool-search-settings.js:215
    const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
  • 读取本地文件
    lib/tool-search-settings.js:217
    const doc = parseDocument(readFileSync(new URL('../cordis.patch.yml', import.meta.url), 'utf8'))
  • 写入本地文件
    lib/skills-archive.js:188
    await mkdir(destination, { recursive: true })
  • 写入本地文件
    lib/skills-archive.js:208
    await mkdir(dirname(target), { recursive: true })
  • 写入本地文件
    lib/skills-archive.js:209
    await writeFile(target, data)
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 npm 发布包

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-include@deepseek-ai/cordis-plugin-loader@deepseek-ai/dsh-agent@deepseek-ai/dsh-agent-loop@deepseek-ai/dsh-api-gateway@deepseek-ai/dsh-atomic-write@deepseek-ai/dsh-mcp-client@deepseek-ai/dsh-scope@deepseek-ai/dsh-skill@deepseek-ai/dsh-skill-filesystem@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

2 张 · 点击查看大图

功能亮点

  • MCP服务管理界面
  • 浮动面板
  • JSON导入配置
v1.9.02026-10-26
· dsh-toolbox-ui v1.9.0 这一版改的是"目录默认多大"和"搜索没找到时怎么反馈"。 两件都不是新功能,是让已有机制不再悄悄做错事。 · 为什么值得升 延迟加载的目的,是让没被用到的工具定义不进提示词。上一版做到这一点之后,剩下两处"静默": · 目录默认会在某个字符数处截断。工具特别多时模型只看到半张地图,而它没有任何标记能区分"没有这个工具"和"这张地图没画全"。 · 搜索落空时返回的那句提示,方向可能是错的:select: 写了个不存在的名字,回执却让它"换个关键词"。 这两处都会让模型对用户说一句它不该说的话,比如"没有这个能力"。 · 变了什么 · 延迟工具目录默认不再自己设上限 以前目录最多列固定长度的工具名,超出部分只留一句「另有 N 个」——工具特别多时,模型可能拿着一张半截地图就去回答「没有这个能力」。现在默认全部列出(目录只放工具名,本身很小),「延迟参数」里新增一个默认关闭的「限制目录大小」开关,真要压上下文时再自己给数。 为什么可以不设上限:拿它和没有这个功能的情况比,而不是和旧的上限比。按两个实测口径(完整定义约 442 字符/工具、只列名字的目录约 25.6 字符/工具),两者比例恒为 17.2×;128k 上下文窗口在约 1,158 个工具处就会被常驻 schema 吃光,而那时目录只占约 7k token。也就是说这类用户只有靠本功能才跑得起来,上限在这条曲线上没有保护作用。 · 搜索落空时不再指错方向 select: 写了个不存在的名字时,以前会把「未命中」说成「schema 都齐了,直接调」,改口之后又说成「换个关键词」——两种都不对。现在按查询形态分开回执:名字不对就说名字不对,并讲明只能逐字复制、这个名字不在目录里;用点或空格把服务器和工具连起来写的(如 browser.capture_network),只要真能对上现有工具就直接认。 "只要真能对上"是有严格判据的:工具名被宿主归一化成 [A-Za-z0-9_-],所以 . 与空格不可能是名字的一部分,用它们拆分只有一种解释;单个 _ 是合法名字字符(repo_read_file 可能真是某张工具的名字),因此不做反拼——认了就是猜。拼不回去时一个字都不返回,绝不返回"最像的那个"。 · 怎么用 不需要任何操作。升级后目录默认就是全列;要压上下文时,面板 MCP → 顶部「延迟参数」→ 打开「限制目录大小」并填一个字符数(打开时预填 12500,那只是建议起点)。 · 升级 dsh plugin --profile web update dsh-toolbox-ui 或按 tag 重装: dsh plugin --profile web add github:Imzl-zl/dsh-toolbox-ui#v1.9.0 · 验证 · 全量 node --test 860/860(real-host-loader 的 HOME 用例需设 HOME,历史上同样如此)。 · 目录不截断:600 个长名字的夹具(长度超过旧默认 12,500)断言 truncated === 0 且全部列出。 · 反拼边界三条用例:点/空格能反拼成真实全名;拼不回去返回 found:false 且不编造;单下划线不反拼(select:jshook_tool_1 必须报不存在,哪怕 mcp__jshook__tool_1 就在目录里)。 · 回执分诊:select: 落空不得再出现"schema 齐了"或"换英文关键词";部分命中仍走成功回执。 · 没实测的:真模型收到新回执之后是改走 select: 还是继续换词,未观测;截断目录下模型是否会在搜索前谎报"没有这个能力",也未观测。靠模型没有百分之百,这一版只保证"不指错方向"。
v1.8.32026-10-23
· dsh-toolbox-ui v1.8.3 这一版修的是一件事的放大效应:有项目 MCP 的工作区里,新建一个会话会卡住十几秒(issue #8)。 顺带修掉三处「工具看着在、点了不对」的正确性缺陷。 · 修了什么 · 1. issue #8:有项目 MCP 时新建会话卡顿 项目 MCP 的工具必须复制进每个会话自己的工具层 —— 这是平台结构决定的,不是实现选择: · 平台没有「工作区级工具来源」,作用域只有 global / preset / agent 三档; · agent 唯一的父级槽位在桌面版被 preset 占着(bindScopeParent 对已绑定的 key 直接抛错),所以拿不到「继承」这条路; · 公开读面也没有便宜的读法:get(name, scope) 每次重建整张表,schemas(scope) 对每个工具的 parameters 做全量深拷贝。 原实现对每一次 tools/change 都把「读全表 + 对账 + 注册」重做一遍,而一次 207 个工具的工具表变化会派发 200+ 个事件、且每个存活会话各算一遍。代价因此是 O(事件 × 会话 × 工具)。 现在按连接的代次缓存:mcp-client 每次工具同步都整批重建定义对象,所以「缓存里那个哨兵定义还在原处」⇔「这条连接的工具集没变」⇒ 一次读取都不付;真变了才读,且只读一次。事件侧再把同一个微任务里的变化合并成一轮。 真宿主 + 真 stdio、207 个工具、交替两轮实测(同一台机器同一时段,绝对值受负载影响,看比值): | 指标 | v1.8.2 | v1.8.3 | |---|---|---| | 首会话里 register() 的同步段 | 998 / 1359 ms | 29 / 83 ms | | 8 个存活会话后一次 tools/change | 72–104 / 68–83 ms | 0.68–2.19 ms | | 第 8 个会话创建 | 329 / 210 ms | 20 / 45 ms | | 重复注册告警(旧实现每个会话挂载时报一条) | 3 条 | 0 条 | · 2. 重连 / 改完配置之后,会话里的工具是「死的」 旧实现只按工具名字对账。连接换代后名字不变、定义对象全换了,于是会话里留下的是指向已经关掉的那条连接的旧定义 —— 调用失败,而且看不出哪里不对。现在按定义对象本身对账,连接换了就换成新的那一版。 · 3. 读不到工具视图时,会把整批工具卸掉 作用域视图读取失败时,旧实现把它当成「这台服务器现在一个工具都没有」,于是把会话里已装的工具全部 dispose(),等下一次变化再装回来 —— 用户看到的是工具时灵时不灵。现在读不到就保持原状(不增不删),只在面板上记下原因。 · 4. 内部:删掉了一层不必要的「投射期间忽略事件」 旧实现假设「同步代码块里派发的事件必然是本次投射自己发的」,于是把投射期间的事件全部忽略。这条不成立:emit 是同步派发,同一次派发里别的监听器也会同步注册工具(DSH 自己的 tool-subagent 就是这么干的),那些变更会被一起吞掉。删掉后改用「合并 + 幂等重算」,实测各指标持平或更好。 · 验证 · 本地 node --test:833 / 833。 · 真宿主(真 cordis + 真 dsh-tools + 真 dsh-mcp-client + 真 stdio 子进程),207 个工具:8 个会话各自投射 207 个工具,经真 stdio 执行成功,重复注册告警 0 条。 · 真模型闭环:模型看到的就是会话里投射出来的 schema,返回 tool_call,实参打到真 stdio 子进程并回灌,最终回复一致。 · 新增三条回归用例(旧实现上为红):稳态只付一次哨兵 get();连接重建定义后必须刷新成新定义;读失败不得卸载已投射的工具。 · 新增两个探针:.tasks/issue-8-tool-view/probes/sentinel-contract-probe.mjs(验证上游「每次同步整批重建定义」这条前提,上游一改就红)、panel-idle-probe.mjs(把面板轮询成本从事件队列的尾巴里分离出来)。 · 升级 dsh plugin --profile web update dsh-toolbox-ui 新装同样一条: dsh plugin --profile web add dsh-toolbox-ui@^1.8.3 升级后重启 dsh web(桌面版重启应用)。 · 仍然存在的边界(说清楚,免得下次当成 bug 报) · 换代时仍要付一次 schemas(scope) 全量深拷贝(207
v1.8.22026-10-20
· dsh-toolbox-ui v1.8.2 一版全是修复,而且都是「看着能点、点了不对」那一类。 两条主修复:市场页的「移除」从来没成功过;同名条目会把整行锁死,导致你既改不了也删不掉。 · 修了什么 · 1. 市场页「移除」从来没成功过 点「移除」时,客户端把参数包成了对象({ name })发给宿主,而 mcpManager/removeServer 的契约是一个标量 name。客户端代理按位置把实参映射到描述符的 wire 字段,于是宿主收到的是 { name: { name } },被 String codec 在边界挡下: typert gateway: mcpManager/removeServer: wire field "name" failed boundary validation 而面板把这条错误画成了「读取目录失败」——看起来像目录坏了,而不是移除失败。现在真的会删;失败时标题是「移除失败」,来源与文案对得上。 同批修掉的还有一处静默缺陷:技能市场的分类接口少声明了一个参数,locale 在发出去之前就被按实参个数拦下,错误又被调用处的 try/catch 吞掉,所以英文界面里分类名一直是中文、且没有任何报错线索。 · 2. 同名条目不再把整行锁死 一个 serverName 在 loader 里可能对应多条条目:别的 bundle / agent preset 提供的,或更早的配置把同一行写重复了。旧逻辑要求「全场只有一条同名条目」才认自己那条,于是别人多一条 = 你这台编辑 / 停用 / 重连 / 移除全部变灰,只留一句「冲突,只读」。 现在区分两个判据: · 能不能改:只看 loader 条目的 id 是否等于 profile patch 里那一行的 id。写操作只落到这一条,别的层一个字节都不动; · 有几条同名:只作信息——详情里点名另一条的 id 与状态,并说明 mcp-client 在连接期按作用域判重、同名里只有一条连得上。 移除之后如果还剩下别层的同名条目,提示会说明「另一条没动、要重启宿主才会重新连接」,不再用一个泛化文案盖掉。 · 升级 dsh plugin --profile web update dsh-toolbox-ui 升级后重启 dsh web(桌面版重启应用)。更新提示每天最多查一次、进程内缓存 24 小时,重启宿主后立刻生效。 · 顺带:仓库的 latest 回到本线 旧包 dsh-mcp-manager-ui 冻结在 1.5.5,而 DSH 0.2.1 对它是硬不兼容(老包 peer 是 >=0.1.5-rc.1 =0.2.0-rc.1 <0.3.0,两个窗口互斥),所以本线的 Release 从这一版起不再标 pre-release,releases/latest 指向 dsh-toolbox-ui。旧线用户升级路径见 README 的迁移说明。 · 验证 · 本地 node --test:829 / 829。 · 新增 test/client-wire-shape.test.mjs:拿出货的 typert 描述符与面板调用点对撞,检查实参个数与标量/对象形状——把本次修复还原回去它立刻变红。 · 冲突语义:test/host-import.test.mjs、test/tool-search-wiring.test.mjs、test/detail-panes.test.mjs 三处改为「只动自己那条」,并新增「另一条被点名、本行仍可编辑、别层条目仍只读」的用例。
数据来自仓库的 GitHub Release,可能与插件实际版本不一致。

README

由 DeepSeek 最新模型翻译生成
dsh-toolbox-ui DeepSeek Harness Web 的 MCP 管理面板 + 技能管理面板 = 0.2.0-rc.1"> 点右下角悬浮按钮或侧栏「工具箱」打开,面板浮在会话之上——改配置、看技能,都不打断正在进行的对话。两个能力面在同一个面板里切换:MCP 与技能。 面板本身跟随 DSH 的界面语言:DSH 设成 English 时,面板里的文案、按钮与状态一律是英文(词典在 lib/client.js 的 EN_DICT);设成中文或宿主没有语言服务时,显示中文原文。语言开关在 DSH 里,不在面板里:设置 → 通用 → 语言。面板刻意不设自己的开关——语言只有宿主一个真相源,两套开关必然对不上。没手动选过语言时,宿主按浏览器语言推断(浏览器是英文,面板就是英文;这时去设置里选一次中文即可,之后记住该选择)。 界面预览 MCP 市场 MCP 市场 47 个逐条一手核实过的服务,分 10 类;搜索为主操作,配「只要免密钥」筛选与排序。每条如实标注免费额度、要准备什么(密钥 / 连接信息 / 装完还得改的参数),卡片直接安装;已配置的只识别并跳过。
展开完整文档(README 剩余 1 节)
dsh-toolbox-ui

DeepSeek Harness Web 的 MCP 管理面板 + 技能管理面板

= 0.2.0-rc.1">

点右下角悬浮按钮或侧栏「工具箱」打开,面板浮在会话之上——改配置、看技能,都不打断正在进行的对话。两个能力面在同一个面板里切换:MCP 与技能。

面板本身跟随 DSH 的界面语言:DSH 设成 English 时,面板里的文案、按钮与状态一律是英文(词典在 lib/client.js 的 EN_DICT);设成中文或宿主没有语言服务时,显示中文原文。语言开关在 DSH 里,不在面板里:设置 → 通用 → 语言。面板刻意不设自己的开关——语言只有宿主一个真相源,两套开关必然对不上。没手动选过语言时,宿主按浏览器语言推断(浏览器是英文,面板就是英文;这时去设置里选一次中文即可,之后记住该选择)。

界面预览

MCP 市场

MCP 市场

47 个逐条一手核实过的服务,分 10 类;搜索为主操作,配「只要免密钥」筛选与排序。每条如实标注免费额度、要准备什么(密钥 / 连接信息 / 装完还得改的参数),卡片直接安装;已配置的只识别并跳过。

技能面板

技能面板

看本机每个技能的真实作用域与同名遮蔽,启停、删除、读正文与诊断,并一键切换「模型自动调用」——它直接改 SKILL.md 的 disable-model-invocation,只动那一行。

特性

MCP 面

- 逐条看状态、传输方式、连接参数与已注册的工具;展开工具可看完整输入 JSON Schema(必填/可选、类型、枚举、默认值)
- 启停、重连、添加、编辑、移除;凭据类字段默认掩码,点眼睛临时揭示有效运行值并一键复制
- 全局 + 项目双作用域:全局写 Web profile(所有项目可用),项目写该项目 .dsh/mcp.json(只该项目会话可见);项目里还能「屏蔽」某个全局 MCP
- 从本机其他客户端导入:Claude Code、Codex、OpenCode、pi、Claude Desktop、Cursor、Windsurf、VS Code、Gemini CLI、Roo Code 与跨工具共享配置,也能直接粘贴 JSON;写入前预览,支持「合并」与「替换」
- 跨工作区搬运:把本项目的 MCP 复制到另一个已注册工作区(在宿主内完成,凭据不经过浏览器),或导出成 JSON 备份 / 分享
- 工具延迟加载(ToolSearch):让某个服务器的工具不再每轮常驻上下文——模型先看到一份只列工具名的目录,用内置的 tool_search 搜到(关键词或 select:<确切名字>)之后,完整参数 schema 才进它的工具列表并可直接调用。默认不开:行上的「延迟 / 全量」标签点一下就切(或列表顶部一键「全部延迟」);环境变量 DSH_MCP_TOOL_SEARCH=off 整体退回全量注入。机制的三个上限(一次返回条数 / 目录行数 / 已发现集大小)可在「延迟参数」里调,写进 profile patch 的 config.toolSearch

技能面

- 真实作用域与同名遮蔽:同名技能跨作用域是合法配置,面板逐条列出并标出哪一份生效
- 启停(写技能文件里的两个调用面字段,不动文件本身)、删除、读正文与诊断——「技能不生效」的原因直接摆在面板里
- 「模型自动调用」开关:直接改 SKILL.md 的 disable-model-invocation,关掉=删掉那一行(开→关能逐字节还原原文);状态一律取自技能文件本身,读不出来就说「未知」而不是猜一个值
- 定位按磁盘上的真实位置(不按技能名):文件/目录名与 frontmatter 的 name 不一致的技能照样能读、能启停、能删
- 市场接 skillhub.cn:安装前披露发布方认证与安全扫描结论,并要一次显式确认(该确认在服务端校验)

公共

- 入口三选一:右下角悬浮按钮(可拖拽、记忆位置)+ 侧栏「工具箱」;可以只留一个,不能都关
- 跟随 DSH 深色/浅色主题,适配窄屏与移动宽度
- 更新提示与一键升级:每天最多查一次 npm、可关闭、绝不自动升级;升级后弹一次「本次更新内容」,不联网

安装

推荐:npm 安装 —— 之后 dsh plugin update 在 ^1.x 内自动升小版本
dsh plugin --profile web add dsh-toolbox-ui@^1.9.0

或固定 GitHub release tag(不自动跨版本,升级要换 tag 重新 add)

dsh plugin --profile web add github:Imzl-zl/dsh-toolbox-ui#v1.9.0

装完重启 dsh web。卸载(不会删除 profile 里已有的 MCP 条目): sh
dsh plugin --profile web remove dsh-toolbox-ui

不要把 mcp-manager-ui 手工插进 profile 的 cordis.patch.yml、Agent preset 或额外的 --patch 文件——插件命令已经完成这件事,重复装配会明确报错。

升级 sh
dsh plugin --profile web update dsh-toolbox-ui

面板顶部有新版时会显示可关闭的提示条,点「升级」走 DSH 官方的 pluginManager。

⚠️ 1.6.1 及更早的版本不会提示 1.6.2 及之后的新版。 它们的更新检查读的是本仓库的 release feed,而那段时间该 feed 的 latest 被另一条产品线(已冻结在 1.5.5 的旧包)占着,于是永远显示「已是最新」。这个缺陷在 1.6.2 修掉了(改成查本包在 npm 上的 latest),修复只能装在新版里——所以请手动升一次,之后就恢复正常:

sh
dsh plugin --profile web update dsh-toolbox-ui

仍装着旧包 dsh-mcp-manager-ui(≤1.5.5)的话走迁移:1.5.5 面板顶部有一条常驻提示,点「迁移」即装本包、卸掉旧包。若面板里的「升级」按钮报 ERR_PNPM_NO_MATCHING_VERSION,那是旧线的升级源已停用(本仓库的 latest 自 v1.8.2 起指向本包),直接用两条命令:

sh
dsh plugin --profile web remove dsh-mcp-manager-ui
dsh plugin --profile web add dsh-toolbox-ui

详见安装与升级。

快速上手

打开面板:右下角悬浮按钮,或侧栏底部「工具箱」。面板浮在会话之上,按 Esc 或点「关闭」收起,不影响会话。

两个作用域:

| 标签页 | 存哪 | 谁可见 | 改动何时生效 |
| 全局 | Web profile 的 cordis.patch.yml | 所有项目 | DSH 热加载,通常立即生效 |
| 某项目 | 该项目 .dsh/mcp.json | 只该项目会话 | 写盘即生效,不需重开会话或重启 Host |

serverName 按作用域判重:不同项目之间、全局与项目之间可以同名,各自独立连接;同一作用域内不能重名。

加 MCP:面板顶部「添加 MCP」填表单,「导入 MCP」粘贴其他客户端的配置(先预览再写入)。常用服务器有预设模板。

常见问题

项目里的改动什么时候生效? 保存的那一刻就对齐到正在运行的会话:新增立刻挂上存活会话、删除立刻撤掉工具、改动就地重载连接——不需要重开会话,也不需要重启 Host。手工编辑 .dsh/mcp.json 则在下一次会话挂载时被采纳。

连接跟配置走,不跟会话走。 最后一个会话结束不会拆掉连接,它只进入空闲等待,下一次会话直接复用——「要用的时候」它已经就绪。两个旋钮写在 server 条目里:idleTimeoutMs(空闲保留多久,默认 5 分钟,0 = 永不回收)与 readyTimeoutMs(挂载时等就绪的总预算,默认 5s,0 = 不等)。字段速查见设计与限制。

项目行那些状态文案是什么意思? 它们把两件独立的事分开说:连接在不在(已连接 · 当前无会话使用(连接保留,下次直接用) / 已连接 · N 个会话在用 / 连接中… / 连接失败 / 尚未建立连接(新会话自动挂载))与几个会话在用——不再有「待会话挂载」那种把两者压成一句、容易被读成「还没连上」的合成状态。

面板显示「已禁用」,模型却报 unknown tool "mcp__xxx__…"? 那个 MCP 被禁用了,所以它没有注册任何工具。在面板里点「启用」即可。

「延迟」打开后,模型还找得到那些工具吗? 找得到,但不是靠全量可见:提示词里只有一份只列工具名的目录加一句引导(没有描述、也没有参数 schema),模型用 tool_search 按关键词或 select:<确切名字> 命中后,完整 schema 才进工具列表、之后可直接调用;凭记忆直调尚未加载的工具会被拒绝,拒绝里给出确切的那条查询串,照抄即可。工具只有两三个的服务器开了省不下什么(每轮仍要付一段引导语),工具多的才划算。要整体退回全量注入:环境变量 DSH_MCP_TOOL_SEARCH=off。注意行上那颗「延迟 / 全量」标签显示的是你的配置(逐台的 defer 值)——点它即可切换;它不表示「此刻这个会话里机制真的生效了」。

单台怎么开,在哪儿开? 列表每一行都有一颗标签:显示「全量」= 这台的工具常驻,显示「延迟」= 已按需加载。点它就切,不用进「编辑」框(项目视图里出现的全局条目要在「全局」标签页里改);想一次全开/全关用列表顶部的 ⚡「全部延迟」。工具数很少的服务器勾了也生效,面板会提示省下的空间可能不多。

两个上限在哪儿调? 面板 MCP → 顶部「延迟参数」:maxResults(一次搜索最多返回几个工具,默认 10)、maxDiscovered(已发现集上限,默认 20);另外有一个默认关着的「限制目录大小」开关(maxCatalogChars)——关着就是全部工具都列进目录,只有工具特别多、又想压上下文时才需要打开它(打开时预填 12500,那只是建议起点)。保存后写进 profile patch 的 config.toolSearch,当前会话立即生效(不需要重启);与默认相同的值不写盘,所以将来默认值调整时你会跟着走。也可以直接手写这段配置,改完重启 dsh web 生效——⚠️ 拼错键会让插件加载失败并报出具体路径(不是静默忽略),改对再重启即可。
「挂载失败」「连接失败」「作用域隔离失败」怎么区分? 三件不同的事:挂载失败=会话挂载阶段就没挂上;连接失败=mcp-client 连不上或重连耗尽;作用域隔离失败=连接正常但工具不在共享作用域层。详情页会给具体原因,排查见设计与限制。

会碰到我的其他配置吗? 不会。全局改动只动由 @deepseek-ai/dsh-mcp-client 声明、且由本插件管理的条目,保留其他插件条目、注释与 !!js 表达式;卸载也不会删除你已有的 MCP 条目与项目的 .dsh/mcp.json。

兼容性

| 项目 | 已验证 |
| DeepSeek Harness | 0.2.0-rc.1 及以上(0.2.0-rc.2、0.2.1-rc.2、0.2.1-rc.3 与 0.2.1-rc.5 都跑过全量;0.2.1 宿主自带的 cordis 4.0.5 / loader 1.0.6 也在覆盖内) |
| Node.js | DSH 自带/支持的运行时 |
| 平台 | Windows;Linux/macOS 使用同一 DSH Web 契约 |

只支持 0.2.x 起:ToolSearch 依赖 0.2 的 per-agent 呈现模式(ctx.tools.modeFor(agent))与 tools:sdk 手册段,0.1.x 上这两样都不存在。不为旧版本保留降级分支。
支持面就是 0.2.0 与 0.2.1 两条线:两者之间宿主换了两代 loader(1.0.3 → 1.0.6),启动错误传播与 dispose 写盘行为都变了,插件对这两处做了显式适配并各有一条常驻用例。

开发 sh
npm test # 全部测试(含真机集成用例:真 cordis / dsh-tools / dsh-scope / dsh-mcp-client + 真 stdio MCP 子进程)
dsh web # 起 Web 做真实操作验证

文档

中文版与英文版内容一致,.en.md 是英文版。两份在开头互链;文内目录锚点各按自己语言的标题生成(中文锚点在英文文档里解析不到,反之亦然),跨文档链接指向对应语言的那一份。

- 安装与升级 —— 三种安装方式、发布流程、故障排查(English)
- 技能管理 —— 作用域与遮蔽、启停、调用权限、技能市场(English)
- JSON 导入 —— 字段映射与限制(English)
- 项目级 MCP 生命周期 —— 挂载、共享连接与作用域对齐(English)
- 设计与限制 —— 共享连接模型、连接状态语义、已知限制、依赖细节(English)
- DeepSeek Harness 官方插件发布指南

友情链接

LINUX DO

License

MIT
预览分享卡片长什么样 ↓Imzl-zl/dsh-toolbox-ui
分享 · DeepSeek Harness Hub
Imzl-zl/dsh-toolbox-ui

DeepSeek Harness Web 的 MCP 服务管理界面——浮动面板、JSON 导入,配置档持久化。

回到顶部