dsh-mcp 1.3.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 CHANGED
@@ -7,6 +7,37 @@ 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
+
24
+ ## [1.4.0] - 2026-08-16
25
+
26
+ ### Added
27
+
28
+ - **Process-level environment variables**: a new "Process env vars" section on Settings → MCP holds a global key-value list shared by every server (expanded by default, with batch-add and a load-failure retry); secret values are stored in the credentials document, a blank value keeps the stored one
29
+ - **Header env substitution**: `streamable-http` header values support `${ENV}` placeholders and bare variable names, resolved at connect time from the server's configured env (including secrets from the credentials document), the process-level env table, or the process environment (e.g. `Authorization: Bearer ${TOKEN}`); unmatched placeholders stay literal so a missing variable never silently empties a header
30
+ - **JSON editor for the whole MCP server list**: a new "JSON config editor" panel on Settings → MCP views and edits every server definition as one JSON array (serverName / transport / enabled / url / command / args / cwd / headers / timeout / failOnStartupError / env); applying replaces the whole list — listed servers are created or updated, existing servers absent from the document are removed (new host `upsertJson` batch method; Apply saves directly), and the server list and tool list refresh automatically afterwards
31
+ - **Page layout**: injection mode on top → env-vars module (expanded by default) → MCP config module; the add/edit server form renders inline above the list or below the edited row (the list stays visible); opening the JSON config panel hides the UI list and applying it restores the list
32
+ - **The server form no longer edits env vars** (managed by the process-level module): saving submits no env and leaves existing server env untouched (the JSON config editor can still replace env wholesale, including stdio child injection)
33
+ - The server list (`list`) now returns non-secret env values with each server so they round-trip through the JSON editor; secret values still live only in the credentials document (exported as a `configured` flag; a blank value keeps the stored one)
34
+
35
+ ### Fixed
36
+
37
+ - **OAuth no longer re-authorizes after a token refresh fails** (after a JSON save / restart, OAuth servers failed to connect without opening the browser): the OAuth client (client_id) was never persisted — every process re-registered a fresh client, so token refresh was rejected by the server with `client_id mismatch`, and the SDK-required `invalidateCredentials` was missing so the stale token could not be cleared and the retry kept failing. Fixed by persisting the client info alongside the tokens (credentials document) and implementing `invalidateCredentials`, so an unrecoverable failure now starts a fresh browser authorization flow
38
+ - **Form save/test failed with "env is not iterable" when no env was submitted**: the host now guards every `request.env` iteration with `?? []` (omitted env keeps the stored one)
39
+ - **List state did not refresh after applying JSON**: mounting is asynchronous, so the apply now refreshes immediately and again at 2s/6s, settling "Connecting" into "Connected"
40
+
10
41
  ## [1.3.0] - 2026-08-16
11
42
 
12
43
  ### Added
