@xxxyz/dsh-mcp-manager 2.0.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.
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@xxxyz/dsh-mcp-manager",
3
+ "version": "2.0.0",
4
+ "description": "DSH-standard MCP manager plugin: Settings UI + HTTP API + model-facing mcp_manager_* tools. Composed as a loader entry, survives restarts. Install via npx, PowerShell, bash or node.",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "exports": {
8
+ ".": "./lib/index.js",
9
+ "./client": "./lib/client.js",
10
+ "./package.json": "./package.json"
11
+ },
12
+ "bin": {
13
+ "dsh-mcp-manager": "install.mjs"
14
+ },
15
+ "files": [
16
+ "lib",
17
+ "install.mjs",
18
+ "uninstall.mjs",
19
+ "install.ps1",
20
+ "install.sh",
21
+ "uninstall.ps1",
22
+ "uninstall.sh",
23
+ "README.md",
24
+ "README.zh-CN.md",
25
+ "安装方式.md",
26
+ "LICENSE"
27
+ ],
28
+ "engines": {
29
+ "node": ">=18"
30
+ },
31
+ "publishConfig": {
32
+ "registry": "https://registry.npmjs.org",
33
+ "access": "public"
34
+ },
35
+ "scripts": {
36
+ "build": "tsc -p tsconfig.json",
37
+ "prepublishOnly": "npm run build"
38
+ },
39
+ "keywords": [
40
+ "dsh",
41
+ "deepseek-harness",
42
+ "mcp",
43
+ "mcp-server",
44
+ "plugin",
45
+ "cordis"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://github.com/xxxyz/DeepSeekHarness-MCP-Manager.git"
50
+ },
51
+ "homepage": "https://github.com/xxxyz/DeepSeekHarness-MCP-Manager",
52
+ "bugs": {
53
+ "url": "https://github.com/xxxyz/DeepSeekHarness-MCP-Manager/issues"
54
+ },
55
+ "dsh": {
56
+ "client": {
57
+ "platform": "web",
58
+ "inject": [
59
+ "@deepseek-ai/dsh-client-connection",
60
+ "@deepseek-ai/dsh-client-locale",
61
+ "@deepseek-ai/dsh-client-runtime",
62
+ "@deepseek-ai/dsh-client-ui-settings",
63
+ "@deepseek-ai/dsh-api-remotes"
64
+ ]
65
+ }
66
+ },
67
+ "peerDependencies": {
68
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
69
+ "react": "^18.2.0"
70
+ },
71
+ "devDependencies": {
72
+ "@deepseek-ai/cordis": "^4.0.1",
73
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.7",
74
+ "@types/node": "^24.0.0",
75
+ "typescript": "^6.0.0"
76
+ },
77
+ "license": "MIT"
78
+ }
package/uninstall.mjs ADDED
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ // dsh-mcp-manager uninstall.mjs — cross-platform uninstaller core
3
+ // (Windows / macOS / Linux, Node.js >= 18, no dependencies).
4
+ //
5
+ // uninstall.ps1 (Windows) and uninstall.sh (macOS / Linux) are thin wrappers.
6
+ //
7
+ // What it removes:
8
+ // 1. <dshHome>/local-packages/dsh-mcp-manager (true source)
9
+ // 2. <dshHome>/profiles/node_modules/dsh-mcp-manager (deployed copy)
10
+ // 3. the loader row (`id: mcp-manager`) from
11
+ // <dshHome>/profiles/<profile>/cordis.patch.yml
12
+ // (other entries are left untouched; the patch stays a valid YAML array)
13
+ //
14
+ // Then restart DSH. Idempotent — safe to run repeatedly.
15
+ import fs from 'node:fs'
16
+ import path from 'node:path'
17
+ import os from 'node:os'
18
+ import { fileURLToPath } from 'node:url'
19
+
20
+ const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url))
21
+ const PKG_NAME = 'dsh-mcp-manager'
22
+ const LOADER_ID = 'mcp-manager'
23
+ const DEFAULT_PROFILE = 'web'
24
+
25
+ const log = (msg) => console.log(msg)
26
+ const warn = (msg) => console.warn('[警告] ' + msg)
27
+ const fail = (msg) => { console.error('[错误] ' + msg); process.exit(1) }
28
+
29
+ function parseArgs(argv) {
30
+ const opts = {
31
+ dshHome: process.env.DSH_HOME || null,
32
+ profile: DEFAULT_PROFILE,
33
+ help: false,
34
+ }
35
+ for (let i = 0; i < argv.length; i++) {
36
+ const a = argv[i]
37
+ const next = () => {
38
+ i++
39
+ if (i >= argv.length) fail('缺少参数值: ' + a + '(用 --help 查看用法)')
40
+ return argv[i]
41
+ }
42
+ switch (a) {
43
+ case '--dsh-home': opts.dshHome = next(); break
44
+ case '--profile': opts.profile = next(); break
45
+ case '-h':
46
+ case '--help': opts.help = true; break
47
+ default: fail('未知参数: ' + a + '(用 --help 查看用法)')
48
+ }
49
+ }
50
+ if (!opts.dshHome) opts.dshHome = path.join(os.homedir(), '.dsh')
51
+ return opts
52
+ }
53
+
54
+ function printUsage() {
55
+ log(`dsh-mcp-manager 卸载脚本(跨平台:Windows / macOS / Linux)
56
+
57
+ 用法:
58
+ node uninstall.mjs [选项]
59
+
60
+ 选项:
61
+ --dsh-home <path> DSH 主目录。默认取 $DSH_HOME 环境变量,否则 ~/.dsh
62
+ --profile <name> 安装时使用的 profile 名(默认 ${DEFAULT_PROFILE})
63
+ -h, --help 显示本帮助
64
+
65
+ 示例:
66
+ node uninstall.mjs
67
+ node uninstall.mjs --dsh-home D:\\path\\.dsh --profile web`)
68
+ }
69
+
70
+ // Remove the loader entry from the patch, then re-normalise so the file stays a
71
+ // valid top-level YAML array (empty/comments-only → `[]`), mirroring the
72
+ // plugin's own joinLines() behaviour. Handles both the current `- insert:`
73
+ // block form and the legacy plain `- id: mcp-manager` row.
74
+ function removeLoader(patchPath) {
75
+ if (!fs.existsSync(patchPath)) return false
76
+ const lines = fs.readFileSync(patchPath, 'utf8').split(/\r?\n/)
77
+ const n = lines.length
78
+ const reChild = () => new RegExp("^(\\s+)- id:\\s*'?" + LOADER_ID + "'?\\s*$")
79
+ const rePlain = () => new RegExp("^- id:\\s*'?" + LOADER_ID + "'?\\s*$")
80
+ const out = []
81
+ let removed = false
82
+ let i = 0
83
+ while (i < n) {
84
+ const line = lines[i]
85
+ if (/^- insert:/.test(line)) {
86
+ let end = i + 1
87
+ while (end < n && !/^- /.test(lines[end])) end++
88
+ const block = lines.slice(i, end)
89
+ if (block.some((l) => reChild().test(l))) {
90
+ removed = true // drop the whole block
91
+ } else {
92
+ out.push(...block)
93
+ }
94
+ i = end
95
+ continue
96
+ }
97
+ if (rePlain().test(line)) {
98
+ removed = true
99
+ i++
100
+ continue
101
+ }
102
+ out.push(line)
103
+ i++
104
+ }
105
+ if (!removed) return false
106
+
107
+ let res = out.join('\n').replace(/\n{3,}/g, '\n\n').replace(/^\n+/, '').replace(/\n*$/, '\n')
108
+ if (!res.trim()) res = '[]\n'
109
+ else if (!/^- /m.test(res) && !/^\[\]\s*$/m.test(res)) res = res.replace(/\n*$/, '\n[]\n')
110
+ fs.writeFileSync(patchPath, res, 'utf8')
111
+ return true
112
+ }
113
+
114
+ function main() {
115
+ const opts = parseArgs(process.argv.slice(2))
116
+ if (opts.help) { printUsage(); return }
117
+
118
+ const dshHome = opts.dshHome
119
+ const localPkg = path.join(dshHome, 'local-packages', PKG_NAME)
120
+ const deployDir = path.join(dshHome, 'profiles', 'node_modules', PKG_NAME)
121
+ const projectPatch = path.join(dshHome, 'profiles', opts.profile, 'cordis.patch.yml')
122
+
123
+ log(`操作系统: ${process.platform === 'win32' ? 'Windows' : process.platform === 'darwin' ? 'macOS' : 'Linux'}`)
124
+ log(`DSH 主目录: ${dshHome}`)
125
+ log(`profile: ${opts.profile}`)
126
+ log('')
127
+
128
+ let anything = false
129
+
130
+ if (fs.existsSync(localPkg)) {
131
+ fs.rmSync(localPkg, { recursive: true, force: true })
132
+ log('已删除 local-packages 真源: ' + localPkg)
133
+ anything = true
134
+ } else {
135
+ log('跳过(不存在): ' + localPkg)
136
+ }
137
+
138
+ if (fs.existsSync(deployDir)) {
139
+ fs.rmSync(deployDir, { recursive: true, force: true })
140
+ log('已删除部署副本: ' + deployDir)
141
+ anything = true
142
+ } else {
143
+ log('跳过(不存在): ' + deployDir)
144
+ }
145
+
146
+ if (removeLoader(projectPatch)) {
147
+ log('已从补丁中移除 loader 行: ' + projectPatch)
148
+ anything = true
149
+ } else {
150
+ log('跳过(无 loader 行): ' + projectPatch)
151
+ }
152
+
153
+ log('')
154
+ if (!anything) {
155
+ warn('未发现 dsh-mcp-manager 的安装痕迹(可能 DSH 主目录不对?用 --dsh-home 指定)')
156
+ return
157
+ }
158
+ log('✔ 卸载完成。请重启 DSH 使设置页与 mcp_manager_* 工具下线。')
159
+ }
160
+
161
+ main()
package/uninstall.ps1 ADDED
@@ -0,0 +1,33 @@
1
+ # dsh-mcp-manager uninstall.ps1 — Windows uninstaller (thin wrapper around uninstall.mjs)
2
+ #
3
+ # .\dsh-mcp-manager\uninstall.ps1 # default: ~/.dsh, web profile
4
+ # .\uninstall.ps1 -DshHome D:\path\.dsh -Profile web
5
+ [CmdletBinding()]
6
+ param(
7
+ [string]$DshHome,
8
+ [string]$Profile = '',
9
+ [switch]$Help
10
+ )
11
+
12
+ $ErrorActionPreference = 'Stop'
13
+
14
+ $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
15
+ $mjs = Join-Path $scriptDir 'uninstall.mjs'
16
+
17
+ $node = Get-Command node -ErrorAction SilentlyContinue
18
+ if (-not $node) {
19
+ Write-Error '未找到 node 命令,请先安装 Node.js 18+(https://nodejs.org)'
20
+ exit 1
21
+ }
22
+
23
+ if ($Help) {
24
+ & $node $mjs '--help'
25
+ exit $LASTEXITCODE
26
+ }
27
+
28
+ $argsList = [System.Collections.Generic.List[string]]::new()
29
+ if ($DshHome) { $argsList.Add('--dsh-home'); $argsList.Add($DshHome) }
30
+ if ($Profile) { $argsList.Add('--profile'); $argsList.Add($Profile) }
31
+
32
+ & $node $mjs @argsList
33
+ exit $LASTEXITCODE
package/uninstall.sh ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env bash
2
+ # dsh-mcp-manager uninstall.sh — macOS / Linux uninstaller (thin wrapper around uninstall.mjs)
3
+ #
4
+ # ./dsh-mcp-manager/uninstall.sh # default: ~/.dsh, web profile
5
+ # ./uninstall.sh --dsh-home /path/.dsh --profile web
6
+ #
7
+ # If "permission denied", run: chmod +x dsh-mcp-manager/uninstall.sh
8
+ set -euo pipefail
9
+
10
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
+ MJS="$SCRIPT_DIR/uninstall.mjs"
12
+
13
+ if ! command -v node >/dev/null 2>&1; then
14
+ echo "未找到 node 命令,请先安装 Node.js 18+(https://nodejs.org)" >&2
15
+ exit 1
16
+ fi
17
+
18
+ declare -a ARGS=()
19
+ while [[ $# -gt 0 ]]; do
20
+ case "$1" in
21
+ --dsh-home) ARGS+=("--dsh-home" "${2:?--dsh-home 需要路径参数}"); shift 2 ;;
22
+ --profile) ARGS+=("--profile" "${2:?--profile 需要名称参数}"); shift 2 ;;
23
+ -h|--help) ARGS+=("--help"); shift ;;
24
+ *) echo "未知参数: $1(用 --help 查看用法)" >&2; exit 2 ;;
25
+ esac
26
+ done
27
+
28
+ exec node "$MJS" "${ARGS[@]}"
@@ -0,0 +1,131 @@
1
+ # dsh-mcp-manager 安装方式
2
+
3
+ ![dsh-mcp-manager 设置页图例](show.png)
4
+
5
+ 一个给 DeepSeek Harness (DSH) 用的**常驻 MCP 服务管理插件**(loader 插件,不是动态会话插件):安装后重启 DSH 依然存在,DSH 升级后可用一条命令修复。
6
+ 功能入口:**设置 → MCP 管理**。
7
+
8
+ - 管理 `@deepseek-ai/dsh-mcp-client` 服务(新增 / 编辑 / 启用 / 禁用 / 重启 / 删除)
9
+ - 支持两个级别:**项目级**(`profiles/<profile>/cordis.patch.yml`)、**全局**(`~/.dsh/cordis.patch.yml`)
10
+ - 修改经 HMR 实时生效;附带工具数健康检查、JSON 导出/导入
11
+ - 按 DSH 官方插件标准实现:对象形态插件(`name` + `inject` + `apply`)、`inject` 声明依赖、
12
+ `ctx.tools.register(defineTool(...))` 注册 4 个模型工具(`mcp_manager_list` / `set_enabled` / `restart` / `add`)
13
+ - 包本身纯 JS、零依赖、跨平台(Windows / macOS / Linux 均支持)
14
+
15
+ ---
16
+
17
+ ## 一、安装(任选一种方式)
18
+
19
+ ### 方式 0:npx 一条命令(最快捷,需要 Node.js >= 18)
20
+
21
+ ```bash
22
+ # 从 npm 安装(推荐)
23
+ npx -y @xxxyz/dsh-mcp-manager
24
+
25
+ # 或直接从 GitHub 安装(无需 npm 账号)
26
+ npx -y github:xxxyz/DeepSeekHarness-MCP-Manager
27
+ ```
28
+
29
+ 所有参数照常透传,例如:`npx -y @xxxyz/dsh-mcp-manager --dsh-home D:\path\.dsh --profile web --repair --port 3080`。
30
+
31
+ > npm 包名是 `@xxxyz/dsh-mcp-manager`(裸名 `dsh-mcp-manager` 在 npm 上已被无关插件占用)。插件部署名仍是 `dsh-mcp-manager`——npx 只是配送渠道,执行的是与下面同样的安装逻辑。
32
+
33
+ ### 方式 1:Windows(PowerShell)
34
+
35
+ ```powershell
36
+ # 默认使用 ~/.dsh 和 web profile
37
+ .\dsh-mcp-manager\install.ps1
38
+
39
+ # 指定 DSH 主目录 / profile
40
+ .\dsh-mcp-manager\install.ps1 -DshHome D:\path\.dsh -Profile web
41
+
42
+ # 修复模式(见第四节)
43
+ .\dsh-mcp-manager\install.ps1 -Repair -Port 3080
44
+ ```
45
+
46
+ ### 方式 2:macOS / Linux(bash)
47
+
48
+ ```bash
49
+ # 默认使用 ~/.dsh 和 web profile
50
+ ./dsh-mcp-manager/install.sh
51
+
52
+ # 指定 DSH 主目录 / profile
53
+ ./dsh-mcp-manager/install.sh --dsh-home /path/.dsh --profile web
54
+
55
+ # 修复模式
56
+ ./dsh-mcp-manager/install.sh --repair --port 3080
57
+ ```
58
+
59
+ > 若 `install.sh` 没有执行权限,先运行:`chmod +x dsh-mcp-manager/install.sh`
60
+
61
+ ### 方式 3:任何平台直接运行(推荐,最通用)
62
+
63
+ ```bash
64
+ node dsh-mcp-manager/install.mjs # 默认 ~/.dsh + web
65
+ node dsh-mcp-manager/install.mjs --dsh-home /path/.dsh --profile web
66
+ node dsh-mcp-manager/install.mjs --repair --port 3080 # 修复模式
67
+ ```
68
+
69
+ ### 参数说明
70
+
71
+ | 参数 | 说明 | 默认值 |
72
+ |---|---|---|
73
+ | `--dsh-home` / `-DshHome` | DSH 主目录(含 `profiles`、`settings.yaml` 的目录) | `$DSH_HOME` 环境变量,否则 `~/.dsh` |
74
+ | `--profile` / `-Profile` | 要安装到的 profile 名 | `web` |
75
+ | `--port` / `-Port` | 修复模式下探测 API 的端口(= DSH Web 端口) | `3080` |
76
+ | `--repair` / `-Repair` | 修复模式:重新部署 + 触发 HMR 重应用 + 轮询 API 直到恢复 | 无 |
77
+ | `--skip-patch` | 只复制包、不修改补丁文件 | 无 |
78
+
79
+ ---
80
+
81
+ ## 二、安装后验证
82
+
83
+ 1. **重启 DSH**(宿主插件与客户端模块在启动时加载;`mcp_manager_*` 4 个工具也在重启后注册)。
84
+ 2. 打开 **设置 → MCP 管理**,应能看到页面并管理现有 MCP 服务(如 stepfun)。
85
+
86
+ > 如果页面在安装前就已打开,先刷新浏览器;仍不出现则重启 DSH。
87
+
88
+ ---
89
+
90
+ ## 三、卸载
91
+
92
+ ```powershell
93
+ # Windows
94
+ .\dsh-mcp-manager\uninstall.ps1 [-DshHome <路径>] [-Profile <名>]
95
+
96
+ # macOS / Linux
97
+ ./dsh-mcp-manager/uninstall.sh [--dsh-home <路径>] [--profile <名>]
98
+
99
+ # 任何平台
100
+ node dsh-mcp-manager/uninstall.mjs [--dsh-home <路径>] [--profile <名>]
101
+ ```
102
+
103
+ 然后重启 DSH。卸载会删除部署目录、`local-packages` 真源目录,并清理补丁里的 loader 行(补丁保持合法)。
104
+
105
+ ---
106
+
107
+ ## 四、DSH 升级后维护(--repair)
108
+
109
+ DSH 升级后若发现 **设置里没有 MCP 管理** 或 **`mcp_manager_*` 工具消失**,运行一次修复命令即可:
110
+ 重新复制包、把 loader 行的 `config.version` 加一(触发 HMR 重新应用)、然后轮询 API 直到
111
+ `POST /dsh-mcp-manager/api` 返回 `{ok:true}`(默认等 30 秒)。
112
+
113
+ ```bash
114
+ node dsh-mcp-manager/install.mjs --repair --port 3080
115
+ ```
116
+
117
+ > 如果 30 秒后 API 仍未恢复,重启一次 DSH —— loader 在启动时会重新导入最新代码。
118
+
119
+ ---
120
+
121
+ ## 五、常见问题
122
+
123
+ - **重启后设置页没有"MCP 管理"**:确认安装脚本输出的路径是实际 DSH 主目录;
124
+ 如果 DSH 用了非默认目录,请用 `--dsh-home` 指定。
125
+ - **安装后立刻报补丁解析错误**:不会发生——脚本保证补丁始终是合法的顶层数组。
126
+ - **给别人分发**:把整个 `dsh-mcp-manager` 文件夹发过去,对方按上面任一方式执行即可。
127
+ - **HTTP 接口无鉴权**:仅限本机使用,不要把 DSH 的 Web 端口暴露到公网。
128
+
129
+ ---
130
+
131
+ *版本:2.0.0 · 常驻 loader 插件(宿主 HTTP API + 4 个模型工具 + 浏览器设置页)*