@huanlin/dsh-plugin-mcp-manager 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +144 -144
  2. package/package.json +13 -9
package/README.md CHANGED
@@ -1,144 +1,144 @@
1
- <p align="center">
2
- <a href="https://dshfind.com/zh/plugins/huanlinoto/dsh-plugin-mcp-manager"><img src="https://dshfind.com/api/card/huanlinoto/dsh-plugin-mcp-manager?lang=zh" alt="dsh-plugin-mcp-manager card"></a>
3
- </p>
4
-
5
- # dsh-mcp-manager
6
-
7
- > DSH MCP 服务器管理插件 — GUI 增删改 MCP 服务器配置 + 工具浏览 + agent 面 `mcp_*` 管理工具。
8
-
9
- ## 定位
10
-
11
- **服务器连接管理 + 工具浏览**。连接生命周期完全委托官方 `@deepseek-ai/dsh-mcp-client`——
12
- 本插件是注册表的「写配置层」+「状态/工具浏览层」,不自己拉连接。
13
-
14
- ```
15
- GUI(settings.section「MCP」) ──HTTP──> /api/mcp-manager ──读写──> profile cordis.patch.yml
16
- Agent 面 mcp_* 工具 ─────────────────────────────┘ (mcp-client insert 行)
17
- │ 配置 HMR 实时挂载
18
-
19
- 官方 mcp-client 实例(连接+注册工具)
20
- GUI 状态/工具浏览 <──ctx.tools.schemas() 过滤 mcp__──┘
21
- ```
22
-
23
- 每台 MCP 服务器 = profile `cordis.patch.yml` 中一条 `name: '@deepseek-ai/dsh-mcp-client'` 的
24
- insert 行。配置 HMR 实时挂载/卸载/热替换,无需重启 web。
25
-
26
- **禁用 ≠ 删除**:禁用写入 entry-level `disabled: true`(与 `id`/`name`/`config` 同级),
27
- loader 跳过挂载该 mcp-client 实例 → 工具不注册(模型不可见),config 原样保留在 patch
28
- 文件中。重新启用只需移除该字段,loader HMR 重新挂载。适合「暂时不让模型用某台服务器」
29
- 而不丢失配置。
30
-
31
- ## 开发
32
-
33
- ### 依赖
34
-
35
- ```powershell
36
- pnpm install
37
- ```
38
-
39
- `@deepseek-ai/*` peer deps 从公共 npm registry 解析(已发布)。`yaml`(eemeli)是唯一运行时依赖。
40
-
41
- ### 三件套
42
-
43
- ```powershell
44
- pnpm typecheck # tsc --noEmit(src/ + tests/;src/client/ 由 tsdown 构建,不进 tsc)
45
- pnpm test # vitest run(registry 单元测试,27 用例)
46
- pnpm build # tsdown 双 bundle:lib/index.mjs(Node half)+ lib/index.js(client half)
47
- ```
48
-
49
- ### 架构
50
-
51
- | 文件 | 职责 |
52
- |------|------|
53
- | `src/registry.ts` | 服务器注册表:eemeli `yaml` Document API 读写 insert 行 + `loadOverlayPatches` 校验 + serverName 唯一 + entry-level `disabled` 字段 |
54
- | `src/tools.ts` | agent 面 `mcp_*` ×5 工具(defineTool,规范 JSON 输出) |
55
- | `src/index.ts` | Node half:`/api/mcp-manager` 路由 + `ctx.tools.schemas()` 过滤 + mcp 工具注册 |
56
- | `src/client/index.ts` | client half:`settings.section` 注册「MCP」面板 |
57
- | `src/client/Panel.tsx` | 面板 UI:服务器列表 + 增删改表单(内联卡片下方)+ 禁用/启用 + 工具浏览 |
58
-
59
- ### 数据模型
60
-
61
- 存储 = profile `cordis.patch.yml` 的 mcp-client insert 行(单一事实来源):
62
-
63
- ```yaml
64
- - insert:
65
- - id: mcp-github # 行 id(mcp-<serverName>)
66
- name: '@deepseek-ai/dsh-mcp-client'
67
- disabled: true # 可选 entry-level 字段:loader 跳过挂载,工具不注册,config 保留
68
- config:
69
- serverName: github # 工具命名空间 mcp__github__*
70
- transport: stdio # stdio | streamable-http
71
- command: npx
72
- args: ['-y', '@modelcontextprotocol/server-github']
73
- env: { GITHUB_TOKEN: '' } # 明文(见下「Secret 处理」)
74
- toolCallTimeoutMs: 60000
75
- failOnStartupError: false
76
- ```
77
-
78
- - 支持 `stdio`(command/args/env/cwd)与 `streamable-http`(url/headers)。
79
- - 编辑 = 整块替换 config(不深合并,与 loader patch 语义一致)。
80
- - **禁用** = 设置 entry-level `disabled: true`(与 id/name/config 同级,不在 config 内)。
81
- loader 跳过挂载 → 工具不注册 → 模型不可见;启用 = 移除该字段。
82
- - 写前用 eemeli yaml 解析 + 可选 `loadOverlayPatches`(app-boot)校验;写后失败自动回滚。
83
- - **保留**其他行的 `!!js` 表达式与注释(eemeli Document API 往返保留)。
84
-
85
- ## 运行
86
-
87
- ### 安装
88
-
89
- ```powershell
90
- # 本地开发(link: 热更新——改源码后 pnpm build 即可见)
91
- dsh plugin --profile web add "link:<本仓库路径>"
92
-
93
- # 远端(预构建 lib/ 入库,无 prepare,开箱即用)
94
- dsh plugin --profile web add "github:dsh-external/dsh-mcp-manager"
95
- ```
96
-
97
- 安装后**重启 dsh web**(bundle 层在 boot 时加载),浏览器硬刷新(`Ctrl+Shift+R`)。
98
-
99
- ### 使用
100
-
101
- - **GUI**:设置页 → 「MCP」面板。
102
- - 新增/编辑/删除服务器;编辑表单内联在对应卡片下方(不在全局底部)。
103
- - 禁用/启用服务器(不删除配置;禁用后 loader 跳过挂载,工具不注册,模型不可见)。
104
- - 点击「工具」展开该服务器的 `mcp__*` 工具列表(禁用状态下不可展开)。
105
- - **Agent**:模型可调用 `mcp_server_list` / `mcp_server_add` / `mcp_server_update` /
106
- `mcp_server_remove` / `mcp_server_set_enabled`。
107
-
108
- ### API 路由
109
-
110
- | 路由 | 方法 | 说明 |
111
- |------|------|------|
112
- | `/api/mcp-manager/servers` | GET | 列出服务器 + 工具数 + 状态 + disabled |
113
- | `/api/mcp-manager/servers` | POST | 新增(body: `{config}`)→ HMR 挂载 |
114
- | `/api/mcp-manager/servers/<id>` | PUT | 编辑(整块替换 config) |
115
- | `/api/mcp-manager/servers/<id>` | PATCH | 禁用/启用(body: `{disabled: boolean}`;config 保留) |
116
- | `/api/mcp-manager/servers/<id>` | DELETE | 删除 |
117
- | `/api/mcp-manager/tools` | GET | 工具浏览(`mcp__` 前缀按 serverName 分组) |
118
- | `/api/mcp-manager/status` | GET | 运行态状态(含 disabled) |
119
-
120
- ### Secret 处理
121
-
122
- ⚠ **P0:env / headers 以明文存入 profile `cordis.patch.yml`**(与官方示例同形态)。
123
- README 明确警示:勿放长期密钥;部署隔离。P1 可接 `@deepseek-ai/dsh-credentials`(待设计)。
124
-
125
- ## 检查(合规自检,对照 plugin-development-guide.md §10)
126
-
127
- - [x] **零源码 patch**:未修改 DSH checkout 任何文件
128
- - [x] **B1**:`package.json` 声明 `dsh.bundle.patch`
129
- - [x] **B2**:自带 `cordis.patch.yml`(insert 行 id/name 齐全)
130
- - [x] **B3**:patch 行 `name` 用包名 `@huanlin/dsh-plugin-mcp-manager`
131
- - [x] **F1**:`files` 含 `lib/` + `cordis.patch.yml`
132
- - [x] **F2**:`peerDependencies` 含 `@deepseek-ai/cordis` + `@deepseek-ai/*`(dsh-tools / dsh-llm / dsh-app-boot / dsh-client-ui-primitives / dsh-client-ui-slots / dsh-client-ui-renderer / dsh-client-locale / dsh-client-ui-settings,对齐 v0.1.2-alpha.1 的 client-runtime 拆分)
133
- - [x] **F3**:typecheck / test / build 三 script 齐全(预构建策略:无 prepare,lib/ 入库)
134
- - [x] **A4**:Config 校验用 `validateServerConfig`(fail loud,携带字段名)
135
- - [x] **A6**:不导出 default
136
- - [x] **C4**:工具返回规范 JSON 值 + render 投影分离
137
- - [x] **G**:测试分层(Unit:35 用例覆盖增删改/禁用/唯一/非法拒绝/!!js 保留/空文件/多行)
138
- - [x] **README**:含开发/运行/检查三节
139
-
140
- ### 预构建策略说明
141
-
142
- 含 `@deepseek-ai/*` private peer deps → 采用**预构建 `lib/` 入库**策略:
143
- `lib/` 不进 `.gitignore`,无 `prepare` 脚本。`github:` 安装开箱即用(pnpm 在 git install 的
144
- prepare 阶段拉不到 private 包,故不能用 prepare 策略)。
1
+ <p align="center">
2
+ <a href="https://dshfind.com/zh/plugins/huanlinoto/dsh-plugin-mcp-manager"><img src="https://dshfind.com/api/card/huanlinoto/dsh-plugin-mcp-manager?lang=zh" alt="dsh-plugin-mcp-manager card"></a>
3
+ </p>
4
+
5
+ # dsh-mcp-manager
6
+
7
+ > DSH MCP 服务器管理插件 — GUI 增删改 MCP 服务器配置 + 工具浏览 + agent 面 `mcp_*` 管理工具。
8
+
9
+ ## 定位
10
+
11
+ **服务器连接管理 + 工具浏览**。连接生命周期完全委托官方 `@deepseek-ai/dsh-mcp-client`——
12
+ 本插件是注册表的「写配置层」+「状态/工具浏览层」,不自己拉连接。
13
+
14
+ ```
15
+ GUI(settings.section「MCP」) ──HTTP──> /api/mcp-manager ──读写──> profile cordis.patch.yml
16
+ Agent 面 mcp_* 工具 ─────────────────────────────┘ (mcp-client insert 行)
17
+ │ 配置 HMR 实时挂载
18
+
19
+ 官方 mcp-client 实例(连接+注册工具)
20
+ GUI 状态/工具浏览 <──ctx.tools.schemas() 过滤 mcp__──┘
21
+ ```
22
+
23
+ 每台 MCP 服务器 = profile `cordis.patch.yml` 中一条 `name: '@deepseek-ai/dsh-mcp-client'` 的
24
+ insert 行。配置 HMR 实时挂载/卸载/热替换,无需重启 web。
25
+
26
+ **禁用 ≠ 删除**:禁用写入 entry-level `disabled: true`(与 `id`/`name`/`config` 同级),
27
+ loader 跳过挂载该 mcp-client 实例 → 工具不注册(模型不可见),config 原样保留在 patch
28
+ 文件中。重新启用只需移除该字段,loader HMR 重新挂载。适合「暂时不让模型用某台服务器」
29
+ 而不丢失配置。
30
+
31
+ ## 开发
32
+
33
+ ### 依赖
34
+
35
+ ```powershell
36
+ pnpm install
37
+ ```
38
+
39
+ `@deepseek-ai/*` peer deps 从公共 npm registry 解析(已发布)。`yaml`(eemeli)是唯一运行时依赖。
40
+
41
+ ### 三件套
42
+
43
+ ```powershell
44
+ pnpm typecheck # tsc --noEmit(src/ + tests/;src/client/ 由 tsdown 构建,不进 tsc)
45
+ pnpm test # vitest run(registry 单元测试,27 用例)
46
+ pnpm build # tsdown 双 bundle:lib/index.mjs(Node half)+ lib/index.js(client half)
47
+ ```
48
+
49
+ ### 架构
50
+
51
+ | 文件 | 职责 |
52
+ |------|------|
53
+ | `src/registry.ts` | 服务器注册表:eemeli `yaml` Document API 读写 insert 行 + `loadOverlayPatches` 校验 + serverName 唯一 + entry-level `disabled` 字段 |
54
+ | `src/tools.ts` | agent 面 `mcp_*` ×5 工具(defineTool,规范 JSON 输出) |
55
+ | `src/index.ts` | Node half:`/api/mcp-manager` 路由 + `ctx.tools.schemas()` 过滤 + mcp 工具注册 |
56
+ | `src/client/index.ts` | client half:`settings.section` 注册「MCP」面板 |
57
+ | `src/client/Panel.tsx` | 面板 UI:服务器列表 + 增删改表单(内联卡片下方)+ 禁用/启用 + 工具浏览 |
58
+
59
+ ### 数据模型
60
+
61
+ 存储 = profile `cordis.patch.yml` 的 mcp-client insert 行(单一事实来源):
62
+
63
+ ```yaml
64
+ - insert:
65
+ - id: mcp-github # 行 id(mcp-<serverName>)
66
+ name: '@deepseek-ai/dsh-mcp-client'
67
+ disabled: true # 可选 entry-level 字段:loader 跳过挂载,工具不注册,config 保留
68
+ config:
69
+ serverName: github # 工具命名空间 mcp__github__*
70
+ transport: stdio # stdio | streamable-http
71
+ command: npx
72
+ args: ['-y', '@modelcontextprotocol/server-github']
73
+ env: { GITHUB_TOKEN: '' } # 明文(见下「Secret 处理」)
74
+ toolCallTimeoutMs: 60000
75
+ failOnStartupError: false
76
+ ```
77
+
78
+ - 支持 `stdio`(command/args/env/cwd)与 `streamable-http`(url/headers)。
79
+ - 编辑 = 整块替换 config(不深合并,与 loader patch 语义一致)。
80
+ - **禁用** = 设置 entry-level `disabled: true`(与 id/name/config 同级,不在 config 内)。
81
+ loader 跳过挂载 → 工具不注册 → 模型不可见;启用 = 移除该字段。
82
+ - 写前用 eemeli yaml 解析 + 可选 `loadOverlayPatches`(app-boot)校验;写后失败自动回滚。
83
+ - **保留**其他行的 `!!js` 表达式与注释(eemeli Document API 往返保留)。
84
+
85
+ ## 运行
86
+
87
+ ### 安装
88
+
89
+ ```powershell
90
+ # 本地开发(link: 热更新——改源码后 pnpm build 即可见)
91
+ dsh plugin --profile web add "link:<本仓库路径>"
92
+
93
+ # 远端(预构建 lib/ 入库,无 prepare,开箱即用)
94
+ dsh plugin --profile web add "github:dsh-external/dsh-mcp-manager"
95
+ ```
96
+
97
+ 安装后**重启 dsh web**(bundle 层在 boot 时加载),浏览器硬刷新(`Ctrl+Shift+R`)。
98
+
99
+ ### 使用
100
+
101
+ - **GUI**:设置页 → 「MCP」面板。
102
+ - 新增/编辑/删除服务器;编辑表单内联在对应卡片下方(不在全局底部)。
103
+ - 禁用/启用服务器(不删除配置;禁用后 loader 跳过挂载,工具不注册,模型不可见)。
104
+ - 点击「工具」展开该服务器的 `mcp__*` 工具列表(禁用状态下不可展开)。
105
+ - **Agent**:模型可调用 `mcp_server_list` / `mcp_server_add` / `mcp_server_update` /
106
+ `mcp_server_remove` / `mcp_server_set_enabled`。
107
+
108
+ ### API 路由
109
+
110
+ | 路由 | 方法 | 说明 |
111
+ |------|------|------|
112
+ | `/api/mcp-manager/servers` | GET | 列出服务器 + 工具数 + 状态 + disabled |
113
+ | `/api/mcp-manager/servers` | POST | 新增(body: `{config}`)→ HMR 挂载 |
114
+ | `/api/mcp-manager/servers/<id>` | PUT | 编辑(整块替换 config) |
115
+ | `/api/mcp-manager/servers/<id>` | PATCH | 禁用/启用(body: `{disabled: boolean}`;config 保留) |
116
+ | `/api/mcp-manager/servers/<id>` | DELETE | 删除 |
117
+ | `/api/mcp-manager/tools` | GET | 工具浏览(`mcp__` 前缀按 serverName 分组) |
118
+ | `/api/mcp-manager/status` | GET | 运行态状态(含 disabled) |
119
+
120
+ ### Secret 处理
121
+
122
+ ⚠ **P0:env / headers 以明文存入 profile `cordis.patch.yml`**(与官方示例同形态)。
123
+ README 明确警示:勿放长期密钥;部署隔离。P1 可接 `@deepseek-ai/dsh-credentials`(待设计)。
124
+
125
+ ## 检查(合规自检,对照 plugin-development-guide.md §10)
126
+
127
+ - [x] **零源码 patch**:未修改 DSH checkout 任何文件
128
+ - [x] **B1**:`package.json` 声明 `dsh.bundle.patch`
129
+ - [x] **B2**:自带 `cordis.patch.yml`(insert 行 id/name 齐全)
130
+ - [x] **B3**:patch 行 `name` 用包名 `@huanlin/dsh-plugin-mcp-manager`
131
+ - [x] **F1**:`files` 含 `lib/` + `cordis.patch.yml`
132
+ - [x] **F2**:`peerDependencies` 含 `@deepseek-ai/cordis` + `@deepseek-ai/*`(dsh-tools / dsh-llm / dsh-app-boot / dsh-client-ui-primitives / dsh-client-ui-slots / dsh-client-ui-renderer / dsh-client-locale / dsh-client-ui-settings,对齐 v0.1.2-alpha.1 的 client-runtime 拆分)
133
+ - [x] **F3**:typecheck / test / build 三 script 齐全(预构建策略:无 prepare,lib/ 入库)
134
+ - [x] **A4**:Config 校验用 `validateServerConfig`(fail loud,携带字段名)
135
+ - [x] **A6**:不导出 default
136
+ - [x] **C4**:工具返回规范 JSON 值 + render 投影分离
137
+ - [x] **G**:测试分层(Unit:35 用例覆盖增删改/禁用/唯一/非法拒绝/!!js 保留/空文件/多行)
138
+ - [x] **README**:含开发/运行/检查三节
139
+
140
+ ### 预构建策略说明
141
+
142
+ 含 `@deepseek-ai/*` private peer deps → 采用**预构建 `lib/` 入库**策略:
143
+ `lib/` 不进 `.gitignore`,无 `prepare` 脚本。`github:` 安装开箱即用(pnpm 在 git install 的
144
+ prepare 阶段拉不到 private 包,故不能用 prepare 策略)。
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@huanlin/dsh-plugin-mcp-manager",
3
3
  "description": "MCP 服务器管理面板:GUI 增删改 MCP 服务器配置(写入 profile cordis.patch.yml 的 mcp-client insert 行,配置 HMR 实时挂载)+ 工具浏览 + agent 面 mcp_* 管理工具。连接生命周期委托官方 @deepseek-ai/dsh-mcp-client。",
4
- "version": "0.2.0",
4
+ "version": "0.3.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -39,14 +39,14 @@
39
39
  "peerDependencies": {
40
40
  "@deepseek-ai/cordis": "^4.0.1",
41
41
  "react": "^18.2.0",
42
- "@deepseek-ai/dsh-tools": "^0.1.2-rc.1",
43
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
44
- "@deepseek-ai/dsh-app-boot": "^0.1.2-rc.1",
45
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.2-rc.1",
46
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
47
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1",
48
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
49
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.2-rc.1"
42
+ "@deepseek-ai/dsh-tools": "^0.1.5-rc.1",
43
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
44
+ "@deepseek-ai/dsh-app-boot": "^0.1.5-rc.1",
45
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.1",
46
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
47
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1",
48
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-rc.1",
49
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.1"
50
50
  },
51
51
  "peerDependenciesMeta": {
52
52
  "@deepseek-ai/dsh-app-boot": {
@@ -66,6 +66,10 @@
66
66
  }
67
67
  },
68
68
  "devDependencies": {
69
+ "@deepseek-ai/dsh-app-boot": "link:D:/Projects/deepseek-harness/dsh/packages/boot/app-boot",
70
+ "@deepseek-ai/dsh-client-ui-primitives": "link:D:/Projects/deepseek-harness/dsh/packages/client/ui-primitives",
71
+ "@deepseek-ai/dsh-mcp-client": "link:D:/Projects/deepseek-harness/dsh/packages/mcp/mcp-client",
72
+ "@deepseek-ai/dsh-tools": "link:D:/Projects/deepseek-harness/dsh/packages/core/tools",
69
73
  "@types/react": "~18.3.1",
70
74
  "@types/node": "^22.0.0",
71
75
  "react": "^18.2.0",