# 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)
