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 +110 -77
- package/docs/README.zh.md +114 -0
- package/lib/registry.js +22 -5
- package/package.json +49 -48
package/README.md
CHANGED
|
@@ -1,91 +1,62 @@
|
|
|
1
1
|
# dsh-project-mcp-manager
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
55
|
-
(url/headers)。行加 `disabled: true` 即停用。标记之外的内容逐字节保留。
|
|
11
|
+
## Installation (mount into a profile)
|
|
56
12
|
|
|
57
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
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
|
-
|
|
73
|
-
`"dsh-project-mcp-manager"`,重启 dsh 生效(HMR 只热装首次 insert 的行,
|
|
74
|
-
换实现需重启宿主进程)。
|
|
39
|
+
**Option 2: install directly with pnpm** (equivalent to option 1):
|
|
75
40
|
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
47
|
+
**Option 3: local development install** (a junction that live-syncs your
|
|
48
|
+
source, so code changes take effect immediately):
|
|
80
49
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
306
|
+
error = message;
|
|
302
307
|
}
|
|
303
308
|
rows = [];
|
|
304
309
|
}
|
|
305
310
|
desiredByProject.set(key, { projectRoot, rows, ok, error });
|
|
306
|
-
|
|
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.
|
|
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
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"@
|
|
46
|
-
"
|
|
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
|
+
}
|