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

技能与 MCP 控制台 6pofx/dsh-tool-explorer

DeepSeek Harnessv0.4.2
6pofx42 天前有提交已提供中文文档扫描:含敏感能力

DSH(DeepSeek Harness)技能与 MCP 管理控制台插件:按来源分级浏览全部已加载技能,分别开关模型调用和用户调用,创建、编辑、删除技能(回收站可恢复),从 GitHub 多选批量安装;增删改 MCP 服务器…

30.5/100
综合分
1
GitHub 星标
—
npm 周下载
—/5
用户评分

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

自动兼容检查有告警:npm 同名包「dsh-tool-explorer」归属 dsh-tool-explorer/dsh-tool-explorer,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add 6pofx/dsh-tool-explorer
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · market
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 42 天前
档位由哪些信号合成

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

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/11/2) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-tool-explorer」归属 dsh-tool-explorer/dsh-tool-explorer,装到的可能不是本插件

展开查看检查明细 ↓

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

✓npm 包dsh-tool-explorer @ 0.4.2
✓Node 引擎要求 >=20 · 基线 Node 22.19 满足
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/14 18:57:12

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

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

读写/删除本地文件
查看扫描证据(共 72 处,展示前 51 条)
  • 读取本地文件
    src/agents-mcp.ts:52
    const parsed = JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>
  • 读取本地文件
    src/agents-mcp.ts:237
    text = readFileSync(path, 'utf8')
  • 读取本地文件
    src/agents-mcp.ts:260
    exists = readFileSync(path, 'utf8').length >= 0
  • 写入本地文件
    src/patch-text.ts:206
    writeFileSync(tmp, text, 'utf8')
  • 写入本地文件
    src/patch-text.ts:208
    renameSync(tmp, path)
  • 写入本地文件
    src/patch-text.ts:212
    renameSync(tmp, path)
  • 读取本地文件
    src/patch-text.ts:222
    return readFileSync(path, 'utf8')
  • 读取本地文件
    src/routes.ts:76
    const manifest = JSON.parse(readFileSync(fileURLToPath(new URL('../package.json', import.meta.url)), 'utf8')) as { version?: string }
  • 写入本地文件
    src/skills-install.ts:111
    writeFileSync(join(dir, 'repo.tar.gz'), buffer)
  • 删除本地文件
    src/skills-install.ts:113
    rmSync(join(dir, 'repo.tar.gz'), { force: true })
  • 读取本地文件
    src/skills-install.ts:120
    return readdirSync(base, { withFileTypes: true })
  • 读取本地文件
    src/skills-install.ts:130
    if (!existsSync(file)) return null
  • 读取本地文件
    src/skills-install.ts:185
    for (const entry of readdirSync(current, { withFileTypes: true })) {
  • 读取本地文件
    src/skills-install.ts:193
    content: readFileSync(full),
  • 删除本地文件递归
    src/skills-install.ts:222
    rmSync(root, { recursive: true, force: true })
  • 读取本地文件
    src/skills-install.ts:259
    if (existsSync(dest)) {
  • 读取本地文件
    src/skills-install.ts:263
    if (!existsSync(join(sourceDir, 'SKILL.md'))) {
  • 写入本地文件
    src/skills-install.ts:271
    mkdirSync(dest, { recursive: true })
  • 删除本地文件递归
    src/skills-install.ts:304
    rmSync(extracted, { recursive: true, force: true })
  • 删除本地文件递归
    src/skills-install.ts:334
    rmSync(extracted, { recursive: true, force: true })
  • 删除本地文件递归
    src/skills-install.ts:353
    rmSync(extracted, { recursive: true, force: true })
  • 删除本地文件递归
    src/skills-install.ts:358
    rmSync(extracted, { recursive: true, force: true })
  • 读取本地文件
    src/skills-trash.ts:69
    const parsed = JSON.parse(readFileSync(join(trashRootOf(host), 'manifest.json'), 'utf8')) as Partial<TrashManifest>
  • 写入本地文件
    src/skills-trash.ts:80
    mkdirSync(trashRootOf(host), { recursive: true })
  • 写入本地文件
    src/skills-trash.ts:82
    writeFileSync(tmp, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8')
  • 写入本地文件
    src/skills-trash.ts:83
    renameSync(tmp, path)
  • 写入本地文件
    src/skills-trash.ts:99
    renameSync(source, destination)
  • 写入本地文件
    src/skills-trash.ts:102
    mkdirSync(destination.replace(/[ /][^ /]+$/u, ''), { recursive: true })
  • 删除本地文件递归
    src/skills-trash.ts:104
    rmSync(source, { recursive: true, force: true })
  • 读取本地文件
    src/skills-trash.ts:113
    while (existsSync(trashDirFor(host, id))) {
  • 读取本地文件
    src/skills-trash.ts:135
    if (!existsSync(originalPath)) return { ok: false, error: `skill "${name}" is not deletable (${originalPath} missing)` }
  • 写入本地文件
    src/skills-trash.ts:145
    mkdirSync(trashRootOf(host), { recursive: true })
  • 读取本地文件
    src/skills-trash.ts:182
    exists: existsSync(join(root, item.id)),
  • 读取本地文件
    src/skills-trash.ts:206
    if (existsSync(item.originalPath)) {
  • 读取本地文件
    src/skills-trash.ts:210
    if (!existsSync(source)) return { ok: false, error: `cannot restore "${item.name}": trash copy is missing` }
  • 删除本地文件递归
    src/skills-trash.ts:217
    rmSync(source, { recursive: true, force: true })
  • 删除本地文件递归
    src/skills-trash.ts:236
    rmSync(trashDirFor(host, item.id), { recursive: true, force: true })
  • 删除本地文件递归
    src/skills-trash.ts:250
    rmSync(trashDirFor(host, item.id), { recursive: true, force: true })
  • 读取本地文件
    src/skills.ts:128
    const parsed = JSON.parse(readFileSync(join(agentsHomeOf(host), '.skill-lock.json'), 'utf8')) as {
  • 读取本地文件
    src/skills.ts:143
    const parsed = JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>
  • 写入本地文件
    src/skills.ts:150
    writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, 'utf8')
  • 写入本地文件
    src/skills.ts:151
    renameSync(tmp, path)
  • 读取本地文件
    src/skills.ts:160
    if (!existsSync(path)) return out
  • 读取本地文件
    src/skills.ts:171
    if (existsSync(skillMd)) {
  • 读取本地文件
    src/skills.ts:176
    if (existsSync(flat)) out.set(name, flat)
  • 读取本地文件
    src/skills.ts:183
    return readdirSync(path, { withFileTypes: true }).map(entry => entry.name)
  • 写入本地文件
    src/skills.ts:415
    writeFileSync(tmp, text, 'utf8')
  • 写入本地文件
    src/skills.ts:416
    renameSync(tmp, path)
  • 写入本地文件
    src/skills.ts:445
    mkdirSync(dir, { recursive: true })
  • 写入本地文件
    src/skills.ts:474
    mkdirSync(newDir, { recursive: true })
  • 删除本地文件递归
    src/skills.ts:479
    rmSync(dir, { recursive: true, force: true })
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-client-locale@deepseek-ai/dsh-client-ui-settings@deepseek-ai/dsh-settings@deepseek-ai/schemastery
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 按来源分级浏览技能
  • 独立开关模型/用户调用
  • 增删改MCP服务器

README

由 DeepSeek 最新模型翻译生成
dsh-tool-explorer npm version npm downloads license DeepSeek Harness (DSH) 管理控制台:在 Web 设置页中浏览、安装、更新、编辑与启停技能,并添加、编辑、启用/禁用、测试与监控 MCP 服务器。 版本兼容 同一个版本同时支持所有受支持的 dsh 线。 设置命名空间通过 ctx.settings.register(ns, schema, { base }) 注册 —— 这是设置接口中没有发生迁移的那一部分(0.1.5 线删掉了旧的模块级 settingsNamespace() / installSettingsSection() 辅助函数,那正是过去导致本插件整体加载失败的原因)。区间两端都做了运行时实测。 | DSH | 状态 | | 0.1.5-rc.2(当前) | 支持 —— 启动、host 路由、设置、client bundle 均已运行时实测 | | 0.1.1-rc.2 | 支持 —— 同一组检查已在该版本上实测通过 | | 0.1.0-rc.7 …
展开完整文档(README 剩余 1 节)
dsh-tool-explorer

npm version
npm downloads
license

DeepSeek Harness (DSH) 管理控制台:在 Web 设置页中浏览、安装、更新、编辑与启停技能,并添加、编辑、启用/禁用、测试与监控 MCP 服务器。

版本兼容

同一个版本同时支持所有受支持的 dsh 线。 设置命名空间通过 ctx.settings.register(ns, schema, { base }) 注册 —— 这是设置接口中没有发生迁移的那一部分(0.1.5 线删掉了旧的模块级 settingsNamespace() / installSettingsSection() 辅助函数,那正是过去导致本插件整体加载失败的原因)。区间两端都做了运行时实测。

| DSH | 状态 |
| 0.1.5-rc.2(当前) | 支持 —— 启动、host 路由、设置、client bundle 均已运行时实测 |
| 0.1.1-rc.2 | 支持 —— 同一组检查已在该版本上实测通过 |
| 0.1.0-rc.7 … 0.1.4 其余版本 | 预期可用:该线提供相同的 ctx.settings.register(ns, schema, { base }) 接口 |
| 宿主无 ctx.settings | 可正常加载运行;偏好项回退为组合条目中的配置 |

host 半部改动需重启 dsh web,client 半部支持热更新。dsh 升级后请重跑 dsh-mcp-client 本地补丁 —— 升级会还原官方文件。

功能

技能
- 全量目录(项目/用户/内置/插件各来源)与共享 .skill-lock.json 合并展示
- 按来源分级浏览:可折叠来源树(项目 .dsh → 项目 .agents → 自定义 → ~/.dsh/skills → ~/.agents/skills → 插件 → 内置),来源下再按 provider 分组,附已加载/禁用计数;支持来源、状态筛选与平铺视图
- 搜索、详情预览、在线新建/编辑(kebab-case 校验、frontmatter 表单、Markdown 正文)
- 独立模型 / 用户调用开关:可只关模型调用(disable-model-invocation,保留 / 菜单),也可只关用户调用;双关 = 完整禁用
- 可恢复回收站:删除用户根技能 → 移入 /skills-trash(锁文件条目快照存档);还原可字节级恢复(含锁条目),永久删除/清空则彻底移除
- GitHub 安装:URL 解析(owner/repo、tree 路径、#branch)、候选预览、多选/全选批量安装(同一仓库仅下载一次 tarball,逐技能独立处理冲突,失败可重试)、安装到 ~/.agents/skills 或 ~/.dsh/skills、检查更新/应用(备份+回滚)、卸载
- skillFolderHash 与 Skills CLI(npx skills)字节级兼容

MCP
- 服务器列表:实时状态(fiber 阶段)、工具清单、各服务器工具计数
- 添加/编辑/删除(stdio + streamable-http)与启用/禁用开关 —— 全部通过 profile patch 层写入(HMR 热生效,无需重启)
- 跨 agent 导入:扫描 ~/.claude.json、~/.cursor/mcp.json、~/.codex/config.toml(TOML 子集)、~/.cline/mcp_settings.json、~/.roo/mcp.json、~/.continue/mcp.json、~/.codeium/windsurf/mcp_config.json,一键导入
- 测试连接:独立 SDK 探测(不干扰运行中实例)
- 写入栅栏(expected-hash):与手改配置并发安全

安装

已发布到 npm(v0.4.2):

dsh plugin --profile web add dsh-tool-explorer

不需要挑版本 —— 当前版本覆盖所有受支持的 dsh 线(见 版本兼容)。0.1.5 之前的旧版本仍留在 npm 上可装,并打了 legacy dist-tag 便于固定;它只能在 DSH ≤ 0.1.4 上加载:

dsh plugin --profile web add dsh-tool-explorer@legacy # = 0.4.1,仅 DSH ≤ 0.1.4

dsh plugin 会自动 reconcile bundle。重启一次 dsh web(host 插件在启动时加载),打开 设置 → Skills 和 MCP。

本地开发

pnpm install
pnpm run typecheck # host + client 源码类型检查
pnpm run build # tsc host -> lib/,tsdown client -> client/client.js(含包装与校验)
pnpm test:self # 136 条断言:mock host CRUD、跨 agent 导入、GitHub 安装、回收站、真实 stdio 探测、设置装配

本地安装循环:

pnpm pack
dsh plugin --profile web remove dsh-tool-explorer
dsh plugin --profile web add file:G:/dsh-tool-explorer/dsh-tool-explorer-0.4.2.tgz

⚠️ 新增运行时依赖(如 tar)必须重新打包并重装 —— 只拷贝 lib/ 不够。

参考实现

M5 功能集(来源分级浏览、独立调用开关、可恢复回收站)参考了以下社区插件(克隆在 .ref/ 下备查):

- cheshireez/dsh-skill-hub —— 基于官方 ctx.skills 注册表的 GUI 技能中枢;其 .trash/ 重命名 + 还原 + 清空模式启发了本插件的可恢复回收站
- SeverusZh/dsh-skills-mcp-group-manager —— 分组管理与"影子 provider 过滤模型技能目录"
- BAIKAI23333/dsh-skills-manager —— 设置页技能管理器
- peiqi10086/dsh-skills-market —— 侧边栏技能面板(用户/项目/内置)+ SkillHub 商城

设计取舍:启停沿用平台文档化的 frontmatter 双开关(disable-model-invocation / user-invocable),而非 skill-hub 的 SKILL.md.disabled 重命名;回收站放在技能根之外,避免 provider watcher 观察到干扰。

目录结构

| 路径 | 用途 |
| src/index.ts | host 入口;从注入服务组装普通 host 对象(绝不修改 Cordis scope Proxy) |
| src/routes.ts | /dsh-tool-explorer/api/ 路由(写操作强制同源校验) |
| src/mcp.ts | MCP 管理:patch 层增删改、启停、状态推导、SDK 探测 |
| src/skills.ts | 技能目录(注册表 × 锁文件 × 磁盘)、编辑/启停、独立模型/用户调用开关、frontmatter 解析(完整 YAML) |
| src/skills-trash.ts | 可恢复回收站:删除入站、还原、永久删除、清空(/skills-trash + manifest) |
| src/skills-install.ts | GitHub 安装生态:tarball 下载(区域代理)、候选发现、锁文件 v3、CLI 兼容目录哈希 |
| src/agents-mcp.ts | 跨 agent MCP 导入(JSON + Codex TOML 子集解析) |
| src/patch-text.ts | patch 层方言:解析(!!js 容错)、行级手术编辑、[] 占位符处理、原子写 |
| scripts/ | client bundle 包装/校验、自测、以及 dsh-mcp-client 本地补丁(见下;补丁工具随 npm 包一同发布) |

dsh-mcp-client 本地补丁

两个幂等补丁修复上游 dsh-mcp-client 的缺口(已上报官方讨论)。每次 dsh 升级后都要重跑 —— npm/pnpm 升级与 dshmarket 更新都会还原官方文件,两个症状随即复发:

pnpm run patch:mcp # 在仓库检出里执行
pnpm run patch:mcp:check # 只检查不写文件;缺补丁时退出码为 2

如果是从 npm 安装的(没有仓库检出),补丁工具随包发布,直接用 node 指向它即可(它会自己找到 profile 里的 dsh-mcp-client):

node "$DSH_HOME/profiles/web/node_modules/dsh-tool-explorer/scripts/patch-mcp-client.mjs"

| 补丁 | 修复的症状 |
| startup-wait | 服务器不可达/挂起时 apply() 会永远停在 connection.ready,dsh web 因此永不打印 dsh web: http://…、也不打开浏览器(就绪提示被 loader.await() 卡住)。等待被限制为有上限(默认 3 秒,可用 DSH_MCP_STARTUP_TIMEOUT_MS 覆盖,0 表示不限制);连接转后台继续,工具到达时照常注册。 |
| stdio-stderr | 每个 stdio 服务器的 stderr 都会继承进 dsh 控制台,FastMCP banner、pino JSON 日志、Python 报错会刷屏。补丁强制 stderr: "ignore";调试服务器时可用 DSH_MCP_STDERR=inherit 恢复官方行为。 |

参数:--check(只报告)、--profile (默认 web)、--target (只处理指定安装)。退出码:0 全部就位、1 未找到安装、2 有补丁待应用或写入失败。备份以 index.js..bak 保存在被修补文件旁;替换锚定官方原文,上游改动布局时会明确报错而不会写坏文件。

单补丁入口(旧用法)仍保留:

node scripts/patch-mcp-client-stderr.mjs
node scripts/patch-mcp-client-async.mjs

dsh 升级之后

pnpm run patch:mcp:check # 退出码 2 = 升级已还原官方文件
pnpm run patch:mcp # 重新打补丁,然后重启 dsh

两个症状就是判断依据:控制台被服务器 banner/JSON 刷屏;dsh web 页面能用但始终不打印地址行。

反馈

问题、功能建议与官方沟通渠道:

- 上文两个本地补丁已上报官方:见 DeepSeek Harness Discussions #5129——官方修复进展可以跟帖关注。
- 其他与本插件相关的问题,请在本仓库发起 issue 或 discussion。

许可证

MIT
预览分享卡片长什么样 ↓6pofx/dsh-tool-explorer
分享 · DeepSeek Harness Hub
6pofx/dsh-tool-explorer

DSH(DeepSeek Harness)技能与 MCP 管理控制台插件:按来源分级浏览全部已加载技能,分别开关模型调用和用户调用,创建、编辑、删除技能(回收站可恢复),从 GitHub 多选批量安装;增删改 MCP 服务器…

这是你的仓库?认领条目

回到顶部