package/CHANGELOG.md CHANGED
@@ -7,6 +7,37 @@
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
+
24
+ ## [1.4.0] - 2026-08-16
25
+
26
+ ### 新增
27
+
28
+ - **进程级环境变量**:Settings → MCP 页新增「进程环境变量」配置区(全局 KV,跨所有服务器,默认展开,支持批量添加与加载失败重试);secret 值写入凭据文档,留空保留原值
29
+ - **请求头环境变量替换**:`streamable-http` 服务器的请求头 value 支持 `${ENV}` 占位符与裸变量名,连接时按服务器 env(含 secret)、进程级环境变量、系统环境变量依次替换(如 `Authorization: Bearer ${TOKEN}`);未匹配的占位符原样保留,避免误清空
30
+ - **JSON 维护服务器配置列表**:Settings → MCP 页新增「JSON 维护配置」面板,以纯 JSON 数组查看/编辑**全部 MCP 服务器配置**(serverName / transport / enabled / url / command / args / cwd / headers / 超时 / failOnStartupError / env);应用时按列表全量替换——已列出的服务器创建或更新、未列出的删除(host 新增 `upsertJson` 批量方法,点应用直接保存),保存后自动刷新服务器列表与工具列表
31
+ - **页面布局重构**:注入模式置顶 → 环境变量模块(默认展开)→ MCP 配置模块;添加/编辑服务器表单内联展示在列表上方或对应行下方(列表始终可见);JSON 配置面板展开时隐藏 UI 列表,应用后自动恢复
32
+ - **服务器表单不再编辑环境变量**(由进程级环境变量统一管理):表单保存不提交 env,已有服务器 env 保持不变;JSON 配置编辑器仍可全量编辑服务器 env(含 stdio 子进程注入)
33
+ - 服务器列表导出(`list`)中的非 secret 环境变量值随配置返回,可随 JSON 往返编辑;secret 值仍只存凭据文档(导出仅 `configured` 标记,留空保留原值)
34
+
35
+ ### 修复
36
+
37
+ - **OAuth token 刷新失效后不再触发授权**(JSON 保存/重启后 OAuth 服务器连接失败且不弹浏览器):根因是 OAuth client(client_id)未持久化——每次进程重新动态注册新 client,token 刷新被服务器以 `client_id mismatch` 拒绝,且 SDK 要求的 `invalidateCredentials` 未实现导致 token 无法清除、重试仍失败。修复:client 信息随 token 持久化(凭据文档),并实现 `invalidateCredentials`,失效后自动进入新的浏览器授权流程
38
+ - **表单保存/测试在未提交 env 时误报 "env is not iterable"**:host 对 `request.env` 的所有迭代补 `?? []` 兜底(未提交则保留已有 env)
39
+ - **JSON 应用后列表状态未刷新**:挂载为异步,应用后立即刷新并追加 2s/6s 延迟刷新,「连接中」自动变为「已连接」
40
+
10
41
  ## [1.3.0] - 2026-08-16
11
42
 
12
43
  ### 新增
package/README.en.md CHANGED
@@ -15,10 +15,12 @@
15
15
  **Highlights:**
16
16
 
17
17
  - **Visual management**: server list / create / edit / delete / test connection / enable-disable / refresh, all in the UI
18
+ - **Process-level environment variables**: a global key-value list (expanded by default, batch-add supported); header values can reference a variable by bare name or `${NAME}` and are substituted at connect time (e.g. `Authorization: Bearer ${TOKEN}`)
19
+ - **Whole-list JSON config**: the "JSON config editor" panel views/edits every server as one JSON array; applying saves immediately (create/update/delete)
18
20
  - **Fine-grained tool control**: expand each server to see its tools, all checked by default; uncheck to load only what you need
19
21
  - **Two injection modes**: `search` (on-demand, token-saving) and `full` (inject everything)
20
22
  - **Zero npm dependencies**: plugs into DeepSeek Harness internals, install and go
21
- - **OAuth authentication**: for `streamable-http` servers using MCP OAuth (authorization-code + PKCE), the browser opens automatically for authorization on connect; tokens are persisted and refreshed automatically by the SDK (auto-renewed while active within 24h)
23
+ - **OAuth authentication**: for `streamable-http` servers using MCP OAuth (authorization-code + PKCE), the browser opens automatically for authorization on connect; tokens and OAuth client info are persisted and refreshed automatically by the SDK (auto-renewed while active within 24h), with automatic re-authorization after expiry
22
24
  - **Three install paths**: npm / GitHub git source / local link; bilingual UI and docs
23
25
 
24
26
  Migrated and merged from uncommitted MCP work in the `deepseek-harness` repository:
@@ -116,29 +118,92 @@ Append to `$DSH_HOME/profiles/web/cordis.patch.yml` (`$DSH_HOME` defaults to `~/
116
118
  name: dsh-mcp
117
119
  ```
118
120
 
119
- Then **restart `dsh web`** (client roster changes require a restart); afterwards hard-refresh the browser
120
- (`Cmd/Ctrl + Shift + R`) to load the settings page.
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.
121
132
 
122
133
  ### 3. Usage
123
134
 
124
135
  **Open the management page**: after restart, open DSH Web → **Settings → MCP**.
125
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
+
126
171
  **Add a server**:
127
172
 
128
- 1. Click **Add server**.
173
+ 1. Click **Add server** (the form expands inline above the list).
129
174
  2. Fill in: server name (`serverName`, determines the tool prefix `mcp__<serverName>__`), transport
130
175
  (`streamable-http` → URL / `stdio` → command), headers, tool-call timeout, etc.
131
176
  3. Click **Test connection** to verify connectivity and the tool list, then **Save**.
132
177
 
178
+ **Process env vars** (below the injection mode, expanded by default):
179
+
180
+ - Configure global key-value pairs referenced by every server's header substitution;
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`
186
+ - Batch-add (paste one `NAME=value` per line) or add rows one by one
187
+ - A header value can reference a variable by **bare name** or **`${NAME}`** (e.g. `Authorization: Bearer ${GITLAB_TOKEN}`),
188
+ substituted at connect time (priority: server env > process-level env > system environment)
189
+
190
+ **JSON config editor** (top-right of the MCP config module):
191
+
192
+ - View/edit every server definition as one JSON array; applying replaces the whole list
193
+ (create/update/delete) and refreshes the list and tool list automatically;
194
+ the UI list is hidden while the JSON panel is open and restored after applying
195
+ - Server-level env (secret flags and stdio child injection) is still maintained through the JSON editor
196
+
133
197
  **OAuth servers** (`streamable-http` using MCP OAuth, e.g. OAuth-protected gateway services):
134
198
 
135
199
  - Just fill in the URL and test the connection; when the server responds with a 401 + OAuth challenge,
136
200
  the plugin **opens the browser automatically** for authorization.
137
201
  - Log in / approve in the browser and return to DSH; the test result refreshes automatically
138
202
  ("connection succeeded + tool count").
139
- - Tokens are persisted in the credentials document (scoped by `serverName`) and refreshed automatically
140
- by the MCP SDK (auto-renewed while active within 24h); after authorizing once, mounts and later
141
- test connections reuse the same token no repeated authorization.
203
+ - Tokens and the registered OAuth client are persisted in the credentials document (scoped by `serverName`)
204
+ and refreshed automatically by the MCP SDK (auto-renewed while active within 24h); after authorizing once,
205
+ mounts and later test connections reuse the same token, and an expired token triggers a fresh
206
+ browser authorization automatically.
142
207
  - The first authorization needs browser interaction, so the test/connect wait budget is relaxed to
143
208
  5 minutes; non-OAuth servers are unaffected and fail fast.
144
209
 
package/README.md CHANGED
@@ -17,10 +17,12 @@
17
17
  **功能优势:**
18
18
 
19
19
  - **可视化管理**:服务器列表 / 新建 / 编辑 / 删除 / 测试连接 / 启停 / 刷新,全 UI 操作
20
+ - **进程级环境变量**:全局 KV 配置(默认展开、支持批量添加),服务器请求头 value 写 `变量名` 或 `${变量名}` 即可在连接时自动替换为配置值(如 `Authorization: Bearer ${TOKEN}`)
21
+ - **JSON 全量配置**:「JSON 维护配置」面板以一段 JSON 数组查看/编辑全部服务器配置,应用即保存(新增/更新/删除)
20
22
  - **工具级精细控制**:每个服务器展开工具列表,默认全选,可取消勾选只加载需要的部分
21
23
  - **双注入模式**:`search`(按需检索,省 token)与 `full`(全量注入)
22
24
  - **零 npm 依赖**:直接对接 DeepSeek Harness 内部能力,安装即用
23
- - **OAuth 认证支持**:`streamable-http` 服务器若走 MCP OAuth(授权码 + PKCE),连接时自动打开浏览器授权;token 持久化、由 SDK 自动刷新(24 小时内活跃自动续期)
25
+ - **OAuth 认证支持**:`streamable-http` 服务器若走 MCP OAuth(授权码 + PKCE),连接时自动打开浏览器授权;token client 信息持久化、由 SDK 自动刷新(24 小时内活跃自动续期),失效后自动重新授权
24
26
  - **三种安装方式**:npm / GitHub git 源 / 本地 link;中英文界面与文档
25
27
 
26
28
  ## 功能
@@ -103,26 +105,78 @@ dsh plugin --profile web add link:<本仓库绝对路径>
103
105
  name: dsh-mcp
104
106
  ```
105
107
 
106
- 然后**重启 `dsh web`**(client roster 变更需重启);之后浏览器硬刷新(`Cmd/Ctrl + Shift + R`)
107
- 加载设置页。
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`),普通刷新可能仍使用缓存的旧页面。
108
116
 
109
117
  ### 3. 使用
110
118
 
111
119
  **打开管理页**:重启后浏览器打开 DSH Web → **设置(Settings)→ MCP**。
112
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
+
113
152
  **添加服务器**:
114
153
 
115
- 1. 点击「添加服务器」
154
+ 1. 点击「添加服务器」(表单在列表上方就地展开)
116
155
  2. 填写:服务器名称(`serverName`,决定工具前缀 `mcp__<serverName>__`)、传输方式
117
156
  (`streamable-http` 填 URL / `stdio` 填命令)、请求头、工具调用超时等
118
157
  3. 点「测试连接」确认连通性与工具列表,点「保存」
119
158
 
159
+ **进程环境变量**(注入模式下方,默认展开):
160
+
161
+ - 配置全局键值对,供所有服务器的请求头替换引用;secret 值写入凭据文档,留空保留原值
162
+ - **process.env 优先**:若变量在进程环境变量(`process.env`)中已存在同名值,连接/展示时直接采用该值(不改名),
163
+ 存储值仅作为兜底——请先在启动脚本里 `export ADA_TOKEN=...` 再重启 `dsh web`
164
+ - 支持「批量添加」(粘贴多行 `NAME=value`)与「添加变量」逐行添加
165
+ - 服务器请求头 value 可直接写**变量名**或 **`${变量名}`**(如 `Authorization: Bearer ${GITLAB_TOKEN}`),
166
+ 连接时自动替换(优先级:服务器 env > 进程级 env > 系统环境变量)
167
+
168
+ **JSON 维护配置**(MCP 配置模块右上角):
169
+
170
+ - 以一段 JSON 数组查看/编辑**全部服务器配置**;应用后按列表全量替换(新增/更新/删除),
171
+ 自动刷新列表与工具列表;JSON 面板展开时隐藏 UI 列表,应用后恢复
172
+ - 服务器级 env(含 secret 标记与 stdio 子进程注入)仍通过 JSON 配置维护
173
+
120
174
  **OAuth 服务器**(`streamable-http` 走 MCP OAuth,如受 OAuth 保护的网关服务):
121
175
 
122
176
  - 只需正常填写 URL 并测试连接;服务器返回 401 + OAuth 挑战时,插件**自动打开浏览器**完成授权
123
177
  - 在浏览器中登录/同意后返回 DSH,测试结果自动刷新(「连接成功 + 工具数」)
124
- - token 持久化在凭据文档(按 `serverName` 隔离),由 MCP SDK 自动刷新(24 小时内活跃自动续期);
125
- 授权一次后,挂载连接与后续测试连接复用同一份 token,无需重复授权
178
+ - token OAuth client 信息持久化在凭据文档(按 `serverName` 隔离),由 MCP SDK 自动刷新
179
+ (24 小时内活跃自动续期);失效后自动重新授权,授权一次后挂载与测试复用
126
180
  - 首次授权需浏览器交互,测试/连接等待时间放宽至 5 分钟;非 OAuth 服务器不受影响,连接失败即时返回
127
181
 
128
182
  **日常管理**: