dsh-project-mcp-manager 0.1.0 → 0.1.1

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/README.md CHANGED
@@ -1,91 +1,62 @@
1
1
  # dsh-project-mcp-manager
2
2
 
3
- 独立项目级 MCP 自动加载插件:在项目根 `<projectRoot>/.dsh/mcp.yml` 写入 MCP
4
- 服务器配置,在该项目开启 dsh 会话时自动装载(经官方
5
- `@deepseek-ai/dsh-mcp-client`),文件改动热重载到运行中的 dsh 进程,并按
6
- 会话 cwd 控制工具可见性。无 UI,核心功能精简型插件。
7
-
8
- ## 工作原理
9
-
10
- - **项目发现**:在线 agent 会话的 `session.header.cwd` + dsh 进程启动目录 →
11
- 向上找最近的含 `.git` 的祖先目录作为项目根(无 `.git` 时退回目录本身)。
12
- - **装载**:每个 `(项目, serverName)` 在宿主 ctx 上装载一个
13
- `@deepseek-ai/dsh-mcp-client` 实例(`ctx.plugin`),注册进全局工具层。
14
- 同一项目内多会话共享同一连接。
15
- - **热重载**:chokidar 监听各项目根(depth 2,忽略 node_modules/.git/.hg/
16
- .svn),`.dsh/mcp.yml` 的增删改经 150ms 防抖触发全量对账:新增行装载、
17
- 删除行卸载、配置变化重装。
18
- - **生效名**:原始 `serverName` 在整个目录(全局行 + 全部项目行)中唯一时
19
- 保持原名;冲突时双方都改为 `p<sha256(项目根)前6位>_<原名>`(截断 32 字符,
20
- 确定性、与装载顺序无关),避免 `dsh-mcp-client` 按进程根的 serverName
21
- 预留冲突。全局行(profile `cordis.patch.yml` / bundle 层已装载的
22
- mcp-client 行)参与占用判定但不改名。
23
- - **会话可见性**:agent 创建时按其会话 cwd 解析项目,对该 agent 应用
24
- `tools.restrict({ deny })`,deny 掉除本会话项目外的全部项目服务器;会话
25
- 无 cwd 时回退 owner 项目(子代理),再回退 dsh 进程 cwd 所在项目。会话
26
- 销毁时释放。
27
-
28
- ## 配置格式
29
-
30
- `<projectRoot>/.dsh/mcp.yml`,格式与 profile `cordis.patch.yml` 的受管块
31
- 一致(begin/end 标记之间的 YAML insert 列表),每行一个 MCP 服务器:
3
+ English | [中文](docs/README.zh.md)
32
4
 
33
- ```yaml
34
- # >>> dsh-project-mcp-manager:mcp:begin
35
- - insert:
36
- - id: panel-mcp-gitlab
37
- name: '@deepseek-ai/dsh-mcp-client'
38
- config:
39
- serverName: gitlab
40
- transport: stdio
41
- command: npx
42
- args: ['-y', '@modelcontextprotocol/server-gitlab']
43
- cwd: . # 相对项目根解析
44
- toolCallTimeoutMs: 60000
45
- failOnStartupError: false
46
- reconnect:
47
- enabled: true
48
- initialDelayMs: 500
49
- maxDelayMs: 30000
50
- maxAttempts: 10
51
- # <<< dsh-project-mcp-manager:mcp:end
52
- ```
5
+ A project-level MCP auto-loading plugin for DSH: write MCP server configs in
6
+ `<projectRoot>/.dsh/mcp.yml` and they are mounted automatically (via the
7
+ official `@deepseek-ai/dsh-mcp-client`) whenever a dsh session opens in that
8
+ project. Changes to the file hot-reload into the running dsh process, and tool
9
+ visibility is scoped per session cwd. No UI — core functionality only.
53
10
 
54
- `transport` 支持 `stdio`(command/args/env/cwd)与 `streamable-http`
55
- (url/headers)。行加 `disabled: true` 即停用。标记之外的内容逐字节保留。
11
+ ## Installation (mount into a profile)
56
12
 
57
- ## 安装(挂载到 profile)
13
+ The plugin is mounted through a **bundle patch**: once the package is added to
14
+ `dsh.profile.bundles`, dsh synthesizes each bundle's patch (the
15
+ `cordis.patch.yml` pointed to by `dsh.bundle.patch`) into plugin lines at
16
+ startup, in order.
58
17
 
59
- 插件通过 **bundle patch** 挂载:把包加入 `dsh.profile.bundles` 后,dsh 启动时
60
- 按顺序合成每个 bundle 的 patch(`dsh.bundle.patch` 指向的 `cordis.patch.yml`)
61
- 作为插件行。**不要再往 profile 的 `cordis.patch.yml` 手动插入同名行**——两层
62
- 同时存在会启动失败:`duplicate loader entry id: mcp-project`(EntryGroup
63
- 拒绝重复 id)。二选一:留在 bundles,或移出 bundles 改手动插行,不能同时。
18
+ **Prerequisite: install dsh itself** (for users who don't have dsh yet):
64
19
 
65
- **本地开发安装**(未发布 npm 前的推荐方式,junction 实时同步源码):
20
+ ```powershell
21
+ npm install -g @deepseek-ai/dsh # official npm package
22
+ npm install -g deepseek-ai/dsh # or install from the GitHub source
23
+ ```
24
+
25
+ **Option 1: the dsh plugin command (recommended)** — `dsh plugin` forwards
26
+ pnpm inside the profile directory and handles installing/upgrading
27
+ dependencies:
66
28
 
67
29
  ```powershell
68
- cd C:\Users\haima\.dsh\profiles\web
69
- pnpm add link:D:\path\to\dsh-mcp-project # 源码包目录
30
+ # Install the latest version (web profile shown as an example;
31
+ # substitute the name of any other profile, e.g. headless)
32
+ dsh plugin --profile web add dsh-project-mcp-manager@latest
33
+
34
+ # Install a specific version (check available versions with
35
+ # npm view dsh-project-mcp-manager versions)
36
+ dsh plugin --profile web add dsh-project-mcp-manager@0.1.0
70
37
  ```
71
38
 
72
- 然后在 `package.json` 的 `dsh.profile.bundles` 数组末尾追加
73
- `"dsh-project-mcp-manager"`,重启 dsh 生效(HMR 只热装首次 insert 的行,
74
- 换实现需重启宿主进程)。
39
+ **Option 2: install directly with pnpm** (equivalent to option 1):
75
40
 
76
- **发布后安装**:`pnpm add dsh-project-mcp-manager`(或 dsh 的插件子命令,
77
- `dsh plugin --profile web ...`),同样确认包已加入 `dsh.profile.bundles`。
41
+ ```powershell
42
+ # dshHome defaults to %USERPROFILE%\.dsh (uses $DSH_HOME if set)
43
+ cd $env:USERPROFILE\.dsh\profiles\web
44
+ pnpm add dsh-project-mcp-manager@latest
45
+ ```
78
46
 
79
- ## 与 dsh-skill-mcp-panel 的关系
47
+ **Option 3: local development install** (a junction that live-syncs your
48
+ source, so code changes take effect immediately):
80
49
 
81
- - 已装的 v2.0.1 面板:无项目级装载能力,与本插件不冲突;其全局受管块行
82
- 会被本插件读取(loader entries),项目同名行自动改名避开。
83
- - v2.1 面板源码(含 ProjectMcpRegistry):与本插件功能重复,**同一进程内
84
- 两者只能启用一个**(双装载同一 serverName 会触发 mcp-client 的进程根
85
- 预留冲突)。v2.1 写出的项目文件行(`panel-mcp-` 前缀 id)本插件可直接
86
- 读取,过渡平滑。
50
+ ```powershell
51
+ cd $env:USERPROFILE\.dsh\profiles\web
52
+ pnpm add link:<path-to-your-dsh-mcp-project-source> # e.g. D:\dev\dsh-mcp-project
53
+ ```
54
+
55
+ **Upgrading / pinning versions**: re-run the `add` command from option 1 with
56
+ the desired version suffix — `@latest` upgrades to the newest release, `@0.1.0`
57
+ pins to a specific version.
87
58
 
88
- ## 构建与测试
59
+ ## Build & test
89
60
 
90
61
  ```powershell
91
62
  npm install
@@ -94,8 +65,70 @@ node test/test-model.mjs
94
65
  node test/test-registry.mjs
95
66
  ```
96
67
 
97
- ## 安全边界
68
+ ## Configuration format
69
+
70
+ `<projectRoot>/.dsh/mcp.yml` uses the same managed-block format as the profile
71
+ `cordis.patch.yml` (a YAML `insert` list between begin/end markers), with one
72
+ MCP server per line:
73
+
74
+ ```yaml
75
+ # >>> dsh-project-mcp-manager:mcp:begin
76
+ - insert:
77
+ - id: panel-mcp-gitlab
78
+ name: '@deepseek-ai/dsh-mcp-client'
79
+ config:
80
+ serverName: gitlab
81
+ transport: stdio
82
+ command: npx
83
+ args: ['-y', '@modelcontextprotocol/server-gitlab']
84
+ cwd: . # resolved relative to the project root
85
+ toolCallTimeoutMs: 60000
86
+ failOnStartupError: false
87
+ reconnect:
88
+ enabled: true
89
+ initialDelayMs: 500
90
+ maxDelayMs: 30000
91
+ maxAttempts: 10
92
+ # <<< dsh-project-mcp-manager:mcp:end
93
+ ```
98
94
 
99
- `.dsh/mcp.yml` 中的 `stdio` 行会在 dsh 宿主进程内 spawn 其 `command`——
100
- 项目文件是**可执行代码载体**,只应在可信项目中添加。装载失败/配置无效行
101
- 仅告警跳过,不影响其他服务器。
95
+ `transport` supports `stdio` (command/args/env/cwd) and `streamable-http`
96
+ (url/headers). Add `disabled: true` to a line to deactivate it. Content outside
97
+ the markers is preserved byte-for-byte.
98
+
99
+ ## How it works
100
+
101
+ - **Project discovery**: the `session.header.cwd` of an active agent session,
102
+ plus the dsh process start directory → walk up to the nearest ancestor
103
+ containing `.git` as the project root (falls back to the directory itself
104
+ when there is no `.git`).
105
+ - **Mounting**: each `(project, serverName)` pair mounts one
106
+ `@deepseek-ai/dsh-mcp-client` instance (`ctx.plugin`) on the host ctx and
107
+ registers it into the global tool layer. Multiple sessions inside the same
108
+ project share a single connection.
109
+ - **Hot reload**: chokidar watches each project root (depth 2, ignoring
110
+ node_modules/.git/.hg/.svn); changes to `.dsh/mcp.yml` trigger a full
111
+ reconciliation after a 150 ms debounce: added lines are mounted, removed
112
+ lines are unmounted, and config changes are remounted.
113
+ - **Effective names**: when the original `serverName` is unique across the
114
+ whole catalog (global lines + all project lines) it keeps its name; on a
115
+ conflict both sides are renamed to
116
+ `p<first 6 chars of sha256(projectRoot)>_<original name>` (truncated to 32
117
+ characters, deterministic and independent of mount order) to avoid the
118
+ serverName reservation conflicts that `dsh-mcp-client` makes per process
119
+ root. Global lines (profile `cordis.patch.yml` / mcp-client lines already
120
+ mounted at the bundle level) participate in occupancy determination but are
121
+ never renamed.
122
+ - **Session visibility**: when an agent is created, its session cwd resolves
123
+ to a project, and `tools.restrict({ deny })` is applied to that agent to deny
124
+ every project server except those of the session's own project; a session
125
+ without a cwd falls back to the owner project (subagents), then to the
126
+ project containing the dsh process cwd. Released when the session is
127
+ destroyed.
128
+
129
+ ## Security boundary
130
+
131
+ `stdio` lines in `.dsh/mcp.yml` spawn their `command` inside the dsh host
132
+ process — project files are **executable code carriers**, so only add them in
133
+ projects you trust. Lines that fail to mount or are invalid are skipped with a
134
+ warning and do not affect other servers.
@@ -0,0 +1,114 @@
1
+ # dsh-project-mcp-manager
2
+
3
+ [English](../README.md) | 中文
4
+
5
+ 项目级 MCP 自动加载插件:在项目根 `<projectRoot>/.dsh/mcp.yml` 写入 MCP
6
+ 服务器配置,在该项目开启 dsh 会话时自动装载(经官方
7
+ `@deepseek-ai/dsh-mcp-client`),文件改动热重载到运行中的 dsh 进程,并按
8
+ 会话 cwd 控制工具可见性。无 UI,仅具备核心功能。
9
+
10
+ ## 安装(挂载到 profile)
11
+
12
+ 插件通过 **bundle patch** 挂载:把包加入 `dsh.profile.bundles` 后,dsh 启动时
13
+ 按顺序合成每个 bundle 的 patch(`dsh.bundle.patch` 指向的 `cordis.patch.yml`)
14
+ 作为插件行。
15
+
16
+ **前置:安装 dsh 本体**(尚未安装 dsh 的用户):
17
+
18
+ ```powershell
19
+ npm install -g @deepseek-ai/dsh # npm 官方包
20
+ npm install -g deepseek-ai/dsh # 或从 GitHub 源码安装
21
+ ```
22
+
23
+ **方式一:dsh 插件命令(推荐)**——`dsh plugin` 在 profile 目录内转发 pnpm,
24
+ 负责安装/升级依赖:
25
+
26
+ ```powershell
27
+ # 安装最新版(web profile 示例;headless 等其他 profile 替换名字即可)
28
+ dsh plugin --profile web add dsh-project-mcp-manager@latest
29
+
30
+ # 安装指定版本(版本号可先 npm view dsh-project-mcp-manager versions 查看)
31
+ dsh plugin --profile web add dsh-project-mcp-manager@0.1.0
32
+ ```
33
+
34
+ **方式二:直接 pnpm 安装**(与方式一等价):
35
+
36
+ ```powershell
37
+ # dshHome 默认为 %USERPROFILE%\.dsh(设置了 DSH_HOME 则用其值)
38
+ cd $env:USERPROFILE\.dsh\profiles\web
39
+ pnpm add dsh-project-mcp-manager@latest
40
+ ```
41
+
42
+ **方式三:本地开发安装**(junction 实时同步源码,改代码即生效):
43
+
44
+ ```powershell
45
+ cd $env:USERPROFILE\.dsh\profiles\web
46
+ pnpm add link:<你的 dsh-mcp-project 源码目录> # 例如 D:\dev\dsh-mcp-project
47
+ ```
48
+
49
+ **升级/锁定版本**:重跑方式一的 `add` 命令并带上目标版本后缀——`@latest`
50
+ 升级到最新,`@0.1.0` 锁定到指定版本。
51
+
52
+ ## 构建与测试
53
+
54
+ ```powershell
55
+ npm install
56
+ npm run build # tsc → lib/
57
+ node test/test-model.mjs
58
+ node test/test-registry.mjs
59
+ ```
60
+
61
+ ## 配置格式
62
+
63
+ `<projectRoot>/.dsh/mcp.yml`,格式与 profile `cordis.patch.yml` 的受管块
64
+ 一致(begin/end 标记之间的 YAML insert 列表),每行一个 MCP 服务器:
65
+
66
+ ```yaml
67
+ # >>> dsh-project-mcp-manager:mcp:begin
68
+ - insert:
69
+ - id: panel-mcp-gitlab
70
+ name: '@deepseek-ai/dsh-mcp-client'
71
+ config:
72
+ serverName: gitlab
73
+ transport: stdio
74
+ command: npx
75
+ args: ['-y', '@modelcontextprotocol/server-gitlab']
76
+ cwd: . # 相对项目根解析
77
+ toolCallTimeoutMs: 60000
78
+ failOnStartupError: false
79
+ reconnect:
80
+ enabled: true
81
+ initialDelayMs: 500
82
+ maxDelayMs: 30000
83
+ maxAttempts: 10
84
+ # <<< dsh-project-mcp-manager:mcp:end
85
+ ```
86
+
87
+ `transport` 支持 `stdio`(command/args/env/cwd)与 `streamable-http`
88
+ (url/headers)。行加 `disabled: true` 即停用。标记之外的内容逐字节保留。
89
+
90
+ ## 工作原理
91
+
92
+ - **项目发现**:在线 agent 会话的 `session.header.cwd` + dsh 进程启动目录 →
93
+ 向上找最近的含 `.git` 的祖先目录作为项目根(无 `.git` 时退回目录本身)。
94
+ - **装载**:每个 `(项目, serverName)` 在宿主 ctx 上装载一个
95
+ `@deepseek-ai/dsh-mcp-client` 实例(`ctx.plugin`),注册进全局工具层。
96
+ 同一项目内多会话共享同一连接。
97
+ - **热重载**:chokidar 监听各项目根(depth 2,忽略 node_modules/.git/.hg/
98
+ .svn),`.dsh/mcp.yml` 的增删改经 150ms 防抖触发全量对账:新增行装载、
99
+ 删除行卸载、配置变化重装。
100
+ - **生效名**:原始 `serverName` 在整个目录(全局行 + 全部项目行)中唯一时
101
+ 保持原名;冲突时双方都改为 `p<sha256(项目根)前6位>_<原名>`(截断 32 字符,
102
+ 确定性、与装载顺序无关),避免 `dsh-mcp-client` 按进程根的 serverName
103
+ 预留冲突。全局行(profile `cordis.patch.yml` / bundle 层已装载的
104
+ mcp-client 行)参与占用判定但不改名。
105
+ - **会话可见性**:agent 创建时按其会话 cwd 解析项目,对该 agent 应用
106
+ `tools.restrict({ deny })`,deny 掉除本会话项目外的全部项目服务器;会话
107
+ 无 cwd 时回退 owner 项目(子代理),再回退 dsh 进程 cwd 所在项目。会话
108
+ 销毁时释放。
109
+
110
+ ## 安全边界
111
+
112
+ `.dsh/mcp.yml` 中的 `stdio` 行会在 dsh 宿主进程内 spawn 其 `command`——
113
+ 项目文件是**可执行代码载体**,只应在可信项目中添加。装载失败/配置无效行
114
+ 仅告警跳过,不影响其他服务器。
package/lib/registry.js CHANGED
@@ -21,8 +21,8 @@
21
21
  * 会话”场景)。
22
22
  */
23
23
  import chokidar from "chokidar";
24
- import { join, resolve } from "node:path";
25
- import { readFile, writeFile } from "node:fs/promises";
24
+ import { dirname, join, resolve } from "node:path";
25
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
26
26
  import * as mcpClient from "@deepseek-ai/dsh-mcp-client";
27
27
  import { extractManagedRows, readPatchFile } from "./mcp-file.js";
28
28
  import { findProjectRoot } from "./project-root.js";
@@ -296,14 +296,23 @@ export class ProjectMcpRegistry {
296
296
  }
297
297
  }
298
298
  catch (catchError) {
299
- if (this.projects.has(key) || !String(catchError).includes("ENOENT")) {
299
+ const message = catchError instanceof Error ? catchError.message : String(catchError);
300
+ // 「配置文件不存在」(ENOENT) 只有在该项目确实有活着的装载时才算异常——
301
+ // 意味着文件在装载之后被删/移走。零配置项目缺文件是常态:不能用
302
+ // projects.has(key) 当判据,空项目条目也会让它恒真(误报根因)。
303
+ const liveServers = this.projects.get(key)?.servers.size ?? 0;
304
+ if (liveServers > 0 || !message.includes("ENOENT")) {
300
305
  ok = false;
301
- error = catchError instanceof Error ? catchError.message : String(catchError);
306
+ error = message;
302
307
  }
303
308
  rows = [];
304
309
  }
305
310
  desiredByProject.set(key, { projectRoot, rows, ok, error });
306
- await this.writeDiag(projectRoot, { kind: "scan", ok, error, rows: rows.map((row) => row.rawName) });
311
+ // 诊断只记有信息量的扫描:异常,或确实解析出了配置行。干净且无配置的
312
+ // 项目不写任何记录——否则每个被访问过的目录都会凭空多出 .dsh/.mcp-diag.json。
313
+ if (!ok || rows.length > 0) {
314
+ await this.writeDiag(projectRoot, { kind: "scan", ok, error, rows: rows.map((row) => row.rawName) });
315
+ }
307
316
  }
308
317
  const catalogProjects = [...desiredByProject.values()]
309
318
  .filter((entry) => entry.ok)
@@ -318,6 +327,11 @@ export class ProjectMcpRegistry {
318
327
  async reconcileProject(key, entry) {
319
328
  let project = this.projects.get(key);
320
329
  if (project === undefined) {
330
+ // 只为「确实有行要装载」的项目建条目:否则会话/进程访问过的每个目录都会
331
+ // 永久留在 projects 里(knownProjects 会一直把它带上),零配置项目也就
332
+ // 不该算作已知项目。已有条目保留,用于卸载后仍能在快照里看到该文件。
333
+ if (entry.rows.length === 0)
334
+ return;
321
335
  project = { projectRoot: entry.projectRoot, servers: new Map() };
322
336
  this.projects.set(key, project);
323
337
  }
@@ -330,6 +344,7 @@ export class ProjectMcpRegistry {
330
344
  await this.mountServer(project, item);
331
345
  }
332
346
  // ── 装载诊断(写 <projectRoot>/.dsh/.mcp-diag.json,宿主日志不可见时定位失败)──
347
+ // 调用方只在有异常或有配置行时写入:无配置的干净项目不创建该文件。
333
348
  async writeDiag(projectRoot, event) {
334
349
  try {
335
350
  const path = join(projectRoot, ".dsh", ".mcp-diag.json");
@@ -345,6 +360,8 @@ export class ProjectMcpRegistry {
345
360
  lines.push({ ts: new Date().toISOString(), ...event });
346
361
  if (lines.length > 30)
347
362
  lines = lines.slice(-30);
363
+ // .dsh 可能已被用户删掉(而项目仍有活装载):补建目录,避免诊断静默丢失。
364
+ await mkdir(dirname(path), { recursive: true });
348
365
  await writeFile(path, JSON.stringify(lines, null, 2), "utf8");
349
366
  }
350
367
  catch {
package/package.json CHANGED
@@ -1,48 +1,49 @@
1
- {
2
- "name": "dsh-project-mcp-manager",
3
- "version": "0.1.0",
4
- "description": "dsh-project-mcp-manager: per-project MCP server loading for DSH. Reads <projectRoot>/.dsh/mcp.yml, mounts each server as an @deepseek-ai/dsh-mcp-client instance, hot-reloads on file change, and scopes tool visibility per session.",
5
- "type": "module",
6
- "main": "lib/index.js",
7
- "exports": {
8
- ".": "./lib/index.js",
9
- "./package.json": "./package.json"
10
- },
11
- "dsh": {
12
- "bundle": {
13
- "patch": "./cordis.patch.yml"
14
- }
15
- },
16
- "license": "MIT",
17
- "author": "wldxiaobai <944418001@qq.com>",
18
- "keywords": [
19
- "dsh",
20
- "deepseek-harness",
21
- "mcp",
22
- "project",
23
- "plugin",
24
- "cordis"
25
- ],
26
- "dependencies": {
27
- "@deepseek-ai/dsh-mcp-client": "^0.1.1-rc.2",
28
- "chokidar": "^5.0.0",
29
- "yaml": "^2.9.0",
30
- "zod": "^4.4.3"
31
- },
32
- "scripts": {
33
- "build": "tsc -p tsconfig.json",
34
- "prepack": "npm run build",
35
- "test": "node test/test-model.mjs && node test/test-registry.mjs"
36
- },
37
- "files": [
38
- "lib",
39
- "cordis.patch.yml",
40
- "README.md",
41
- "LICENSE"
42
- ],
43
- "devDependencies": {
44
- "@deepseek-ai/cordis": "^4.0.1",
45
- "@types/node": "^26.2.0",
46
- "typescript": "^7.0.2"
47
- }
48
- }
1
+ {
2
+ "name": "dsh-project-mcp-manager",
3
+ "version": "0.1.1",
4
+ "description": "dsh-project-mcp-manager: per-project MCP server loading for DSH. Reads <projectRoot>/.dsh/mcp.yml, mounts each server as an @deepseek-ai/dsh-mcp-client instance, hot-reloads on file change, and scopes tool visibility per session.",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "exports": {
8
+ ".": "./lib/index.js",
9
+ "./package.json": "./package.json"
10
+ },
11
+ "dsh": {
12
+ "bundle": {
13
+ "patch": "./cordis.patch.yml"
14
+ }
15
+ },
16
+ "license": "MIT",
17
+ "author": "wldxiaobai <944418001@qq.com>",
18
+ "keywords": [
19
+ "dsh",
20
+ "deepseek-harness",
21
+ "mcp",
22
+ "project",
23
+ "plugin",
24
+ "cordis"
25
+ ],
26
+ "dependencies": {
27
+ "@deepseek-ai/dsh-mcp-client": "^0.1.1-rc.2",
28
+ "chokidar": "^5.0.0",
29
+ "yaml": "^2.9.0",
30
+ "zod": "^4.4.3"
31
+ },
32
+ "scripts": {
33
+ "build": "tsc -p tsconfig.json",
34
+ "prepack": "npm run build",
35
+ "test": "node test/test-model.mjs && node test/test-registry.mjs"
36
+ },
37
+ "files": [
38
+ "lib",
39
+ "cordis.patch.yml",
40
+ "README.md",
41
+ "docs",
42
+ "LICENSE"
43
+ ],
44
+ "devDependencies": {
45
+ "@deepseek-ai/cordis": "^4.0.1",
46
+ "@types/node": "^26.2.0",
47
+ "typescript": "^7.0.2"
48
+ }
49
+ }