dsh-mcp 1.4.0 → 1.5.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/CHANGELOG.en.md +14 -0
- package/CHANGELOG.md +14 -0
- package/README.en.md +49 -2
- package/README.md +41 -2
- package/lib/client.js +98 -89
- package/lib/index.js +35 -16
- package/lib/oauth.js +125 -46
- package/package.json +1 -1
- package/src/client/GlobalEnvEditor.module.css +10 -0
- package/src/client/GlobalEnvEditor.tsx +15 -6
- package/src/client/locales.ts +1 -1
- package/static/snapshot.en.jpg +0 -0
- package/static/snapshot.en.webp +0 -0
- package/static/snapshot.jpg +0 -0
- package/static/snapshot.webp +0 -0
package/CHANGELOG.en.md
CHANGED
|
@@ -7,6 +7,20 @@ All notable changes to this project are documented in this file.
|
|
|
7
7
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
8
8
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
9
9
|
|
|
10
|
+
## [1.5.0] - 2026-08-17
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Process env vars now prefer process.env by name**: when a variable exists in process.env its value is used verbatim (name unchanged) and stored values act as fallback; the UI is unchanged (value input and secret retained), and non-secret variables display the process.env value
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- **OAuth authorization page rejected with `redirect_uri_mismatch`**: the loopback port used to be random per process while the persisted OAuth client's `redirect_uris` are fixed at registration — after a restart the new callback address no longer matched, so the CAS server refused authorization. Fixed by deriving a stable port from the server name and validating in `clientInformation()` that the persisted client's `redirect_uris` cover the current callback, dropping it (and re-registering) otherwise
|
|
19
|
+
- **OAuth silently failed to connect with an expired token** (no browser authorization): when the access token expired and the refresh token was also dead, the SDK threw `InvalidTokenError` without retrying, so the connection just failed. The provider's `tokens()` now reads the JWT `exp` claim and clears expired credentials, letting the SDK fall through to a fresh browser authorization flow
|
|
20
|
+
- **OAuth token exchange failed with `code, code_verifier, client_id, redirect_uri are required`**: when the client was loaded from persistence the in-memory closure was null, so the token request lacked `client_id`. The exchange now reads client info and code verifier through the provider accessors (memory first, persistence fallback)
|
|
21
|
+
- **OAuth concurrent authorization port collision**: with a stable callback port, a mount and a test connection authorizing at the same time collided on the port (EADDRINUSE). Authorization flows are now serialized per server
|
|
22
|
+
- **Env-variable secret values were not persisted**: the editor dropped the value for secret rows. Filled values are now submitted (secret values go to the credentials document); a blank value keeps the stored one
|
|
23
|
+
|
|
10
24
|
## [1.4.0] - 2026-08-16
|
|
11
25
|
|
|
12
26
|
### Added
|
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,20 @@
|
|
|
7
7
|
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
8
8
|
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
|
9
9
|
|
|
10
|
+
## [1.5.0] - 2026-08-17
|
|
11
|
+
|
|
12
|
+
### 新增
|
|
13
|
+
|
|
14
|
+
- **进程环境变量展示/取值 process.env 优先**:变量存在 process.env 时按同名取真实值(不改名),存储值作为兜底;界面功能不变(值输入、secret 保留),非 secret 变量展示 process.env 的值
|
|
15
|
+
|
|
16
|
+
### 修复
|
|
17
|
+
|
|
18
|
+
- **OAuth 授权页报 `redirect_uri_mismatch`**:回调端口原先每次进程随机生成,而持久化的 OAuth client 的 `redirect_uris` 在注册时固定——重启后新回调地址与注册地址不一致,CAS 拒绝授权。修复:回调端口按 serverName 稳定派生;`clientInformation()` 校验持久化 client 的 `redirect_uris` 是否覆盖当前回调地址,不匹配则丢弃并重新注册
|
|
19
|
+
- **OAuth 过期 token 导致静默连接失败**(不弹浏览器):access_token 过期且 refresh_token 也失效时,SDK 抛 `InvalidTokenError` 且不做失效重试,直接连接失败。修复:provider 的 `tokens()` 解析 access_token 的 JWT `exp`,过期即清除凭据,SDK 自动转入新的浏览器授权流程
|
|
20
|
+
- **OAuth token 交换报 `code, code_verifier, client_id, redirect_uri are required`**:client 从持久化读取时内存闭包为 null,token 请求缺 `client_id`。修复:exchange 改用 provider 访问器(内存优先、持久化回退)
|
|
21
|
+
- **OAuth 并发授权端口冲突**:回调端口稳定后,挂载与测试连接同时授权会抢同一端口(EADDRINUSE)。修复:同服务器授权流程串行化
|
|
22
|
+
- **环境变量 secret 值未写入凭据**:编辑器保存 secret 行时丢弃了值。修复:填写值即提交(secret 写入凭据文档),留空保留原值
|
|
23
|
+
|
|
10
24
|
## [1.4.0] - 2026-08-16
|
|
11
25
|
|
|
12
26
|
### 新增
|
package/README.en.md
CHANGED
|
@@ -118,13 +118,56 @@ Append to `$DSH_HOME/profiles/web/cordis.patch.yml` (`$DSH_HOME` defaults to `~/
|
|
|
118
118
|
name: dsh-mcp
|
|
119
119
|
```
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
> ⚠️ **This step is mandatory**: dsh-mcp does not declare `dsh.bundle`, so `dsh plugin add` only
|
|
122
|
+
> installs the package into the profile — **it does not activate the plugin**. Without the
|
|
123
|
+
> registration row the plugin never mounts.
|
|
124
|
+
|
|
125
|
+
Then **restart `dsh web`** and **hard-refresh the browser** (`Cmd/Ctrl + Shift + R`):
|
|
126
|
+
|
|
127
|
+
> ⚠️ **Both the restart and the hard refresh are required**:
|
|
128
|
+
> - The settings page (client half) needs the **client roster**, and roster changes only take
|
|
129
|
+
> effect after **restarting `dsh web`** (refreshing the browser alone is not enough);
|
|
130
|
+
> - After the restart you must **hard-refresh** (`Cmd/Ctrl + Shift + R`) — a normal reload may
|
|
131
|
+
> keep serving the cached old page.
|
|
123
132
|
|
|
124
133
|
### 3. Usage
|
|
125
134
|
|
|
126
135
|
**Open the management page**: after restart, open DSH Web → **Settings → MCP**.
|
|
127
136
|
|
|
137
|
+
### 4. Troubleshooting
|
|
138
|
+
|
|
139
|
+
**Q1: No "MCP" entry in Settings after installing?**
|
|
140
|
+
|
|
141
|
+
Check in order:
|
|
142
|
+
|
|
143
|
+
1. **Is the plugin registered?** Confirm `$DSH_HOME/profiles/web/cordis.patch.yml` has the
|
|
144
|
+
`- insert: [{ id: dsh-mcp, name: dsh-mcp }]` row (`id`/`name` must exactly match the package
|
|
145
|
+
name `dsh-mcp`). `dsh plugin add` does not equal activation — **without the registration row
|
|
146
|
+
the plugin never mounts**.
|
|
147
|
+
2. **Did you restart `dsh web`?** Refreshing the browser is not enough — the settings entry comes
|
|
148
|
+
from the client roster, and roster changes require **restarting the process**.
|
|
149
|
+
3. **Did you hard-refresh the browser?** After the restart use `Cmd/Ctrl + Shift + R`
|
|
150
|
+
(Windows/Linux: `Ctrl + Shift + R`); a plain `F5` may load a cached old page.
|
|
151
|
+
4. **Is it installed in the right profile?** Make sure both the install and the registration use
|
|
152
|
+
the `web` profile (`dsh plugin --profile web add dsh-mcp` +
|
|
153
|
+
`$DSH_HOME/profiles/web/cordis.patch.yml`); other profiles have their own settings pages.
|
|
154
|
+
5. **Is it the latest version?** npm metadata caching can pin an old version; force the version
|
|
155
|
+
with `dsh plugin --profile web add dsh-mcp@latest` (or `@1.4.0`).
|
|
156
|
+
|
|
157
|
+
**Q2: "MCP" is visible but the server list is empty or errors?**
|
|
158
|
+
|
|
159
|
+
- Check the `dsh web` process log for `mcp-manager` initialization errors;
|
|
160
|
+
- After upgrading the plugin, restart and **hard-refresh** so the old client bundle does not
|
|
161
|
+
mix with the new host (typical symptom: `client api: ... 404` or `env is not iterable` — both
|
|
162
|
+
come from mixing versions).
|
|
163
|
+
|
|
164
|
+
**Q3: MCP tools do not show up in an agent session?**
|
|
165
|
+
|
|
166
|
+
- Make sure the server status is "Connected" and its tools are checked (all checked by default);
|
|
167
|
+
- In "On-demand search" mode the model discovers tools via `mcp_tool_search` and hot-injects them,
|
|
168
|
+
so tools not searched are absent from the system prompt by design; switch to "Full injection"
|
|
169
|
+
to verify.
|
|
170
|
+
|
|
128
171
|
**Add a server**:
|
|
129
172
|
|
|
130
173
|
1. Click **Add server** (the form expands inline above the list).
|
|
@@ -136,6 +179,10 @@ Then **restart `dsh web`** (client roster changes require a restart); afterwards
|
|
|
136
179
|
|
|
137
180
|
- Configure global key-value pairs referenced by every server's header substitution;
|
|
138
181
|
secret values are stored in the credentials document, a blank value keeps the stored one
|
|
182
|
+
- **process.env wins**: if a variable already exists in the process environment (`process.env`)
|
|
183
|
+
under the same name, that value is used verbatim (name unchanged) at connect/display time and
|
|
184
|
+
stored values only act as fallback — export it in your startup script first
|
|
185
|
+
(e.g. `export ADA_TOKEN=...`) then restart `dsh web`
|
|
139
186
|
- Batch-add (paste one `NAME=value` per line) or add rows one by one
|
|
140
187
|
- A header value can reference a variable by **bare name** or **`${NAME}`** (e.g. `Authorization: Bearer ${GITLAB_TOKEN}`),
|
|
141
188
|
substituted at connect time (priority: server env > process-level env > system environment)
|
package/README.md
CHANGED
|
@@ -105,13 +105,50 @@ dsh plugin --profile web add link:<本仓库绝对路径>
|
|
|
105
105
|
name: dsh-mcp
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
> ⚠️ **这一步必须手动完成**:dsh-mcp 未声明 `dsh.bundle`,`dsh plugin add` 只负责把包装进
|
|
109
|
+
> profile,**不会自动进入运行组合**。漏掉注册行则插件完全不生效。
|
|
110
|
+
|
|
111
|
+
然后**重启 `dsh web`**,并**硬刷新浏览器**(`Cmd/Ctrl + Shift + R`):
|
|
112
|
+
|
|
113
|
+
> ⚠️ **重启 + 硬刷新缺一不可**:
|
|
114
|
+
> - 设置页(client 半部)需要 **client roster** 生效,**插件集变更必须重启 `dsh web`**(刷新浏览器不够);
|
|
115
|
+
> - 重启后浏览器必须**硬刷新**(`Cmd/Ctrl + Shift + R`),普通刷新可能仍使用缓存的旧页面。
|
|
110
116
|
|
|
111
117
|
### 3. 使用
|
|
112
118
|
|
|
113
119
|
**打开管理页**:重启后浏览器打开 DSH Web → **设置(Settings)→ MCP**。
|
|
114
120
|
|
|
121
|
+
### 4. 常见问题排查
|
|
122
|
+
|
|
123
|
+
**Q1:安装后设置页看不到「MCP」?**
|
|
124
|
+
|
|
125
|
+
按顺序检查:
|
|
126
|
+
|
|
127
|
+
1. **是否已注册插件行**:确认 `$DSH_HOME/profiles/web/cordis.patch.yml` 已追加
|
|
128
|
+
`- insert: [{ id: dsh-mcp, name: dsh-mcp }]`(`id`/`name` 必须与插件包名 `dsh-mcp` 完全一致)。
|
|
129
|
+
`dsh plugin add` 不等于生效,**没有注册行插件不会挂载**。
|
|
130
|
+
2. **是否重启了 `dsh web`**:仅刷新浏览器不够——设置页入口来自 client roster,
|
|
131
|
+
插件集变更必须**重启进程**才进入 roster。
|
|
132
|
+
3. **是否硬刷新了浏览器**:重启后用 `Cmd/Ctrl + Shift + R`(Windows/Linux:`Ctrl + Shift + R`)
|
|
133
|
+
强制刷新;普通 `F5` 可能加载缓存的旧页面。
|
|
134
|
+
4. **是否装到了正确的 profile**:确认安装与注册都在 `web` profile
|
|
135
|
+
(`dsh plugin --profile web add dsh-mcp` + `$DSH_HOME/profiles/web/cordis.patch.yml`);
|
|
136
|
+
装到其他 profile 则在其他 profile 的设置页查看。
|
|
137
|
+
5. **是否为最新版本**:npm 元数据缓存可能导致装到旧版,可强制指定版本
|
|
138
|
+
`dsh plugin --profile web add dsh-mcp@latest`(或 `@1.4.0`)。
|
|
139
|
+
|
|
140
|
+
**Q2:设置页能看到「MCP」,但服务器列表为空/报错?**
|
|
141
|
+
|
|
142
|
+
- 确认 `dsh web` 进程日志中 `mcp-manager` 没有初始化错误;
|
|
143
|
+
- 若升级过插件,请重启后**硬刷新**,避免旧 client bundle 与新版 host 不匹配
|
|
144
|
+
(典型现象:操作报 `client api: ... 404` 或 `env is not iterable`,都是新旧版本混用所致)。
|
|
145
|
+
|
|
146
|
+
**Q3:MCP 工具没有出现在 agent 会话里?**
|
|
147
|
+
|
|
148
|
+
- 确认对应服务器状态为「已连接」且工具已勾选(默认全选);
|
|
149
|
+
- 注入模式为「按需检索」时,模型会通过 `mcp_tool_search` 检索后热注入,未检索到的工具不在
|
|
150
|
+
系统提示词中属正常现象;可切换到「全量注入」验证。
|
|
151
|
+
|
|
115
152
|
**添加服务器**:
|
|
116
153
|
|
|
117
154
|
1. 点击「添加服务器」(表单在列表上方就地展开)
|
|
@@ -122,6 +159,8 @@ dsh plugin --profile web add link:<本仓库绝对路径>
|
|
|
122
159
|
**进程环境变量**(注入模式下方,默认展开):
|
|
123
160
|
|
|
124
161
|
- 配置全局键值对,供所有服务器的请求头替换引用;secret 值写入凭据文档,留空保留原值
|
|
162
|
+
- **process.env 优先**:若变量在进程环境变量(`process.env`)中已存在同名值,连接/展示时直接采用该值(不改名),
|
|
163
|
+
存储值仅作为兜底——请先在启动脚本里 `export ADA_TOKEN=...` 再重启 `dsh web`
|
|
125
164
|
- 支持「批量添加」(粘贴多行 `NAME=value`)与「添加变量」逐行添加
|
|
126
165
|
- 服务器请求头 value 可直接写**变量名**或 **`${变量名}`**(如 `Authorization: Bearer ${GITLAB_TOKEN}`),
|
|
127
166
|
连接时自动替换(优先级:服务器 env > 进程级 env > 系统环境变量)
|