Skip to content
dsh.fish
Bundle

@why913/dshx

DeepSeek Harness(dsh)的 MCP / Skill / 记忆管理工具:写入前先连接自检,连不上不写;从 Claude Code / Codex 一键迁移;可装成 dsh 插件,在 Web 里用 /mcp 命令和卡片操作。

Source
why913
stars
5 stars
License
MIT
Updated
Updated 3 days ago

Readme

# dshx

中文 | [English](README.en.md)

![dshx 的核心思路:Claude Code 和 Codex 里的 MCP 服务器经过 dshx 的握手与 tools/list 校验,能连上的才写进 dsh,403 或起不来的当场拦下。](assets/dshx-hero.webp)

给 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh`)配的命令行小工具,MCP、skill、记忆一把抓:

- 一条命令增删 MCP 服务器,不用再手改 `cordis.patch.yml`
- 写入前先真连一次,连不上的直接拒绝,坏配置进不了文件
- API Key 走环境变量引用,不会明文留在配置里
- skill 从 GitHub 一条命令装,记住来源 commit,能一键更新
- `import` 三件套:把 Claude Code / Codex 的 MCP、skill、全局记忆全部搬过来
- dsh Web 里有 `/mcp` 命令和可点的卡片,巡检和迁移都不用敲命令行
- 自带 SKILL.md,装上之后 dsh 里的 agent 自己就会用这个工具

```sh
npm install -g @why913/dshx

# 加一个本地服务器
dshx mcp add everything -- npx -y @modelcontextprotocol/server-everything
# 连接测试 everything … 通过(2133ms,发现 13 个工具)
# 已写入 ~/.dsh/profiles/web/cordis.patch.yml

# 从 Claude Code / Codex 一键迁移
dshx mcp import --yes
```

## 为什么做这个

dsh 的 MCP 客户端本身不错(stdio / streamable-http、断线重连都有),但官方没给任何管理命令,加一个服务器只能手改 YAML:先找到 `$DSH_HOME/profiles/xxx/cordis.patch.yml`,再搞懂 patch 分层怎么写,还有个坑——原始文件里是个 `[]` 占位符,直接往后追加必报错。

我们拿 agent 实测过:手改一次要 **6 分半**。Claude Code 里同样的事就是 `claude mcp add` 一条命令的功夫。

另外手改还有个更隐蔽的问题:配置写错了 dsh 不报错,启动后静默挂载零个工具,你还得翻日志猜。dshx 在写入前就把握手和 `tools/list` 跑一遍,坏的根本写不进去。

![命令或 URL 进来,dshx 跑握手和 tools/list,通过的 MCP 进 DSH,403 的被拦在门外。](assets/dshx-mcp-flow.webp)

真机迁移实测(就一台机器,不是什么通用基准):Claude Code + Codex 共 12 个 MCP 服务器,**10 个迁移成功,2 个被拦下**(一个 403,一个起不来)——拦下的这两个就是以前会让你翻半天日志的那种。另外说清楚:下载和跑那个包是 `npx` 的活,dshx 负责确认它真的会说 MCP,确认了才写配置。

## 安装

```sh
npm install -g @why913/dshx
```

想让 dsh 里的 agent 也能直接调(获得 `mcp_add` 等 5 个原生工具,外加 `/mcp` 命令和卡片):

```sh
dsh plugin --profile web add @why913/dshx
```

推荐再装个 skill,agent 遇到 MCP 相关的活会主动想起用 dshx:

```sh
dshx skill add ./skills/dshx       # 会记下来源,以后 skill update 才能用
```

skills 目录是热监听的,装完就生效,不用重启。实测 agent 能自己发现这个 skill,自己调 `mcp_list` / `mcp_test` / `mcp_import`,16 秒干完活。

## 用法

```text
dshx mcp add <name> -- <command> [args...]     加本地 stdio 服务器
dshx mcp add --transport http <name> <url>     加远程 streamable-http 服务器
dshx mcp list                                  列出已配置的服务器
dshx mcp rm <name>                             删除
dshx mcp test <name>                           只测连接,不改配置
dshx mcp import [--yes]                        从 Claude Code / Codex 搬 MCP

dshx skill list                                列出 skill(顺带体检格式问题)
dshx skill add <owner/repo[/子目录] | 本地路径>  从 GitHub 或本地装 skill
dshx skill rm <name>                           删(只删自己装的,--force 才删别的)
dshx skill update <name>                       按记录的来源重新拉取
dshx skill import [--yes]                      从 ~/.claude/skills 搬 skill

