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

技能与 MCP 设置分栏 jipika/dsh-skill-mcp-panel

DeepSeek Harness
jipika39 天前有提交已提供中文文档扫描:含敏感能力

在设置窗口分栏管理技能与 MCP,不再占用侧栏主区

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

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

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add jipika/dsh-skill-mcp-panel
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]✓
本站已真实安装成功
非静态推断
L4 · 真实安装等级说明 →
数据截至 2026/09/27·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]—
更新放缓:最近一次提交在 39 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

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

验证判据与等级说明 →

可信度证据

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

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

可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 85 处,展示前 74 条)
  • 读取本地文件
    lib/index.js:531
    const info = await stat(resolvePath(path)).catch(() => undefined);
  • 读取本地文件
    lib/index.js:602
    const scopedRaw = await readFile(entry.file, "utf8");
  • 读取本地文件
    lib/index.js:614
    const raw = await readFile(located.entry.file, "utf8");
  • 写入本地文件
    lib/index.js:647
    await rename(entry.file, target);
  • 写入本地文件
    lib/index.js:677
    await rename(skill.path, target);
  • 删除本地文件递归
    lib/index.js:687
    await rm(dirname(entry.file), { recursive: true, force: true });
  • 删除本地文件
    lib/index.js:689
    await rm(entry.file, { force: true });
  • 删除本地文件递归
    lib/index.js:713
    await rm(dirname(skill.path), { recursive: true, force: true });
  • 删除本地文件
    lib/index.js:715
    await rm(skill.path, { force: true });
  • 写入本地文件
    lib/index.js:950
    await mkdir(dirname(filePath), { recursive: true });
  • 写入本地文件
    lib/index.js:951
    await writeFile(filePath, write.data);
  • 写入本地文件
    lib/index.js:954
    await rename(staging, target);
  • 写入本地文件
    lib/index.js:958
    await rename(stagedFile, target);
  • 删除本地文件递归
    lib/index.js:959
    await rm(staging, { recursive: true, force: true }).catch(() => { });
  • 删除本地文件递归
    lib/index.js:965
    await rm(stagingBase, { recursive: true, force: true }).catch(() => { });
  • 读取本地文件
    lib/skill-files.js:34
    await access(path);
  • 读取本地文件
    lib/skill-files.js:225
    items = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/skill-files.js:235
    || (item.isSymbolicLink() && (await stat(full).catch(() => undefined))?.isDirectory() === true);
  • 读取本地文件
    lib/skill-files.js:243
    const parsed = parseFrontmatter(await readFile(file, "utf8").catch(() => ""));
  • 读取本地文件
    lib/skill-files.js:265
    const parsed = parseFrontmatter(await readFile(full, "utf8").catch(() => ""));
  • 读取本地文件
    lib/skill-files.js:269
    const parsed = parseFrontmatter(await readFile(full, "utf8"));
  • 读取本地文件
    lib/scope.js:45
    const info = await stat(absolute).catch(() => undefined);
  • 读取本地文件
    lib/scope.js:75
    const raw = readFileSync(join(dshHome, "storages", "workspace.json"), "utf8");
  • 删除本地文件递归
    lib/scope.js:105
    await rm(path, { recursive: true, force: true });
  • 写入本地文件
    lib/scope.js:142
    await mkdir(targetRoot, { recursive: true });
  • 写入本地文件
    lib/scope.js:146
    await rename(sourceDir, target);
  • 写入本地文件
    lib/scope.js:160
    await rename(staging, target);
  • 写入本地文件
    lib/scope.js:163
    await mkdir(staging, { recursive: true });
  • 写入本地文件
    lib/scope.js:166
    await rename(stagedFile, target);
  • 删除本地文件递归
    lib/scope.js:167
    await rm(staging, { recursive: true, force: true }).catch(() => { });
  • 删除本地文件递归
    lib/scope.js:171
    await rm(staging, { recursive: true, force: true }).catch(() => { });
  • 删除本地文件递归
    lib/scope.js:181
    await rm(target, { recursive: true, force: true }).catch(() => { });
  • 读取本地文件
    lib/groups.js:37
    const parsed = JSON.parse(await readFile(groupsFile(dshHome), "utf8"));
  • 写入本地文件
    lib/groups.js:62
    await mkdir(groupsRoot(dshHome), { recursive: true });
  • 写入本地文件
    lib/groups.js:65
    await writeFile(tmp, JSON.stringify({ version: GROUPS_VERSION, groups }, void 0, 2) + "\n", "utf8");
  • 写入本地文件
    lib/groups.js:66
    await rename(tmp, target);
  • 读取本地文件
    lib/version.js:17
    const pkg = JSON.parse(readFileSync(fileURLToPath(new URL("../package.json", import.meta.url)), "utf8"));
  • 读取密钥环境变量
    lib/version.js:37
    const token = process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim();
  • 发起网络请求
    lib/version.js:38
    const response = await fetch(RELEASES_LATEST_URL, {
  • 执行外部命令固定命令
    lib/global-shim.js:18
    return execFileSync("npm", ["prefix", "-g"], { encoding: "utf8", windowsHide: true }).trim();
  • 读取本地文件
    lib/global-shim.js:25
    const old = existsSync(path) ? readFileSync(path, "utf8") : undefined;
  • 读取本地文件
    lib/global-shim.js:25
    const old = existsSync(path) ? readFileSync(path, "utf8") : undefined;
  • 写入本地文件
    lib/global-shim.js:28
    writeFileSync(path, content, mode !== undefined ? { mode } : "utf8");
  • 写入本地文件
    lib/global-shim.js:30
    chmodSync(path, mode);
  • 写入本地文件
    lib/global-shim.js:37
    mkdirSync(binDir, { recursive: true });
  • 读取本地文件
    lib/provider.js:79
    const raw = await readFile(candidate.locator.path, { encoding: "utf8", signal: options.signal });
  • 读取本地文件
    lib/cli-skill.js:76
    return Buffer.from((await readFile(fullPath, "utf8")).replace(/^ FEFF/, "").replace(/ /g, "\n").replace(/ /g, "\n"), "utf8");
  • 读取本地文件
    lib/cli-skill.js:83
    const items = await readdir(dir, { withFileTypes: true });
  • 读取本地文件
    lib/cli-skill.js:94
    const target = await stat(full).catch(() => undefined);
  • 读取本地文件
    lib/cli-skill.js:113
    const info = await stat(source).catch(() => undefined);
  • 读取本地文件
    lib/cli-skill.js:125
    const validation = validateFrontmatter(await readFile(skillMd, "utf8"));
  • 读取本地文件
    lib/cli-skill.js:136
    const validation = validateFrontmatter(await readFile(source, "utf8"));
  • 写入本地文件
    lib/cli-skill.js:173
    await mkdir(destRoot, { recursive: true });
  • 写入本地文件
    lib/cli-skill.js:179
    await mkdir(dirname(dest), { recursive: true });
  • 写入本地文件
    lib/cli-skill.js:181
    await writeFile(dest, await readNormalizedMd(file.full));
  • 写入本地文件
    lib/cli-skill.js:183
    await copyFile(file.full, dest);
  • 写入本地文件
    lib/cli-skill.js:185
    await rename(staging, target);
  • 写入本地文件
    lib/cli-skill.js:188
    await mkdir(staging, { recursive: true });
  • 删除本地文件递归
    lib/cli-skill.js:192
    await rm(staging, { recursive: true, force: true }).catch(() => { });
  • 删除本地文件递归
    lib/cli-skill.js:196
    await rm(staging, { recursive: true, force: true }).catch(() => { });
  • 删除本地文件递归
    lib/cli-skill.js:264
    await rm(tmpBase, { recursive: true, force: true }).catch(() => { });
  • 执行外部命令固定命令
    lib/cli-skill.js:281
    const child = spawn("dsh", ["plugin", "--profile", profile, "add", INSTALL_SPEC + "#v" + version], {
  • 删除本地文件递归
    lib/cli-skill.js:577
    await rm(dirname(entry.file), { recursive: true, force: true });
  • 删除本地文件
    lib/cli-skill.js:579
    await rm(entry.file, { force: true });
  • 读取本地文件
    lib/cli-mcp.js:277
    const data = JSON.parse(await readFile(resolve(path), "utf8"));
  • 读取本地文件
    lib/patch-editor.js:18
    return await readFile(path, "utf8");
  • 写入本地文件
    lib/patch-editor.js:147
    await writeFile(temp, content, "utf8");
  • 写入本地文件
    lib/patch-editor.js:149
    await rename(temp, path);
  • 删除本地文件
    lib/patch-editor.js:154
    await rm(path, { force: true });
  • 写入本地文件
    lib/patch-editor.js:155
    await rename(temp, path);
  • 删除本地文件
    lib/patch-editor.js:159
    await rm(temp, { force: true }).catch(() => { });
  • 读取本地文件
    lib/patch-editor.js:178
    const info = await stat(lockPath);
  • 删除本地文件
    lib/patch-editor.js:180
    await rm(lockPath, { force: true }).catch(() => { });
  • 删除本地文件
    lib/patch-editor.js:196
    await rm(lockPath, { force: true }).catch(() => { });
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

社区实装还没有人打卡 · 装过的第一个就是你
依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-home-paths@deepseek-ai/dsh-typert-protocol@deepseek-ai/dsh-subprocess@deepseek-ai/cordis
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 设置窗口分栏管理
  • 技能与MCP管理
  • 不占用侧栏主区

README

由 DeepSeek 最新模型翻译生成
本地改版快照 · Local fork snapshot 这不是上游官方仓库,而是我在本机使用的改版快照:基于上游 Fishquito7/dsh-skill-mcp-panel 2.1.0(MIT)。 与上游的差异只有一处行为变化:lib/client.js 把「技能」「MCP」的管理入口从侧栏行 + 中央主区(sidebar.panellist / main)改为设置窗口里的两个独立分栏(settings.section),并相应新增设置分栏外壳样式、去掉只服务于「返回对话」按钮的 layout 硬依赖(避免设置模态框环境下 layout 缺席导致整个插件不装载);另加 tests/settings-sections-probe.mjs 探针。上游版权归 Fishquito7,本仓库不是上游的发布渠道。 dsh-skill-mcp-panel DSH 插件,在 Web 主页左侧栏「插件」下方提供「技能」与「MCP」两个管理面板(点击即在中央主区打开,不是弹窗),并随包提供统一终端命令 dsh-panel(skill / mcp 两个子命令族)。 注意:本项目提供的参考命令默认指定profile为默认的--profile web,需要更改profile的请自行注意。
展开完整文档(README 剩余 1 节)
本地改版快照 · Local fork snapshot

这不是上游官方仓库,而是我在本机使用的改版快照:基于上游 Fishquito7/dsh-skill-mcp-panel 2.1.0(MIT)。
与上游的差异只有一处行为变化:lib/client.js 把「技能」「MCP」的管理入口从侧栏行 + 中央主区(sidebar.panellist / main)改为设置窗口里的两个独立分栏(settings.section),并相应新增设置分栏外壳样式、去掉只服务于「返回对话」按钮的 layout 硬依赖(避免设置模态框环境下 layout 缺席导致整个插件不装载);另加 tests/settings-sections-probe.mjs 探针。上游版权归 Fishquito7,本仓库不是上游的发布渠道。

dsh-skill-mcp-panel

DSH 插件,在 Web 主页左侧栏「插件」下方提供「技能」与「MCP」两个管理面板(点击即在中央主区打开,不是弹窗),并随包提供统一终端命令 dsh-panel(skill / mcp 两个子命令族)。

注意:本项目提供的参考命令默认指定profile为默认的--profile web,需要更改profile的请自行注意。

安装

1. 安装本包(bundle 层自动挂载,无需编辑配置文件),二选一:

方式一:GitHub Release tarball

dsh plugin --profile web add https://github.com/Fishquito7/dsh-skill-mcp-panel/releases/download/v2.1.0/dsh-skill-mcp-panel-2.1.0.tgz

方式二:npm(预构建,插件市场同款通道)

dsh plugin --profile web add dsh-skill-mcp-panel

两种方式都安装预构建产物,无需本地构建。也可以从 Git 安装(Git 来源的依赖默认禁止运行 prepare 构建脚本;若报 "git-hosted plugins build on install...",把 pnpm 在上面打印的 key 加到 profile 目录 pnpm-workspace.yaml 的 allowBuilds 下再重跑):

dsh plugin --profile web add github:Fishquito7/dsh-skill-mcp-panel

2. 重启网关

重启后刷新页面:左侧栏从「插件」往下依次是「技能」「MCP」,点击哪一个,中央主区就切换成哪一个面板。

功能

两个面板与宿主自带的「插件」页一样,是侧边栏全局面板:点击左栏的「技能」/「MCP」直接把中央主区切过去(不是设置页那种弹窗)。两个页面左上角各有一个「← 返回会话」箭头,点它立刻回到进面板之前那个会话;点会话列表里的任意会话或「插件」也能切走。

技能面板

- skill 卡片列表:预览已注册安装的 skill,点击卡片可展开查看完整内容
- skill 状态:启用、停用状态标签,与内置插件列表同款样式
- skill 管理:开关热启用/停用、删除;按名称搜索;进入页面自动刷新
- skill 添加(0.7.0 统一入口):点“+”直接选文件(.md / .zip),或把文件、压缩包、技能文件夹直接拖进页面——自动识别目录束/单文件/压缩包结构,不合规内容会被拒绝并提示原因
- 工作区分栏(0.3.0):技能实体直接存放在其所属位置里——全局在 ~/.dsh/skills,限定工作区在该工作区的 .dsh/skills。页面“技能列表”下方有一条工作区选择器(折叠式下拉,全局 + 各工作区,最多显示 11 项、其余滚动),选中即只显示该工作区下的技能。
- 批量迁移:“+”号左侧的迁移按钮:源工作区、目标工作区(可多选)与技能都在对话框内手动选择,批量复制或移动(默认不勾选任何技能;逐个迁移、失败不影响其余;移动模式限单个目标)。源工作区有分组时,可在技能列表上方按分组筛选(0.7.0)。
- 技能分组(0.5.0):工作区选择器下方新增分组横栏(全部 + 分组名,放不下时换行),点击只显示该分组下的技能。“分组”按钮(迁移按钮左侧)打开分组编辑器:新建/重命名/ 删除分组、选择工作区、命名并批量勾选成员。分组只写入插件自己的显示配置(~/.dsh/skills/.system/skill-viewer/groups.json),不修改技能目录。
- 作用域化管理(0.6.4):同名技能同时存在于全局与某工作区时,删除、启停、查看内容均按(名称+作用域)精确操作——页面各行独立展开、独立操作,绝不影响其它作用域里的副本;找不到指定作用域的条目会直接报错,不会回退误操作。
命令行同名技能也需用 --global / --project / --workspace 显式指定。

MCP 面板(v2.0.0)
- 主页侧边栏「技能」下方新增「MCP」面板,管理 profile cordis.patch.yml 中的 MCP 服务器受管块;
- 支持 Stdio(本地命令)与 HTTP(streamable-http)两种调用方式;
- 支持新增、编辑、启停、删除、测试连接;保存后由 DSH HMR 热加载,无需重启网关;
- env / headers 密钥在 RPC 与页面中脱敏,编辑时缺省 key 保留旧值;
- cordis.patch.yml 面板块外的用户内容逐字节保留。

主页面板与返回会话(v2.1.0)
- 管理面板从设置页迁移到主页侧边栏:与宿主自带的「插件」页同一套槽位机制(sidebar.panellist 列表槽位 + main 键控槽位),点击左栏「技能」/「MCP」直接在中央主区切页,设置页不再有这两个 tab;面板自带整页外壳(滚动与页边距)。
需要宿主提供上述两个槽位,本机 DSH 0.1.6-alpha.2 已实测。
- 「← 返回会话」箭头:两个页面左上角各一个,点它立刻回到进面板之前那个会话(调宿主 ctx.layout.selectPanel(null),不改变当前会话)。

DSH 版本兼容(v2.0.5)
- 适配 DSH 自 0.1.6-alpha.2 起的 TypertCodec create() 工厂契约 —— 该改动会让仍写 schema: 的插件在注册阶段直接抛错、整个插件树加载失败(网关起不来)。同一份构建同时兼容 0.1.5-rc.2 及更早(读 schema)与 0.1.6-alpha.2 及以后(读 create),无需按版本探测或分开维护分支。
- 作用域选择器固定为折叠式下拉(最多显示 11 项,其余滚动);分组栏改为换行布局。
- 技能列表不再依赖「是否打开了会话」:没有会话时服务端回退全局注册表。

命令行

统一父命令为 dsh-panel。

技能子命令

dsh-panel skill --help

dsh-panel skill list # 列出技能(含工作区:全局 / 工作区) dsh-panel skill add # 添加到全局(.md 文件、目录束或 .zip 压缩包) dsh-panel skill add --workspace D:\项目A # 直接添加到指定工作区 dsh-panel skill scope --global # 迁移单个技能到全局 dsh-panel skill scope --workspace D:\项目A # 迁移单个技能到指定工作区(--copy 复制) dsh-panel skill migrate --from --to [--copy] [--yes] dsh-panel skill update [--profile ] # 检查并更新插件(默认 web 配置)批量迁移(复制/移动) dsh-panel skill disable # 停用 dsh-panel skill enable # 启用 dsh-panel skill delete # 删除(需确认)

MCP 子命令

dsh-panel mcp list [--profile ]
dsh-panel mcp add --name --stdio --command [--args ...] [--env KEY=VALUE ...] [--cwd ] [--profile ]
dsh-panel mcp add --name --http --url [--header KEY=VALUE ...] [--profile ]
dsh-panel mcp enable|disable [--profile ]
dsh-panel mcp remove [--yes] [--profile ]
dsh-panel mcp test [--profile ]
dsh-panel mcp update [--yes] [--profile ]
dsh-panel update [--yes] [--profile ] # 更新整个 dsh-skill-mcp-panel

MCP 配置写入目标 profile 的 cordis.patch.yml 受管块;网关在线时自动热加载。面板块由 dsh-skill-mcp-panel:mcp:begin / # 。
同名技能存在于多个作用域时,enable/disable/delete 需加 --global/--project/--workspace 指定操作哪一份。

工作原理

技能部分:

页面和 dsh-panel skill 命令的每次操作,最终都是对磁盘上技能文件(SKILL.md)的改动,DSH 自带的文件监听器立刻发现变化——所以启用/停用、增删、迁移都热生效,无需重启网关。

- 技能实体直接存放在其工作区的技能文件夹:全局 = ~/.dsh/skills,工作区 = /.dsh/skills,没有隐藏存储或联接点——卸载插件后技能仍是普通文件,照常被 DSH 发现
- 停用 = 把 SKILL.md 改名为 SKILL.md.disabled,启用 = 改回来
- 改变所属位置 = 真实地把文件复制/移动到目标位置的文件夹(先校验、失败回滚)
- 随部署附带的技能(bundled)为只读,不可停用或删除

MCP部分:
- 负责把 MCP 服务器配置写进 profile 的 cordis.patch.yml 受管块;真正连接和注册工具的是 DSH 官方插件 @deepseek-ai/dsh-mcp-client,由 DSH 的 HMR 自动加载。

开发

源码为 TypeScript,位于 src/;编译产物 lib/*.js 随仓库一起提交(保证 Git 直装可用)。
改完源码后运行 pnpm build:tsc 编译到 lib/ 并剥离浏览器束的多余模块标记。
发布时 npm pack 会通过 prepack 自动重新构建,无需手工编译。

卸载

dsh plugin --profile web remove dsh-skill-mcp-panel

License

MIT
预览分享卡片长什么样 ↓jipika/dsh-skill-mcp-panel
分享 · DeepSeek Harness Hub
jipika/dsh-skill-mcp-panel

在设置窗口分栏管理技能与 MCP,不再占用侧栏主区

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部