npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@omdp/dsh-connector

v0.3.8

Published

Unified DeepSeek Harness connector: edit MCP servers (cordis.patch.yml), user skills (~/.dsh/skills) and browse the ModelScope MCP/Skills marketplaces from one Web UI settings page.

Readme

@omdp/dsh-connector

MCP 服务器 + 用户 Skills + 魔搭市场浏览三合一设置页(v0.3.8)。适合需要在 DSH 里频繁增删改 MCP server / skills、又不想手改 cordis.patch.yml 的用户。

Requirements

  • DeepSeek Harness 带 web profile GUI(npx @deepseek-ai/dsh web)
  • Node.js ^22.19 或 >=24
  • @deepseek-ai/schemastery 3.18.1 / 3.18.2 / 3.18.4(peer 枚举,供工具过滤的 Config 声明用;无则过滤静默全放行)
  • 已实测 DSH 0.1.5-rc.1(源码级核查,2026-09-10)、0.1.5-rc.2 与 0.1.6-alpha.1(源码级 + 运行时冒烟:/connector/api/* 正常服务、设置页渲染,2026-09-15,见 docs/plugin-compatibility.md)、0.1.7-rc.1(0.3.3 适配:修掉 import 期崩溃 + 迁移到 settings 托管配置,2026-09-24)、0.1.7-rc.2(0.3.5:rc.1→rc.2 tarball 逐文件 diff 零 API 变化 + rc.2 真机回归实测通过;0.3.6 再修 CRLF 解析 + 取当前 profile 补丁路径,2026-09-25)、0.2.0-rc.1(0.3.7:lib/ 逐字节零变化 + 0.2.0 门禁放行 + 沙箱真机装配入树,2026-09-28)
  • @deepseek-ai/dsh peer 声明 >=0.2.0-rc.1 <0.2.1-0(0.3.8 起改用三元组区间:实测 0.2.0-rc.1 ⇒ 自动放行 0.2.0-rc.2(已验证)/ 后续 rc / 正式版 0.2.0;规范见 AGENTS.md 规范 3)

兼容性门禁(0.3.4 起声明)

0.3.4 起本插件在 peerDependencies 里显式声明支持的 DSH 版本:

"peerDependencies": {
  "@deepseek-ai/dsh": ">=0.2.0-rc.1 <0.2.1-0"
}

这条声明由 DSH 自己的 evaluatePluginCompatibility()(dsh-app-boot 的公开导出,是一个 Inspector 可查的正式机制、不是本插件自造的约定)在安装时与每次启动时校验,语义是「声明版本 = 我实测过的版本」:

| 运行中的 DSH | 行为 | |---|---| | 0.2.0-rc.1(实测,2026-09-28) | ✅ lib/ 逐字节零变化(dsh-web-app/dsh-host-webserver 等本插件依赖面在 rc.2→0.2.0-rc.1 全量文件 SHA1 一致);0.2.0-rc.1 门禁对本插件 0.3.7 判定放行;沙箱真机(官方 [email protected] + 本插件)--dump-config 装配入树、零拦截 | | 0.2.0-rc.2(实测,2026-09-30) | ✅ rc.1→rc.2 全量 20 包逐文件 SHA256 diff:本插件依赖面只有 package.json 版本号变化;dsh 主包的变化全部是 desktop profile 支持(与本插件无关);门禁放行 | | 0.2.0-rc.3 / 同一三元组内后续 rc / 正式版 0.2.0 | ✅ 自动放行,无需改声明或重发包:都落在 >=0.2.0-rc.1 <0.2.1-0 区间内 | | 0.2.1-rc.1 / 0.3.0 等跨三元组版本 | ⛔ 门禁拦下:上界 <0.2.1-0 精确切在同一三元组的末尾,跨 patch/minor 必须重新核查后新增区间 | | 0.1.7-rc.1 / 0.1.7-rc.2 | ⛔ 自 0.3.8 起不再声明(本插件只承诺 0.2.0 线):这两个运行时上会被门禁跳过。需要在 0.1.7 上用请装 0.3.7 | | ≤0.1.6 及 0.1.7-alpha.x | ➖ 不受影响:那些版本里根本没有这个门禁(经解包 npm tarball 逐版核对,0.1.5-rc.2/0.1.5-rc.3/0.1.6-alpha.1/0.1.6-alpha.2/0.1.7-alpha.1/0.1.7-alpha.2 的 dsh-app-boot 里 evaluatePluginCompatibility 出现 0 次,只有 0.1.7-rc.1 出现 4 次),旧运行时读到这条 peer 只是「不认识的声明」,照常加载 |

为什么用「三元组区间」而不是逐版本枚举:逐版本枚举要求每发一个 rc 就改声明 + 重发包(0.2.0-rc.1 → rc.2 已连续踩两轮,每轮都表现为「插件整项消失、路由 404」);而同一 [major,minor,patch] 三元组内的 rc 属同一 API 契约的迭代(实测 0.2.0-rc.1 → rc.2 全量 lib/ 逐字节零变化),故实测该三元组的首个 rc 即可放行其后续 rc 与正式版。区间最多只宽到一个三元组,跨 patch/minor 仍需重新核查 —— 见 AGENTS.md 规范 3。

⚠️ 上界必须写 <0.2.1-0,不能写 <0.2.1:semver 里预发布排在正式版之前,0.2.1-rc.1 < 0.2.1 成立,写 <0.2.1 会把下一个三元组的 rc 漏放进来。-0 是该三元组的最小预发布。

升级 DSH 后若设置页突然看不到 Connector 标签,先看启动日志有没有 skipping profile bundle——若新版本跨了三元组(如 0.2.1-rc.1),核查通过后新增一段区间并同步更新 docs/plugin-compatibility.md。

Overview

把 MCP 服务器、用户 Skills 的管理和 魔搭(ModelScope)市场浏览 合并到 DSH Web UI 的同一个设置页(设置页标签:Connector)。

  • MCP:读取/编辑 profiles/web/cordis.patch.yml 中的 mcp-* 块(结构化表单)。保存后重启 dsh 生效。
  • 工具过滤(0.3.0 新增):每台 MCP server 卡片下可勾选放行的工具(mcp__<server>__<raw> 公开名按 __ 切分回 raw 名)。规则存本插件自己的配置(0.1.7+ 为 profile 条目 connector 行的 config.toolFilters;rc.x 为 settings.yaml 的 connector.toolFilters,双后端自动判别),无配置 = 全量放行;保存后新会话即生效、无需重启。生效三件套:systemPrompt.tools(provider) 隐藏 schema + ctx.tools.guard 执行期硬拦截(做法参照 hyqhyq3/dsh-mcp-manager)。典型场景:tinyfish 这类 15 个工具只留 search/fetch_content 两个免费工具。
  • Skills:列出/查看/编辑/删除 ~/.dsh/skills 下的 SKILL.md。保存即时生效(filesystem provider 自动重新发现)。
  • 市场探索(0.2.0 新增):只读浏览魔搭社区 Skills 中心 与 MCP 广场(匿名 OpenAPI,无需密钥)。
    • 列表/详情:名称、作者、分类、下载/浏览数、认证标识(Hosted 官方托管 / 已认证)
    • 一键复制 skill 安装命令(npx / curl / modelscope 三种)与 MCP 配置片段(server_config 的 mcpServers JSON)
    • Skill 更新提示:把本地 skill 关联市场条目(写入 frontmatter 的 source/sourceUpdated)后,「检查更新」比对市场 file_last_modified 标出"有更新/最新"
    • 零落盘:市场数据只存在 DSH 进程内存(30 分钟 TTL 缓存),重启即清,从不写文件
    • MCP 为部署模式、无版本概念,不提供更新提示(仅浏览与复制配置)

设计上复用官方两款参考插件的方式:

  • 设置页槽位注册方式参照 dsh-mcp-manager(settings.section + Package 私有 HTTP API)。
  • Skills 的 frontmatter 解析/序列化参照 dsh-skill-manager。

Quick start

# 1. 安装(npm)
cd ~/.dsh/profiles/web
pnpm add @omdp/dsh-connector

# 2. 确认 bundle 挂载
node "$env:APPDATA\npm\node_modules\@deepseek-ai\dsh\lib\bin.js" --profile web --dump-config | grep connector

# 3. 重启 dsh
# 4. 打开 Web UI → 设置 → Connector,即可看到 MCP 服务器和 Skills 两个区

最小可复现:安装后打开设置页 → Connector → 在 MCP 区点「+添加」→ 填一个 stdio server(如 cmd /c npx -y @upstash/context7-mcp)→ 保存 → 重启 dsh → 该 MCP server 可用。

SSE(MCP over SSE) 如何处理

本插件不内置 SSE 桥接。需要连接走 legacy SSE 协议的 MCP 服务器(如知乎搜索 / 全网搜索)时,仍在 cordis.patch.yml 里用 mcp-remote 把 SSE 转成 stdio,本插件只是把它作为一条普通 mcp-remote 配置来可视化编辑。这样避免重造进程管理逻辑——连接本身交给成熟的 mcp-remote。

安装

推荐:本地 link: 安装(避免从 GitHub 直接拉取的网络/TLS 问题)。在 profiles/web/package.json 的 dependencies 里加入(或直接编辑):

"@omdp/dsh-connector": "link:D:/WorkSpace/omdp/dsh-connector"

然后在该 profile 下重建 lockfile 并建立 junction(dsh plugin add 底层就是 pnpm, 等价于):

cd ~/.dsh/profiles/web
pnpm install --lockfile-only --offline   # 按 link 依赖重写 lockfile

pnpm install 会为 link: 依赖建立 node_modules/@omdp/dsh-connector junction 指向 D:/WorkSpace/omdp/dsh-connector,插件源码即仓库源码,改仓库 → 重启 dsh 即生效。

确保 dsh.profile.bundles 里包含 "@omdp/dsh-connector"(包内声明了 dsh.bundle.patch,激活行自动生效,无需手动改 cordis.patch.yml)。

安装前请先备份 profiles/web/cordis.patch.yml。本插件会改写其中的 MCP 块。

方式一(推荐):从 npm 安装

插件已发布到 npm(GitHub Actions 自动发包,见仓库根 docs/npm-publish.md)。 在 profile 的 package.json 加入依赖后 pnpm install:

"dependencies": {
  "@omdp/dsh-connector": "^0.3.4"
}
cd ~/.dsh/profiles/web
pnpm install

更新:pnpm update @omdp/dsh-connector(标准 npm 语义,无 git #path: 问题)。

备选:从 GitHub 远程安装

不想本地 checkout 时,可直接从仓库装(#path: 指向子目录):

dsh plugin --profile web add github:XJungit/omdp#path:dsh-connector

安装命令前提:上面的 dsh plugin add 需要 dsh 已在 PATH。若你是按官方文档用 npx 运行 dsh(没有全局 dsh 命令),上面这行会报 command not found: dsh —— 改用等价命令: npx @deepseek-ai/dsh plugin --profile web add github:XJungit/omdp#path:dsh-connector(不要求 dsh 在 PATH)。

pnpm ≥10 默认拒绝运行 git 依赖的构建脚本,首次 add 会失败,需在 profiles/web/pnpm-workspace.yaml 加白名单后重试:

allowBuilds:
  '@omdp/dsh-connector': true

(本插件是纯 JS 零构建,白名单是唯一门槛,无需 prepare 脚本。详见官方 publish.md。)

更新

本地 link 模式下没有"拉取"这一步:直接 git pull 或编辑 D:/WorkSpace/omdp, 然后重启 dsh --profile web 加载新代码(运行中的进程仍用旧代码)。

卸载

# 1. 从依赖移除
cd ~/.dsh/profiles/web
pnpm remove @omdp/dsh-connector

# 2. 从 bundles 移除(pnpm remove 会重写 package.json,若 bundles 里还有则手动删)
#    编辑 profiles/web/package.json,从 dsh.profile.bundles 删掉 "@omdp/dsh-connector"

# 3. (可选)还原被插件改写的 MCP 块
#    插件改写过 cordis.patch.yml 里的 mcp-* 块;若想彻底还原,从备份恢复或手动编辑

禁用(临时):在 cordis.patch.yml 加一行 - id: connector\n disabled: true (或从 bundles 移除后重启),无需删除包。

使用

打开 Web UI 的 设置 → Connector:

  1. MCP 服务器 区:
    • 列出当前 cordis.patch.yml 里的 mcp-* 服务器
    • 「编辑」改名称/传输/URL/命令/参数/Header;「删除」移除;「+ 添加」新建
    • 每台 server 卡片下有工具过滤多选(chips):勾选即放行,未勾选的工具模型不可见、调用被拒;「清除」回到全量放行
    • 保存后提示重启 dsh 才会真正加载新的 MCP server(工具过滤规则除外:存本插件的 profile 条目配置,新会话即生效)
  2. Skills 区:
    • 列出 ~/.dsh/skills 下的用户技能
    • 「编辑」改 frontmatter 与正文;「删除」移除目录;「+ 新建」创建
    • 「检查更新」:对已关联市场来源的 skill 比对魔搭更新时间,显示"有更新/最新"徽标
  3. 市场探索 区:
    • MCP 市场:输入关键词搜索魔搭 MCP 广场;条目显示作者/浏览数与"已配置"徽标;展开详情看 Hosted / 认证 / 环境变量 / 配置变体,「复制配置」 一键复制 mcpServers JSON 片段
    • Skills 市场:搜索魔搭技能中心;展开详情看三条安装命令(逐个复制,自行执行), 「记录来源」把本地技能关联到该市场条目(写 frontmatter source/sourceUpdated)
    • 全部数据经 host 30 分钟内存缓存代理,仅本机内存,不写盘

工作原理

| 组成 | 机制 | |---|---| | 设置页 | client half 注册 settings.section 槽位("Connector" 页签;client factory 须 exports.inject = ['slots'],否则 fiber 在 slots 就绪前跑 apply 会静默丢注册) | | 跨边界调用 | client 用 fetch('/connector/api/...'),host 用 ctx.webServer.register 接收(安装包走 HTTP) | | MCP 持久化 | 文本块级提取并替换 cordis.patch.yml 中含 mcp- 的 insert 块,保留 !!js 表达式与 env 块原样(preserve 桶) | | 工具过滤 | 规则存本插件 profile 条目(connector 行)的 config.toolFilters,经 Config 的 .volatile() 字段由 DSH settings 服务托管(0.1.7+);systemPrompt.tools(provider) 滤 schema + tools.guard 硬拦截;dsh-mcp-client Config 封闭,规则不能写进 mcp 行 config | | Skill 持久化 | 直接读写 ~/.dsh/skills/<name>/SKILL.md |

已知限制

  • MCP 改动需重启 dsh 才生效(因为 dsh-mcp-client 实例是静态加载的)。若想要保存即时生效,需用 dsh-mcp-manager(它自行实现 MCP client)。
  • 保存时按 dsh-mcp-client 的契约校验:transport 只能是 stdio/streamable-http;serverName 必须匹配 [A-Za-z0-9_-]{1,32};stdio 的 command 必须是单个词且能在 PATH 中找到(或为绝对路径);streamable-http 的 url 必须是合法 http(s)(!!js 表达式除外);命令/URL/参数中不允许控制字符。任何一项不合法,保存会被拒绝(HTTP 400)并提示原因,不会写入 cordis.patch.yml——坏配置永远到不了下次启动。
  • MCP 块解析为结构化提取,复杂嵌套 YAML(如多 env 变量)在表单里以单字段呈现;极复杂配置请直接在 cordis.patch.yml 编辑。
  • 不桥接 MCP 的 resources/prompts,只管理 server 配置。
  • 市场只读:不做 MCP 部署、不做 skill 安装(MCP 部署/部分 skill 安装不是简单改配置)。安装命令/配置片段请复制后自行执行。
  • 版本提示仅限 skill:魔搭 MCP 是部署模式、无版本概念,不提供更新提示;skill 的"有更新"以市场 file_last_modified 对比本地 sourceUpdated 判定(需先「记录来源」)。
  • 市场依赖 modelscope.cn 可达性;不可达时接口返回 502 提示,不影响 MCP/skill 本地管理。

Troubleshooting

| 问题 | 原因 / 解决 | |---|---| | 设置页看不到 Connector 标签 | bundle 未挂载:确认 dsh.profile.bundles 含 @omdp/dsh-connector,重启 dsh;仍无则检查 client.js 尾部 exports.inject = ['slots'] 是否在(缺了会静默丢注册) | | 工具过滤不生效(模型仍能看到/调用) | 过滤规则只对新会话生效(当前会话的 schema 已下发);确认规则落盘位置正确——0.1.7+ 看 profile 条目 connector 的 config.toolFilters,rc.x 看 ~/.dsh/settings.yaml 的 connector.toolFilters;再确认 serverName 拼写与 patch 一致 | | 升级 0.1.7 后勾好的工具过滤变回全量放行 | 0.1.7 的配置迁移会静默漏掉未声明 volatile Config 的段,规则被留在 ~/.dsh/settings.yaml.imported 里;0.3.4 的 ensureLegacyFiltersMigration() 会在首次请求时自动搬回(日志 migrated toolFilters from settings.yaml.imported)。不要删 settings.yaml.imported——它是遗留配置的唯一副本。若仍未恢复,用 PUT /connector/api/mcp/filters 手写一次即可 | | 升级 DSH 后设置页整页丢失 Connector 标签、/connector/api/* 全 404 | 先查启动日志有无 skipping profile bundle "@omdp/dsh-connector"——这是 0.1.7 起的兼容性门禁拦下了尚未核查的 DSH 版本(见「## 兼容性门禁」)。核查通过后把该版本追加进 peerDependencies["@deepseek-ai/dsh"] 枚举 | | 保存 MCP 被拒(HTTP 400) | 配置不合法(transport/serverName/command/url 校验失败),按提示修正——插件不会写入坏配置 | | MCP server 保存后不生效 | 需重启 dsh(dsh-mcp-client 静态加载) | | /connector/api/* 404 | client/host 边界异常:确认插件 host 半边已加载(重启),浏览器强刷缓存 | | 改动丢失 | 检查是否误用了旧版(link: 模式下改仓库源码需重启才生效) |

日志:插件错误会进入 dsh 启动的 stderr 日志(profile 下的 dsh-boot.err)。 回滚:MCP 块改动前先备份 cordis.patch.yml;或直接用 dsh-undo-savepoint 快照回滚。

Development

# 本地开发:用 link: 安装(README 顶部方式一),改仓库源码 → 重启 dsh 即生效
cd ~/.dsh/profiles/web
pnpm add "link:D:/WorkSpace/omdp/dsh-connector"

# 语法检查
node --check D:/WorkSpace/omdp/dsh-connector/index.js
node --check D:/WorkSpace/omdp/dsh-connector/client.js

# 发布(GitHub Actions 自动发包,见 docs/npm-publish.md)
# 改 dsh-connector/package.json 的 version → git tag vX.Y.Z → push

结构:index.js(host,HTTP API)/ client.js(Web UI 设置页)/ cordis.patch.yml(bundle 激活行)。 贡献:PR 到 https://github.com/XJungit/omdp。

License & security

MIT License。安全问题请通过 GitHub Issues 私密报告(https://github.com/XJungit/omdp/issues), 或直接联系维护者。涉及 token 的配置(README「安全实践」)请勿提交到公开仓库。

安全实践

  • 不要在 cordis.patch.yml 里写明文 token。MCP server 需要密钥时,用环境变量引用(!!js process.env.XXX),例如:
    env:
      AUTH_HEADER: !!js ('Bearer ' + process.env.ZHIHU_TOKEN)
    token 明文只存在于 .env / 系统环境变量,不落进配置文件(同 dsh-mcp-manager 的 tokenEnv 理念)。
  • 本插件的 API(/connector/api/*)与 DSH GUI 同源,无额外鉴权——仅限本机使用,不要暴露到公网。
  • Skills 内容与 MCP 配置都属于本地敏感数据,改动会直接写入磁盘。

Permissions & data

| 数据 | 访问方式 | 说明 | |---|---|---| | profiles/web/cordis.patch.yml | 读写 | MCP 块的结构化编辑(保留 !!js/env 原样);0.1.7+ 工具过滤规则也由 DSH settings 服务写回本行 config.toolFilters | | ~/.dsh/skills/**/SKILL.md | 读写 | 用户技能文件的查看/编辑/删除/新建;「记录来源」会写 source/sourceUpdated frontmatter | | ~/.dsh/settings.yaml 等 | rc.x 经 settings 服务读;0.1.7+ 只读 settings.yaml.imported 做一次性救援 | 0.1.7+ 不再直接读写活动配置(DSH 已改为 profile 条目托管);.imported 是遗留配置唯一副本,永不删除 | | HTTP /connector/api/* | 本机监听 | 与 DSH GUI 同源,无额外鉴权 | | 魔搭 modelscope.cn/openapi/v1 | 只读外部 | 市场浏览代理(匿名);结果仅存进程内存(30 分钟 TTL),不写文件、不落盘 | | 环境变量 | 只读引用 | 只读 process.env.*,不持久化 |

不收集:无遥测、无外部上报、无用户数据离开本机。

兼容性

本插件采用抗崩溃架构,DSH 更新时不会导致 DSH 崩溃(硬保证)。

  • 纯静态依赖:只 import node:* + yaml(^2.9.0);jsdom(^24.1.3)只在魔搭 WAF 挑战求解时动态 import(),不在模块顶层加载(见下方 0.1.7 说明)。@deepseek-ai/schemastery 仅 peer 声明(供工具过滤的 Config 声明用),且用 typeof field.volatile === 'function' 守卫,具备则走 0.1.7+ 托管配置。
  • 唯一的 DSH 硬依赖:ctx.webServer(inject: ['webServer']),用于注册 /connector/api/* HTTP 路由。
  • 失败隔离:webServer 不可用/变化时插件干净失败不加载,DSH 照常运行;内部多处 try/catch 防御。

为什么 jsdom 必须懒加载(0.3.3 修复)

0.3.2 在模块顶层 import { JSDOM, VirtualConsole } from 'jsdom',这会在插件 import 期就拉起 jsdom → whatwg-url → tr46 依赖图,而 tr46/index.js 第 3 行是 require("punycode/")。 DSH 0.1.7-rc.1 的解析路由(dsh-app-boot ResolutionRouter.routeScoped)对 punycode/ 这种带子路径的内置模块名会先切出裸名 punycode,再用 createRequire(...).resolve.paths("punycode") 求查找路径 —— Node 对裸内置模块名返回 null,而该处循环没有兜底,直接抛:

TypeError: createRequire.resolve.paths is not a function or its return value is not iterable
    at ResolutionRouter.routeScoped (…/dsh-app-boot/lib/index.js:1414:58)

后果不是"市场功能不可用",而是整个插件的 import 失败:fiber 建不起来,设置页那行永远停在 「已安装,重启后生效」,/connector/api/* 全部 404(重启也不会好,因为抛错是确定性的)。 修复即把 jsdom 挪进 loadJsdom(),只在真正要解 WAF 挑战时才 await import('jsdom'), 失败范围收敛到该功能本身。

⚠️ 诚实说明:这是缓解,不是根治。 DSH 的解析拦截(PluginPackages 安装的 installRuntimeInterception)在进程生命周期内常驻(只在 ctx.effect 清理时 dispose()), 所以懒加载只是把同一个 TypeError 推迟到首次解 WAF 挑战时,并非消除:

| | 0.3.2(顶层静态 import) | 0.3.3(懒加载) | |---|---|---| | 插件 import | ❌ 崩溃 ⇒ 设置页死的、全部路由 404 | ✅ 干净 | | 设置页 / MCP / Skills / 工具过滤 | ❌ 全废 | ✅ 恢复 | | 魔搭市场浏览(走 WAF 解) | ❌(插件都没起来) | ⚠️ 首次解挑战仍会抛,但被 marketError 包成 502 + 明确 message,不挂起 | | 爆炸半径 | 整个插件 | 单个功能分支 |

实测该 WAF 挑战当前未下发(PUT /api/v1/dolphin/mcpServers 返回 HTTP 200、116103 字节、 无 acw_sc__v2/aliyunwaf),故该路径处于休眠。根治仍应由 DSH 在 dsh-app-boot 的该循环 补 ?? [] 兜底(同文件 packageDirFromAnchor 是有兜底的,新增 routeScoped 时漏了)。

| 场景 | 崩溃? | |---|---| | DSH 小更新/补丁 | ✅ 不会崩 | | DSH 大版本(webServer API 变化) | ✅ DSH 不崩;connector 需适配更新 | | yaml 版本 | ✅ 独立 npm 包,不受 DSH 更新影响 | | 魔搭市场不可达 | ✅ 市场接口报 502,本地 MCP/skill 管理不受影响 |

最后验证:DSH 0.1.7-rc.1(2026-09-24,本轮修复:模块 import 期零抛错,node --check + 实际 import() 冒烟通过;工具过滤读写改用 0.1.7 的 Config+.volatile()+settings.replace(); 0.3.4 追加 @deepseek-ai/dsh peer 声明并用 DSH 真实 evaluatePluginCompatibility() 验证门禁行为、 追加遗留 toolFilters 一次性救援)。历史: DSH 0.1.0-rc.8(2026-08-20);0.2.0 市场功能以 node --check + 真实 HTTP 集成测试通过(11 项: skills/mcp 列表与详情、证书/Hosted 标识、安装命令、记录来源回写、更新判定),未改动 DSH 实例。

变更记录

  • 0.3.8(2026-09-30):peer 声明改用三元组区间 >=0.2.0-rc.1 <0.2.1-0(代码零改动)。 背景:0.2.0-rc.2 发布后,门禁又把只声明到 0.2.0-rc.1 的 0.3.7 拦下 —— 已是连续第三轮 同型故障(每轮都表现为「设置页整项消失、路由 404」),根因不是不兼容,而是逐版本枚举的声明 在 rc 迭代下必然过时。 核查依据:0.2.0-rc.1 → rc.2 全量 20 包逐文件 SHA256 diff(本插件依赖面只有 package.json 版本号变化;dsh 主包的变化全部是 desktop profile 支持);用 rc.2 自带的 evaluatePluginCompatibility() 对全版本矩阵实测 —— 0.2.0-rc.1/rc.2/rc.3/rc.9/正式版 0.2.0 全 PASS,0.2.1-rc.1/0.3.0-rc.1 全 BLOCK(11/11 符合预期)。 ⚠️ 本条同时收窄了支持面:0.1.7-rc.1 / 0.1.7-rc.2 不再声明(只承诺 0.2.0 线), 需要在 0.1.7 上运行请继续用 0.3.7。

  • 0.3.7(2026-09-28):追加 DSH 0.2.0-rc.1 支持(peer 枚举 0.1.7-rc.1 || 0.1.7-rc.2 || 0.2.0-rc.1,代码零改动)。 背景:DSH 桌面端升级到 0.2.0-rc.1 后,门禁把只声明到 0.1.7-rc.2 的 0.3.6 拦下 —— 表现是设置页里 Connector 整项消失、/connector/api/* 全部 404(skipping profile bundle,不是崩溃)。 核查依据:0.1.7-rc.2 → 0.2.0-rc.1 的 npm tarball 逐文件 diff(本插件依赖的 dsh-web-app / dsh-host-webserver / dsh-credentials / dsh-settings / dsh-tools / dsh-mcp-client 的 lib/ 逐字节零变化);用 0.2.0-rc.1 自带的 evaluatePluginCompatibility() 判定新声明为 放行;并沙箱安装官方 @deepseek-ai/[email protected] + 本插件跑 --dump-config 真机装配入树、零拦截; npm pack 产物经复核含新枚举。

  • 0.3.6(2026-09-25):修两个真机 bug —— CRLF 补丁文件解析 + 编辑错 profile 的补丁文件。

    1. CRLF 兼容:parseMcpServers() 的键值正则 ^\s+(\w+):\s*(.*)$ 在 CRLF 文件上必然失配 (JS 里 .* 不匹配 \r、$ 也不匹配 \r 之前的位置),于是每行的 transport/serverName/command/url 全部落进 preserve 桶:API 返回 transport:"" serverName:"",UI 的「工具过滤」区因 if (!props.serverName) return null 静默消失、transport 徽标退化成 stdio。修复:解析前用 toLf() 归一化换行(连同 stripQuotes/stripListScalar 的 $ 正则一起恢复),写回时也统一成 LF。 验证:同一份配置文本按 LF / CRLF 两种形态跑解析,修复前 CRLF 五项断言全红、修复后 14/14 通过。
    2. profile 补丁路径:patchPath() 曾硬编码 profiles/web/cordis.patch.yml,在桌面端 (跑 profiles/desktop)会去改 另一个 profile 的文件——写下去对自己的 MCP 配置毫无影响, UI 提示还把错误路径显示给用户。修复:0.1.7+ 从 ctx.get('profileContext').patchPath 取当前 profile 的真实路径(dsh-app-boot 的 ProfileContext 契约),无该服务(0.1.5/0.1.6)时保留 历史路径;GET /api/mcp 一并回传 patchPath,设置页提示改成显示真实路径。 触发场景:用户手改(或编辑器保存)cordis.patch.yml 使其变成 CRLF,桌面端点开 「Connector → MCP 服务器」就只剩 4 张光秃秃的卡片。详见 notes/2026-09-25/debug/connector-crlf-patch-parser-and-profile-path.md。
  • 0.3.5(2026-09-25):追加 DSH 0.1.7-rc.2 支持(peer 枚举 0.1.7-rc.1 || 0.1.7-rc.2,代码零改动)。 背景:DSH 桌面版(DeepSeek Harness desktop)0.1.7-rc.2 上线后,门禁把只声明 0.1.7-rc.1 的 0.3.4 拦下 (skipping profile bundle,插件列表显示「异常」)。核查:rc.1→rc.2 npm tarball 逐文件 diff—— dsh-shell/dsh-settings/dsh-credentials 的 lib/ 逐字节零变化(仅 README/package.json), dsh-llm 仅新增内容类型与错误码(不改既有签名),dsh-app-boot 的变更全部与插件无关 (skippedBundles 诊断重构、generateConfigSchema 内部签名);再用 rc.2 的 evaluatePluginCompatibility() 执行新声明 → undefined(放行)。回归实测:scratch profile ([email protected] + 插件 0.3.4 + 精确版本豁免)真机启动 → /connector/api/mcp/filters 200。 教训:0.1.7-rc.1 这类 rc 枚举在 rc.2 发布当天就会过时——rc 系列每个新 rc 都要重新核查并追加。

  • 0.3.4(2026-09-24):声明 DSH 版本支持 + 修复工具过滤被静默清空。

    1. @deepseek-ai/dsh peer 声明 0.1.7-rc.1(逐版本枚举,语义见上方「## 兼容性门禁」)。 用 DSH 真实的 evaluatePluginCompatibility() 逐一验证:0.1.7-rc.1 → 正常加载; 0.1.7-alpha.2 / 0.1.6-alpha.1 / 0.1.5-rc.3 / 0.1.8-rc.1 → 被门禁拦下(前者是老运行时 无门禁、后者是未实测的新版本,均符合规范 3)。
    2. 修复工具过滤丢失(根因:DSH 0.1.7 的配置迁移是「全有或全无」) —— 0.1.7 首次启动会把 <DSH_HOME>/settings.yaml 改名为 settings.yaml.imported 并逐段导入 profile 条目;该导入 对没有 volatile Config 声明的段会静默跳过(只往 stderr 打一行 settings: section … was not imported)。本插件 0.3.3 才刚引入 Config,所以用户机器上 connector.toolFilters 被落在 settings.yaml.imported 里没搬过来 ⇒ 过滤规则读成空 ⇒ 全量放行(表现为 「设置页里勾的过滤没了」)。 修复:新增 ensureLegacyFiltersMigration(),在路由处理前(apply() 期间 settings.replace() 不可用,因为该条目 fiber 尚未进入 ACTIVE 状态)检查一次——若活的 config.toolFilters 为空、 而 settings.yaml.imported 里还留着 connector.toolFilters,就把它写回本插件的 profile 条目 并打一行 migrated toolFilters from settings.yaml.imported。失败时复位重试标记,下一次请求再试。 一次性且幂等:已有非空过滤规则时不覆盖用户当前设置。
    3. settings.yaml.imported 只读、绝不删除——它是遗留配置的唯一副本(0.1.7 迁移后就地改名, 原始 settings.yaml 已不存在;DSH 内置导入器见到 .imported 不会再跑)。
  • 0.3.3(2026-09-24):适配 DSH 0.1.7-rc.1。

    1. 修复 import 期崩溃:jsdom 由顶层静态 import 改为按需 await import()(原因见上方 「为什么 jsdom 必须懒加载」)——0.3.2 在 0.1.7 上整个插件 import 失败、设置页永远显示 「已安装,重启后生效」、API 全 404。
    2. 工具过滤迁到 0.1.7 托管配置:导出 Config = z.object({ toolFilters: <dict>.volatile() }), 读取走注入的 config.toolFilters 活 Ref、写入走 settings.replace(entryId, …);同时对 0.1.5/0.1.6 rc.x 保留老的 settings.register/get/update 后端(typeof volatile === 'function' 守卫自动分流),新旧两代均可用。
    3. 补 @deepseek-ai/schemastery peer 枚举 3.18.4(0.1.7 自带版本)。