dshx memory import [--yes]                     把 CC/Codex 全局记忆搬进 $DSH_HOME/AGENTS.md
```

说明:skills 目录 dsh 是热监听的,装完立即生效;项目里的 CLAUDE.md 不用搬,dsh 本来就认。记忆迁移写的是带标记的段落,重跑只更新自己写的段,不动你手写的内容。三个 `import` 默认都只是预览,加 `--yes` 才写。密钥有一句得说清:**你自己**用 `$VAR` 写法给的值会存成引用,但源配置里本来是明文 token 的,搬过来还是明文。

常用参数:

| 参数 | 说明 |
|---|---|
| `--profile <name>` | 写到哪个 profile,默认 `web` |
| `--global` | 写到 `$DSH_HOME/cordis.patch.yml`,所有 profile 共用 |
| `--env KEY=$VAR` | 环境变量。`$VAR` 写法会存成 `!!js process.env.VAR` 引用,密钥不进文件 |
| `--header 'K: V'` | http 服务器的请求头,值同样支持 `$VAR` |
| `--timeout <ms>` | 连接测试超时,默认 30 秒 |
| `--no-test` | 跳过连接测试,强行写入 |
| `--force` | 覆盖同名服务器 |
| `--agents` | skill 装到 `~/.agents/skills` |

## dsh Web 里长什么样

同一个插件还带一个 `/mcp` 命令,结果是可以点的卡片:

```text
/mcp

  MCP 服务器 · 9/10 连通                                    [全部重测]
   ✓ codex           2 tools · 322ms                           [重测]
   ✓ playwright     24 tools · 7942ms                           [重测]
   ✗ node_repl      连接失败 · 60ms                             [重测]
       MCP error -32000: Connection closed

/mcp import

  可迁移 2 个 · 已管理 10 个                                [全部迁移]
   + openai-docs   claude-user · streamable-http · https://…     [迁移]
   + obsidian      claude-user · stdio · node …\main.js          [迁移]
   = codex         已管理
```

| 写法 | 干什么 |
|---|---|
| `/mcp` | 全部服务器巡检,一行一个 |
| `/mcp <server>` | 只测一个,顺带列出它的工具名 |
| `/mcp import` | 列出可迁移的(已管理的自动剔掉) |
| `/mcp import <server>` / `/mcp import all` | 真迁移,每个都先连接测试 |
| `/mcp help` | 上面这些 |

按钮是**重放命令**,所以点「重测」或「迁移」会在下面新出一张卡片,而不是原地刷新——命令日志是只追加的。没装客户端那半边的话,同一个命令照样显示成纯文本。

## 几条设计上的死规矩

1. **先测后写,连不上不写**——命令行、agent 工具、卡片按钮三条路都一样
2. 重名报错,`--force` 才覆盖;`rm` 只删自己写的条目,不碰别的
3. 改 YAML 不破坏你的注释;删光之后把 `[]` 占位符还原回去
4. 改完提示你重启生效,绝不偷偷杀你正在跑的会话
5. skill 装之前先体检:缺 `name`/`description`、名字不是 kebab-case、用了老的 `disableModelInvocation` 驼峰键,一律拒绝——总比装进去之后在 dsh 里静默加载失败好

## 做不到的事

- **斜杠命令只在 dsh Web 里有。** 官方 `headless` CLI 会把位置参数整个丢给模型,所以 `dsh --profile headless "/mcp"` 是发给模型而不是命令注册表。终端里请用 `dshx mcp …`
- **拿不到 dsh 的真实连接状态**,所以 `/mcp` 是自己新建一条诊断连接来报告,看不到 dsh 那边的活连接和重连状态
- **不支持需要 OAuth 的 MCP 服务器**,等 dsh 开放接口
- **改完要重载 dsh 才生效**,dshx 不会替你重启任何东西
- **想改已有服务器的某个字段**,只能 `--force` 整条重写

## 路线图

- `/dshx migrate`:把 skill 和全局记忆也做进同一张卡片
- skill / memory 的插件工具形态(让 agent 也能直接调 `skill_add`、`memory_import`)
- OAuth 认证的 MCP 服务器(Web UI 方案可以看 [dsh-mcp-manager](https://github.com/hyqhyq3/dsh-mcp-manager))

## 说明

dsh 还在 developer preview,变动很快。dshx 只碰有文档保证的东西——patch 文件、`@deepseek-ai/dsh-mcp-client` 的配置格式、`ctx.commands`、以及 `conversation.chat.commandview` 插槽——当前在 `@deepseek-ai/dsh` 0.1.0-rc.6 上测试通过。`@deepseek-ai/dsh-tools` 是 peer 依赖,由宿主提供。需要 Node ≥ 22.19。

非官方社区项目,与 DeepSeek 无关联。

## 许可证

[MIT](LICENSE)

Install

dsh plugin --profile web add github:why913/dshx

Profile: web

  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source