dsh-mcp-connector 0.2.37 → 0.2.39
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.md +30 -1
- package/README.en.md +7 -3
- package/README.md +7 -3
- package/cordis.patch.yml +1 -0
- package/docs/USER-GUIDE.md +6 -1
- package/lib/client.js +430 -14
- package/lib/index.js +4 -0
- package/lib/settings.js +24 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.2.39] - 2026-09-08
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- 从“设置 → 插件 → 插件配置”快捷打开 MCP连接器时,将连接器弹框 Portal 到页面根层并显示在设置弹框之上;关闭后仍返回原设置位置。
|
|
12
|
+
- MCP连接器位于设置弹框上方时会优先处理 Escape,只关闭最上层连接器弹框,不连带关闭底层设置弹框。
|
|
13
|
+
|
|
14
|
+
### Verification
|
|
15
|
+
|
|
16
|
+
- 206 项自动测试、lint、版本/营销元数据/商店截图门禁和 npm 发布包白名单/敏感内容扫描全部通过;新增覆盖连接器弹框根层 Portal、层级与嵌套弹框 Escape 行为。
|
|
17
|
+
|
|
18
|
+
## [0.2.38] - 2026-09-08
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- 在 `设置 → 插件 → 插件配置` 新增“MCP连接器”卡片,可按当前 DSH profile 显示或隐藏侧边栏入口。
|
|
23
|
+
- 设置卡片新增“打开 MCP连接器”快捷动作;入口隐藏后仍可随时打开、连接和管理 MCP Server,关闭弹框后返回原操作位置。
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- 侧边栏可见性保存后即时生效;仅隐藏入口,不影响插件、连接、工具、后台刷新或对话内调用。
|
|
28
|
+
- Settings Host 与客户端服务均采用可选注入;旧版 DSH 或服务暂不可用时安全回退为显示侧边栏,避免升级后失去入口。
|
|
29
|
+
|
|
30
|
+
### Verification
|
|
31
|
+
|
|
32
|
+
- 205 项自动测试、lint、版本/营销元数据/商店截图门禁和 npm 发布包白名单/敏感内容扫描全部通过;新增覆盖 Host 设置注册、客户端持久化、快捷打开、隐藏态零挂载、键盘焦点恢复和兼容回退。
|
|
33
|
+
|
|
7
34
|
## [0.2.37] - 2026-09-06
|
|
8
35
|
|
|
9
36
|
### Changed
|
|
@@ -580,7 +607,9 @@
|
|
|
580
607
|
- 外部 URL 与导入 Header 执行安全校验。
|
|
581
608
|
- iframe 消息校验同源和消息来源。
|
|
582
609
|
|
|
583
|
-
[Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.
|
|
610
|
+
[Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.39...HEAD
|
|
611
|
+
[0.2.39]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.38...v0.2.39
|
|
612
|
+
[0.2.38]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.37...v0.2.38
|
|
584
613
|
[0.2.37]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.36...v0.2.37
|
|
585
614
|
[0.2.36]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.35...v0.2.36
|
|
586
615
|
[0.2.35]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.34...v0.2.35
|
package/README.en.md
CHANGED
|
@@ -26,7 +26,7 @@ Manage MCP connections from different providers in one place inside DeepSeek Har
|
|
|
26
26
|
dsh plugin --profile web add dsh-mcp-connector
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Fully restart DeepSeek Harness Desktop or `dsh web` after installation or upgrade, then open **MCP Connector** in the primary sidebar
|
|
29
|
+
Fully restart DeepSeek Harness Desktop or `dsh web` after installation or upgrade, then open **MCP Connector** in the primary sidebar, or open it directly from **Settings → Plugins → Plugin Configuration → MCP Connector**.
|
|
30
30
|
|
|
31
31
|

|
|
32
32
|
|
|
@@ -49,6 +49,7 @@ If the plugin helps you connect an MCP server faster, consider [starring the rep
|
|
|
49
49
|
## Features
|
|
50
50
|
|
|
51
51
|
- A primary sidebar entry below New Conversation and above workspaces/conversations, with a public footer-slot fallback for incompatible DSH DOM versions.
|
|
52
|
+
- A profile-wide sidebar visibility preference; even when the shortcut is hidden, the existing connector dialog remains available from **Settings → Plugins → Plugin Configuration → MCP Connector**.
|
|
52
53
|
- Searchable Marketplace and Installed views; the default Marketplace groups cards into Featured plus nine business-category sections, previews four cards per section, keeps the category bar visible while scrolling, and shows every card when a single category is selected.
|
|
53
54
|
- OAuth 2.0 Authorization Code with PKCE, including DCR public clients and `client_secret_post` / `client_secret_basic`; API key/Bearer/unauthenticated HTTP configuration, stdio local-process configuration, and `mcpServers` JSON import.
|
|
54
55
|
- Installation from a credential-free connector descriptor URL.
|
|
@@ -97,7 +98,7 @@ Run the same command again to upgrade. Fully quit and restart DeepSeek Harness D
|
|
|
97
98
|
|
|
98
99
|
## Usage
|
|
99
100
|
|
|
100
|
-
1. Select **MCP Connector** in the primary sidebar
|
|
101
|
+
1. Select **MCP Connector** in the primary sidebar, or choose **Open MCP Connector** from **Settings → Plugins → Plugin Configuration → MCP Connector**.
|
|
101
102
|
2. Choose a connector, confirm **Current project** or **All projects (global)**, and complete authorization or configuration.
|
|
102
103
|
3. Open its details to inspect tools or send an example prompt to a new conversation draft.
|
|
103
104
|
4. Use Installed or the conversation tools to enable, disable, inspect, or disconnect a connection.
|
|
@@ -139,10 +140,13 @@ The default bundle configuration is in `cordis.patch.yml`:
|
|
|
139
140
|
entryPrefix: mcp
|
|
140
141
|
refreshSkewMs: 300000
|
|
141
142
|
openBrowser: true
|
|
143
|
+
showSidebarEntry: true
|
|
142
144
|
```
|
|
143
145
|
|
|
144
146
|
Set `catalogUrl` to an empty string for an explicitly offline/private setup. A custom non-default URL is used as-is and does not fall back to the public registry.
|
|
145
147
|
|
|
148
|
+
`showSidebarEntry` defaults to `true`. Users can override it from the DSH plugin configuration page; turning it off hides only the shortcut and does not disable the connector, connected MCP servers, or tools.
|
|
149
|
+
|
|
146
150
|
## Compatibility and responsibility boundary
|
|
147
151
|
|
|
148
152
|
| Area | Current boundary |
|
|
@@ -171,7 +175,7 @@ npm run dev:ui
|
|
|
171
175
|
|
|
172
176
|
Every Registry merge regenerates `catalog-stats.json`; an hourly workflow in this repository synchronizes the Chinese and English product copy plus a local stats snapshot. The static npm README updates with package releases, while the live badges above read the Registry directly and therefore stay current without another npm release.
|
|
173
177
|
|
|
174
|
-
The current public version is [`dsh-mcp-connector@0.2.
|
|
178
|
+
The current public version is [`dsh-mcp-connector@0.2.39`](https://www.npmjs.com/package/dsh-mcp-connector), with [GitHub Release v0.2.39](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.39).
|
|
175
179
|
|
|
176
180
|
See [CHANGELOG.md](CHANGELOG.md) for version history and [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md) for the Desktop release checklist.
|
|
177
181
|
|
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
dsh plugin --profile web add dsh-mcp-connector
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
安装或升级后完全重启 DeepSeek Harness Desktop 或 `dsh web`,然后打开左侧「🧩 MCP
|
|
29
|
+
安装或升级后完全重启 DeepSeek Harness Desktop 或 `dsh web`,然后打开左侧「🧩 MCP连接器」;也可从“设置 → 插件 → 插件配置 → MCP连接器”直接打开。
|
|
30
30
|
|
|
31
31
|

|
|
32
32
|
|
|
@@ -49,6 +49,7 @@ dsh plugin --profile web add dsh-mcp-connector
|
|
|
49
49
|
## 功能
|
|
50
50
|
|
|
51
51
|
- 左侧主导航入口:目标位置为“新会话”下方、“工作区/会话列表”上方;若 DSH DOM 结构不兼容,自动回退到底部公开插槽。
|
|
52
|
+
- 侧边栏入口可按当前 profile 隐藏;隐藏后仍可从“设置 → 插件 → 插件配置 → MCP连接器”临时打开现有连接器弹框,用完即关。
|
|
52
53
|
- 图形化市场:默认“全部”按推荐与 9 类业务分类分章节展示,每章先展示 4 张并可展开;分类栏固定可见,单分类页展示全部卡片。
|
|
53
54
|
- 图形化添加:手动 HTTP/stdio、`mcpServers` JSON、连接器描述 URL 三种入口,失败时保留表单并给出修复建议。
|
|
54
55
|
- 连接器详情:精选 Prompt 优先展示,点击可带入 DSH 新会话;工具按 Server 分组,支持描述、搜索和独立滚动。
|
|
@@ -99,7 +100,7 @@ bash <(curl -fsSL https://raw.githubusercontent.com/duhu2000/dsh-mcp-connector/m
|
|
|
99
100
|
|
|
100
101
|
## 使用
|
|
101
102
|
|
|
102
|
-
1. 点击左侧“🧩 MCP连接器”。
|
|
103
|
+
1. 点击左侧“🧩 MCP连接器”,或从“设置 → 插件 → 插件配置 → MCP连接器”点击“打开 MCP连接器”。
|
|
103
104
|
2. 在市场中选择连接器,确认“当前项目”或“所有项目(全局)”,再完成授权或配置。
|
|
104
105
|
3. 打开卡片详情,可点击示例 Prompt 的发送按钮,在当前工作区创建/复用空白会话并写入草稿。
|
|
105
106
|
4. 在“已安装”或对话工具中查看、停用、恢复或断开连接。
|
|
@@ -135,10 +136,13 @@ Bundle 默认配置位于 `cordis.patch.yml`:
|
|
|
135
136
|
entryPrefix: mcp
|
|
136
137
|
refreshSkewMs: 300000
|
|
137
138
|
openBrowser: true
|
|
139
|
+
showSidebarEntry: true
|
|
138
140
|
```
|
|
139
141
|
|
|
140
142
|
`catalogUrl` 默认通过 jsDelivr CDN 读取公共 [dsh-mcp-connector-registry](https://github.com/duhu2000/dsh-mcp-connector-registry),支持 ETag/TTL 缓存;主源失败时自动尝试 GitHub raw 备用源,再回退到上次缓存或随包内置目录。jsDelivr 的分支 URL 可能存在缓存延迟,因此 Registry 合并后的新卡片不保证秒级出现。需要离线/私有模式时可将 `catalogUrl` 显式设为空字符串;显式配置其他目录 URL 时不会自动切换到公共备用源。
|
|
141
143
|
|
|
144
|
+
`showSidebarEntry` 默认为 `true`。用户可在 DSH 插件配置页覆盖该值;关闭后只隐藏侧边栏快捷入口,不停用连接器、已连接 MCP Server 或工具。
|
|
145
|
+
|
|
142
146
|
## 兼容性与责任边界
|
|
143
147
|
|
|
144
148
|
| 项目 | 当前边界 |
|
|
@@ -167,7 +171,7 @@ npm run dev:ui
|
|
|
167
171
|
|
|
168
172
|
公共 Registry 每次合并后会生成 `catalog-stats.json`;本仓库的定时工作流每小时同步中英文介绍和统计快照。npm 页面中的静态正文随版本发布更新,上方动态统计徽标则直接读取 Registry,可在不发布新 npm 版本时保持实时数量一致。
|
|
169
173
|
|
|
170
|
-
当前公开版本为 [`dsh-mcp-connector@0.2.
|
|
174
|
+
当前公开版本为 [`dsh-mcp-connector@0.2.39`](https://www.npmjs.com/package/dsh-mcp-connector),对应 [GitHub Release v0.2.39](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.39)。
|
|
171
175
|
|
|
172
176
|
版本能力与变更记录见 [CHANGELOG.md](CHANGELOG.md)。
|
|
173
177
|
Desktop 发版回归见 [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md)。
|
package/cordis.patch.yml
CHANGED
package/docs/USER-GUIDE.md
CHANGED
|
@@ -34,7 +34,12 @@ dsh web
|
|
|
34
34
|
|
|
35
35
|
## 2. 打开 MCP连接器
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
重启后,可以用以下任一方式打开:
|
|
38
|
+
|
|
39
|
+
- 在 DSH 左侧主导航点击“🧩 MCP连接器”。入口通常位于“新会话”下方、工作区/会话列表上方;如果当前 DSH 版本没有对应的公开插槽,入口会回退到左侧底部。
|
|
40
|
+
- 打开“设置 → 插件 → 插件配置 → MCP连接器”,展开卡片并点击“打开 MCP连接器”。该按钮直接复用同一个连接器弹框,不要求侧边栏入口可见;关闭弹框后仍回到设置页。
|
|
41
|
+
|
|
42
|
+
如需腾出侧边栏空间,可在同一配置卡片关闭“在侧边栏显示 MCP连接器”。该偏好作用于当前 DSH profile,并在重启后保留;它只隐藏快捷入口,不停用插件、已连接 MCP Server 或工具。隐藏后可以随时从该配置卡片直接打开连接器,或重新开启入口。旧版 DSH 没有 Settings 能力时,插件保持入口可见,不会因设置功能进入 Safe Mode。
|
|
38
43
|
|
|
39
44
|
页面顶部提供:
|
|
40
45
|
|
package/lib/client.js
CHANGED
|
@@ -23,6 +23,9 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
const VERSION_CHECK_RETRY_MS = 5 * 60 * 1e3;
|
|
24
24
|
const NPM_PACKAGE_URL = "https://www.npmjs.com/package/dsh-mcp-connector";
|
|
25
25
|
const PLUGIN_PACKAGE_NAME = "dsh-mcp-connector";
|
|
26
|
+
const CONNECTOR_SETTINGS_NAMESPACE = "mcp-connector";
|
|
27
|
+
const SHOW_SIDEBAR_ENTRY_FIELD = "showSidebarEntry";
|
|
28
|
+
const CONNECTOR_MODAL_Z_INDEX = 1100;
|
|
26
29
|
const UPDATE_PROVIDER_OPERATION_POLL_MS = 1e3;
|
|
27
30
|
const UPDATE_PROVIDER_ADAPTERS = Object.freeze([
|
|
28
31
|
createHttpUpdateProviderAdapter({
|
|
@@ -110,6 +113,9 @@ window.__ModuleLoader__.load({
|
|
|
110
113
|
.mcpConnectorTopEntry[data-wide="false"] .mcpConnectorLauncher {
|
|
111
114
|
margin: 0 0 8px;
|
|
112
115
|
}
|
|
116
|
+
`;
|
|
117
|
+
const OVERLAY_STYLE_ID = "dsh-mcp-connector-overlay";
|
|
118
|
+
const overlayCss = `
|
|
113
119
|
|
|
114
120
|
.mcpConnectorMarketPanel { background: #ffffff; color: #111827; }
|
|
115
121
|
.mcpConnectorMarketHeader { border-color: #e5e7eb; }
|
|
@@ -218,19 +224,189 @@ window.__ModuleLoader__.load({
|
|
|
218
224
|
.mcpConnectorMarketClose:hover,
|
|
219
225
|
.mcpConnectorMarketClose:focus-visible { background: #30343d !important; color: #ffffff; }
|
|
220
226
|
}
|
|
227
|
+
`;
|
|
228
|
+
const SETTINGS_STYLE_ID = "dsh-mcp-connector-settings";
|
|
229
|
+
const settingsCss = `
|
|
230
|
+
.mcpConnectorSettingsCard {
|
|
231
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.28));
|
|
232
|
+
background: var(--dsw-alias-bg-layer-3, transparent);
|
|
233
|
+
border-radius: 12px;
|
|
234
|
+
list-style: none;
|
|
235
|
+
}
|
|
236
|
+
.mcpConnectorSettingsCard[data-open="true"] {
|
|
237
|
+
background: var(--dsw-alias-bg-layer-2, rgba(127, 127, 127, 0.06));
|
|
238
|
+
border-color: var(--dsw-alias-label-dimmed, rgba(127, 127, 127, 0.5));
|
|
239
|
+
}
|
|
240
|
+
.mcpConnectorSettingsHeader {
|
|
241
|
+
appearance: none;
|
|
242
|
+
display: flex;
|
|
243
|
+
align-items: center;
|
|
244
|
+
gap: 12px;
|
|
245
|
+
width: 100%;
|
|
246
|
+
padding: 14px 16px;
|
|
247
|
+
border: 0;
|
|
248
|
+
border-radius: 12px;
|
|
249
|
+
color: inherit;
|
|
250
|
+
background: transparent;
|
|
251
|
+
font: inherit;
|
|
252
|
+
text-align: left;
|
|
253
|
+
cursor: pointer;
|
|
254
|
+
}
|
|
255
|
+
.mcpConnectorSettingsHeader:focus-visible,
|
|
256
|
+
.mcpConnectorSettingsButton:focus-visible,
|
|
257
|
+
.mcpConnectorSettingsSwitch:focus-visible {
|
|
258
|
+
outline: 2px solid var(--dsw-alias-brand-primary, currentColor);
|
|
259
|
+
outline-offset: 2px;
|
|
260
|
+
}
|
|
261
|
+
.mcpConnectorSettingsHeadText {
|
|
262
|
+
display: flex;
|
|
263
|
+
flex: 1;
|
|
264
|
+
flex-direction: column;
|
|
265
|
+
gap: 4px;
|
|
266
|
+
min-width: 0;
|
|
267
|
+
}
|
|
268
|
+
.mcpConnectorSettingsName {
|
|
269
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
270
|
+
font-size: 15px;
|
|
271
|
+
font-weight: 600;
|
|
272
|
+
line-height: 1.4;
|
|
273
|
+
}
|
|
274
|
+
.mcpConnectorSettingsDescription,
|
|
275
|
+
.mcpConnectorSettingsHint,
|
|
276
|
+
.mcpConnectorSettingsState {
|
|
277
|
+
color: var(--dsw-alias-label-tertiary, rgba(127, 127, 127, 0.9));
|
|
278
|
+
font-size: 13px;
|
|
279
|
+
line-height: 1.5;
|
|
280
|
+
}
|
|
281
|
+
.mcpConnectorSettingsChevron {
|
|
282
|
+
flex: none;
|
|
283
|
+
color: var(--dsw-alias-label-tertiary, currentColor);
|
|
284
|
+
font-size: 16px;
|
|
285
|
+
transition: transform 0.16s;
|
|
286
|
+
}
|
|
287
|
+
.mcpConnectorSettingsCard[data-open="true"] .mcpConnectorSettingsChevron {
|
|
288
|
+
transform: rotate(180deg);
|
|
289
|
+
}
|
|
290
|
+
.mcpConnectorSettingsBody {
|
|
291
|
+
margin: 0 16px;
|
|
292
|
+
padding: 14px 0 10px;
|
|
293
|
+
border-top: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.28));
|
|
294
|
+
}
|
|
295
|
+
.mcpConnectorSettingsRow {
|
|
296
|
+
display: grid;
|
|
297
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
298
|
+
align-items: center;
|
|
299
|
+
gap: 18px;
|
|
300
|
+
}
|
|
301
|
+
.mcpConnectorSettingsLabel {
|
|
302
|
+
display: block;
|
|
303
|
+
color: var(--dsw-alias-label-primary, inherit);
|
|
304
|
+
font-size: 14px;
|
|
305
|
+
font-weight: 600;
|
|
306
|
+
}
|
|
307
|
+
.mcpConnectorSettingsHint {
|
|
308
|
+
display: block;
|
|
309
|
+
margin-top: 5px;
|
|
310
|
+
}
|
|
311
|
+
.mcpConnectorSettingsSwitch {
|
|
312
|
+
position: relative;
|
|
313
|
+
appearance: none;
|
|
314
|
+
width: 42px;
|
|
315
|
+
height: 24px;
|
|
316
|
+
margin: 0;
|
|
317
|
+
border: 0;
|
|
318
|
+
border-radius: 999px;
|
|
319
|
+
background: var(--dsw-alias-fill-secondary, rgba(127, 127, 127, 0.35));
|
|
320
|
+
cursor: pointer;
|
|
321
|
+
transition: background 0.16s;
|
|
322
|
+
}
|
|
323
|
+
.mcpConnectorSettingsSwitch::after {
|
|
324
|
+
position: absolute;
|
|
325
|
+
top: 3px;
|
|
326
|
+
left: 3px;
|
|
327
|
+
width: 18px;
|
|
328
|
+
height: 18px;
|
|
329
|
+
border-radius: 50%;
|
|
330
|
+
background: #ffffff;
|
|
331
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
|
|
332
|
+
content: "";
|
|
333
|
+
transition: transform 0.16s;
|
|
334
|
+
}
|
|
335
|
+
.mcpConnectorSettingsSwitch:checked {
|
|
336
|
+
background: var(--dsw-alias-state-success, #16a34a);
|
|
337
|
+
}
|
|
338
|
+
.mcpConnectorSettingsSwitch:checked::after {
|
|
339
|
+
transform: translateX(18px);
|
|
340
|
+
}
|
|
341
|
+
.mcpConnectorSettingsSwitch:disabled {
|
|
342
|
+
cursor: default;
|
|
343
|
+
opacity: 0.55;
|
|
344
|
+
}
|
|
345
|
+
.mcpConnectorSettingsFooter {
|
|
346
|
+
display: flex;
|
|
347
|
+
align-items: center;
|
|
348
|
+
flex-wrap: wrap;
|
|
349
|
+
gap: 8px;
|
|
350
|
+
margin-top: 14px;
|
|
351
|
+
padding-top: 12px;
|
|
352
|
+
border-top: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.28));
|
|
353
|
+
}
|
|
354
|
+
.mcpConnectorSettingsState {
|
|
355
|
+
flex: 1 1 210px;
|
|
356
|
+
margin: 0;
|
|
357
|
+
}
|
|
358
|
+
.mcpConnectorSettingsState[data-tone="error"] {
|
|
359
|
+
color: var(--dsw-alias-label-error, #b91c1c);
|
|
360
|
+
}
|
|
361
|
+
.mcpConnectorSettingsButton {
|
|
362
|
+
appearance: none;
|
|
363
|
+
padding: 6px 12px;
|
|
364
|
+
border: 1px solid var(--dsw-alias-border-l2, rgba(127, 127, 127, 0.28));
|
|
365
|
+
border-radius: 8px;
|
|
366
|
+
color: var(--dsw-alias-label-secondary, inherit);
|
|
367
|
+
background: transparent;
|
|
368
|
+
font: inherit;
|
|
369
|
+
font-size: 13px;
|
|
370
|
+
cursor: pointer;
|
|
371
|
+
}
|
|
372
|
+
.mcpConnectorSettingsButton[data-primary="true"] {
|
|
373
|
+
border-color: transparent;
|
|
374
|
+
color: var(--dsw-alias-bg-layer-3, #ffffff);
|
|
375
|
+
background: var(--dsw-alias-label-primary, #111827);
|
|
376
|
+
}
|
|
377
|
+
.mcpConnectorSettingsButton:disabled {
|
|
378
|
+
cursor: default;
|
|
379
|
+
opacity: 0.45;
|
|
380
|
+
}
|
|
381
|
+
@media (max-width: 520px) {
|
|
382
|
+
.mcpConnectorSettingsRow { grid-template-columns: 1fr; }
|
|
383
|
+
.mcpConnectorSettingsFooter .mcpConnectorSettingsButton { flex: 1 1 140px; }
|
|
384
|
+
}
|
|
221
385
|
`;
|
|
222
386
|
const SIDEBAR_WORKSPACES_SELECTOR = '[data-slot="sidebar.workspaces"]';
|
|
223
387
|
const TOP_MOUNT_SELECTOR = '[data-mcp-connector-top-mount="true"]';
|
|
224
388
|
|
|
225
|
-
function
|
|
226
|
-
if (document.querySelector(`style[data-plugin="${
|
|
389
|
+
function installStyles(id, css) {
|
|
390
|
+
if (document.querySelector(`style[data-plugin="${id}"]`) !== null) return () => {};
|
|
227
391
|
const style = document.createElement("style");
|
|
228
|
-
style.dataset.plugin =
|
|
229
|
-
style.textContent =
|
|
392
|
+
style.dataset.plugin = id;
|
|
393
|
+
style.textContent = css;
|
|
230
394
|
document.head.append(style);
|
|
231
395
|
return () => { style.remove(); };
|
|
232
396
|
}
|
|
233
397
|
|
|
398
|
+
function installSidebarStyles() {
|
|
399
|
+
return installStyles(SIDEBAR_STYLE_ID, sidebarCss);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
function installOverlayStyles() {
|
|
403
|
+
return installStyles(OVERLAY_STYLE_ID, overlayCss);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function installSettingsStyles() {
|
|
407
|
+
return installStyles(SETTINGS_STYLE_ID, settingsCss);
|
|
408
|
+
}
|
|
409
|
+
|
|
234
410
|
/**
|
|
235
411
|
* DSH rc.7 没有公开的「新会话与工作区之间」插槽。插件仍注册在公开的
|
|
236
412
|
* footer list slot 中保证生命周期与降级可用,再把实际按钮 Portal 到
|
|
@@ -548,17 +724,24 @@ window.__ModuleLoader__.load({
|
|
|
548
724
|
* 包名或客户端模块到达顺序让整个 Desktop 进入 Safe Mode。
|
|
549
725
|
*/
|
|
550
726
|
function createMarketViewStore() {
|
|
727
|
+
let sidebarVisible = true;
|
|
728
|
+
const liveActions = new Set();
|
|
551
729
|
const spec = {
|
|
552
|
-
init: () => ({ open: false, detailOpen: false }),
|
|
730
|
+
init: () => ({ open: false, detailOpen: false, sidebarVisible }),
|
|
553
731
|
actions: {
|
|
554
732
|
open: (draft) => { draft.open = true; },
|
|
555
733
|
close: (draft) => { draft.open = false; draft.detailOpen = false; },
|
|
556
734
|
detailOpened: (draft) => { draft.detailOpen = true; },
|
|
557
|
-
detailClosed: (draft) => { draft.detailOpen = false; }
|
|
735
|
+
detailClosed: (draft) => { draft.detailOpen = false; },
|
|
736
|
+
setSidebarVisible: (draft, visible) => { draft.sidebarVisible = visible !== false; }
|
|
558
737
|
}
|
|
559
738
|
};
|
|
560
739
|
return {
|
|
561
740
|
spec,
|
|
741
|
+
syncSidebarVisible(visible) {
|
|
742
|
+
sidebarVisible = visible !== false;
|
|
743
|
+
for (const actions of liveActions) actions.setSidebarVisible(sidebarVisible);
|
|
744
|
+
},
|
|
562
745
|
create() {
|
|
563
746
|
let state = spec.init();
|
|
564
747
|
const listeners = new Set();
|
|
@@ -571,6 +754,7 @@ window.__ModuleLoader__.load({
|
|
|
571
754
|
for (const listener of listeners) listener();
|
|
572
755
|
};
|
|
573
756
|
}
|
|
757
|
+
liveActions.add(actions);
|
|
574
758
|
return {
|
|
575
759
|
actions,
|
|
576
760
|
getSnapshot: () => state,
|
|
@@ -578,12 +762,216 @@ window.__ModuleLoader__.load({
|
|
|
578
762
|
listeners.add(listener);
|
|
579
763
|
return () => { listeners.delete(listener); };
|
|
580
764
|
},
|
|
581
|
-
clearPersisted() {
|
|
765
|
+
clearPersisted() {
|
|
766
|
+
liveActions.delete(actions);
|
|
767
|
+
listeners.clear();
|
|
768
|
+
}
|
|
582
769
|
};
|
|
583
770
|
}
|
|
584
771
|
};
|
|
585
772
|
}
|
|
586
773
|
|
|
774
|
+
function resolveSidebarVisible(snapshot) {
|
|
775
|
+
return snapshot?.status === "ready"
|
|
776
|
+
? snapshot.value?.[SHOW_SIDEBAR_ENTRY_FIELD] !== false
|
|
777
|
+
: true;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function connectorSettingsCopy() {
|
|
781
|
+
const language = document.documentElement?.lang || window.navigator?.language || "zh";
|
|
782
|
+
if (String(language).toLowerCase().startsWith("en")) {
|
|
783
|
+
return {
|
|
784
|
+
title: "MCP Connector",
|
|
785
|
+
description: "Control how the MCP Connector is opened.",
|
|
786
|
+
show: "Show MCP Connector in the sidebar",
|
|
787
|
+
hint: "Turning this off only hides the shortcut. Connected MCP servers and tools remain available.",
|
|
788
|
+
visible: "The sidebar shortcut is visible.",
|
|
789
|
+
hidden: "The shortcut is hidden. You can still open MCP Connector here.",
|
|
790
|
+
readOnly: "This settings page is read-only.",
|
|
791
|
+
saving: "Saving…",
|
|
792
|
+
failed: "The setting was not saved. Please try again.",
|
|
793
|
+
reset: "Reset",
|
|
794
|
+
open: "Open MCP Connector",
|
|
795
|
+
expand: "Expand MCP Connector settings",
|
|
796
|
+
collapse: "Collapse MCP Connector settings"
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
return {
|
|
800
|
+
title: "MCP连接器",
|
|
801
|
+
description: "控制侧边栏入口和快捷打开方式。",
|
|
802
|
+
show: "在侧边栏显示 MCP连接器",
|
|
803
|
+
hint: "关闭后只隐藏入口,不影响已连接的 MCP Server 和工具。",
|
|
804
|
+
visible: "侧边栏入口当前显示。",
|
|
805
|
+
hidden: "入口已隐藏,仍可从这里打开 MCP连接器。",
|
|
806
|
+
readOnly: "当前设置页只读。",
|
|
807
|
+
saving: "正在保存…",
|
|
808
|
+
failed: "设置未保存,请重试。",
|
|
809
|
+
reset: "恢复默认",
|
|
810
|
+
open: "打开 MCP连接器",
|
|
811
|
+
expand: "展开 MCP连接器设置",
|
|
812
|
+
collapse: "收起 MCP连接器设置"
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
function ConnectorSettingsCard(props) {
|
|
817
|
+
const { settingsScope, actions } = props;
|
|
818
|
+
const copy = connectorSettingsCopy();
|
|
819
|
+
const snapshot = (0, react.useSyncExternalStore)(
|
|
820
|
+
(listener) => settingsScope.subscribe(listener),
|
|
821
|
+
() => settingsScope.getSnapshot()
|
|
822
|
+
);
|
|
823
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
824
|
+
const [saving, setSaving] = (0, react.useState)(false);
|
|
825
|
+
const [failed, setFailed] = (0, react.useState)(false);
|
|
826
|
+
if (snapshot.status !== "ready") return null;
|
|
827
|
+
const visible = resolveSidebarVisible(snapshot);
|
|
828
|
+
const writable = snapshot.writable === true;
|
|
829
|
+
const overridden = snapshot.user !== null
|
|
830
|
+
&& typeof snapshot.user === "object"
|
|
831
|
+
&& Object.prototype.hasOwnProperty.call(snapshot.user, SHOW_SIDEBAR_ENTRY_FIELD);
|
|
832
|
+
|
|
833
|
+
const save = async (next) => {
|
|
834
|
+
setSaving(true);
|
|
835
|
+
setFailed(false);
|
|
836
|
+
try {
|
|
837
|
+
await settingsScope.set(SHOW_SIDEBAR_ENTRY_FIELD, next);
|
|
838
|
+
const confirmed = settingsScope.getSnapshot();
|
|
839
|
+
setFailed(confirmed.status !== "ready" || resolveSidebarVisible(confirmed) !== next);
|
|
840
|
+
} catch (error) {
|
|
841
|
+
console.error("[mcp-connector] sidebar setting update failed:", error);
|
|
842
|
+
setFailed(true);
|
|
843
|
+
} finally {
|
|
844
|
+
setSaving(false);
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
const reset = async () => {
|
|
849
|
+
setSaving(true);
|
|
850
|
+
setFailed(false);
|
|
851
|
+
try {
|
|
852
|
+
await settingsScope.unset(SHOW_SIDEBAR_ENTRY_FIELD);
|
|
853
|
+
const confirmed = settingsScope.getSnapshot();
|
|
854
|
+
const stillOverridden = confirmed.user !== null
|
|
855
|
+
&& typeof confirmed.user === "object"
|
|
856
|
+
&& Object.prototype.hasOwnProperty.call(confirmed.user, SHOW_SIDEBAR_ENTRY_FIELD);
|
|
857
|
+
setFailed(confirmed.status !== "ready" || stillOverridden);
|
|
858
|
+
} catch (error) {
|
|
859
|
+
console.error("[mcp-connector] sidebar setting reset failed:", error);
|
|
860
|
+
setFailed(true);
|
|
861
|
+
} finally {
|
|
862
|
+
setSaving(false);
|
|
863
|
+
}
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
867
|
+
className: "mcpConnectorSettingsCard",
|
|
868
|
+
"data-open": open,
|
|
869
|
+
children: [
|
|
870
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
871
|
+
type: "button",
|
|
872
|
+
className: "mcpConnectorSettingsHeader",
|
|
873
|
+
"aria-expanded": open,
|
|
874
|
+
"aria-label": open ? copy.collapse : copy.expand,
|
|
875
|
+
onClick: () => { setOpen(!open); },
|
|
876
|
+
children: [
|
|
877
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
878
|
+
className: "mcpConnectorSettingsHeadText",
|
|
879
|
+
children: [
|
|
880
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mcpConnectorSettingsName", children: copy.title }),
|
|
881
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mcpConnectorSettingsDescription", children: copy.description })
|
|
882
|
+
]
|
|
883
|
+
}),
|
|
884
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mcpConnectorSettingsChevron", "aria-hidden": true, children: "⌄" })
|
|
885
|
+
]
|
|
886
|
+
}),
|
|
887
|
+
open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
888
|
+
className: "mcpConnectorSettingsBody",
|
|
889
|
+
children: [
|
|
890
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
891
|
+
className: "mcpConnectorSettingsRow",
|
|
892
|
+
children: [
|
|
893
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
894
|
+
htmlFor: "mcp-connector-show-sidebar-entry",
|
|
895
|
+
children: [
|
|
896
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mcpConnectorSettingsLabel", children: copy.show }),
|
|
897
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "mcpConnectorSettingsHint", children: copy.hint })
|
|
898
|
+
]
|
|
899
|
+
}),
|
|
900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
901
|
+
id: "mcp-connector-show-sidebar-entry",
|
|
902
|
+
className: "mcpConnectorSettingsSwitch",
|
|
903
|
+
type: "checkbox",
|
|
904
|
+
role: "switch",
|
|
905
|
+
"aria-checked": visible,
|
|
906
|
+
checked: visible,
|
|
907
|
+
disabled: !writable || saving,
|
|
908
|
+
onChange: (event) => { void save(event.target.checked); }
|
|
909
|
+
})
|
|
910
|
+
]
|
|
911
|
+
}),
|
|
912
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
913
|
+
className: "mcpConnectorSettingsFooter",
|
|
914
|
+
children: [
|
|
915
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
916
|
+
className: "mcpConnectorSettingsState",
|
|
917
|
+
"data-tone": failed ? "error" : "normal",
|
|
918
|
+
role: failed ? "alert" : "status",
|
|
919
|
+
children: failed ? copy.failed : saving ? copy.saving : !writable ? copy.readOnly : visible ? copy.visible : copy.hidden
|
|
920
|
+
}),
|
|
921
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
922
|
+
type: "button",
|
|
923
|
+
className: "mcpConnectorSettingsButton",
|
|
924
|
+
disabled: !writable || saving || !overridden,
|
|
925
|
+
onClick: () => { void reset(); },
|
|
926
|
+
children: copy.reset
|
|
927
|
+
}),
|
|
928
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
929
|
+
type: "button",
|
|
930
|
+
className: "mcpConnectorSettingsButton",
|
|
931
|
+
"data-primary": true,
|
|
932
|
+
"aria-haspopup": "dialog",
|
|
933
|
+
onClick: () => { actions.open(); },
|
|
934
|
+
children: copy.open
|
|
935
|
+
})
|
|
936
|
+
]
|
|
937
|
+
})
|
|
938
|
+
]
|
|
939
|
+
}) : null
|
|
940
|
+
]
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
function installClientSettings(ctx, marketView) {
|
|
945
|
+
if (typeof ctx.inject !== "function") return;
|
|
946
|
+
ctx.inject(["settingsScope"], (settingsCtx) => {
|
|
947
|
+
const settingsScope = settingsCtx.settingsScope.bind({
|
|
948
|
+
namespace: CONNECTOR_SETTINGS_NAMESPACE,
|
|
949
|
+
decode(value) {
|
|
950
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
951
|
+
return typeof value[SHOW_SIDEBAR_ENTRY_FIELD] === "boolean"
|
|
952
|
+
? { [SHOW_SIDEBAR_ENTRY_FIELD]: value[SHOW_SIDEBAR_ENTRY_FIELD] }
|
|
953
|
+
: void 0;
|
|
954
|
+
}
|
|
955
|
+
});
|
|
956
|
+
settingsCtx.effect(() => {
|
|
957
|
+
const sync = () => { marketView.syncSidebarVisible(resolveSidebarVisible(settingsScope.getSnapshot())); };
|
|
958
|
+
sync();
|
|
959
|
+
const unsubscribe = settingsScope.subscribe(sync);
|
|
960
|
+
return () => {
|
|
961
|
+
unsubscribe();
|
|
962
|
+
marketView.syncSidebarVisible(true);
|
|
963
|
+
};
|
|
964
|
+
}, "mcp-connector: sidebar visibility setting");
|
|
965
|
+
settingsCtx.effect(() => installSettingsStyles(), "mcp-connector: settings styles");
|
|
966
|
+
settingsCtx.slots.inject("settings.plugin.item", () => settingsCtx.slots.register({
|
|
967
|
+
name: "settings.plugin.item",
|
|
968
|
+
key: CONNECTOR_SETTINGS_NAMESPACE,
|
|
969
|
+
store: marketView,
|
|
970
|
+
inject: () => ({ settingsScope })
|
|
971
|
+
}, ConnectorSettingsCard));
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
|
|
587
975
|
/**
|
|
588
976
|
* 用 DSH 自身的工作区/会话/输入机把示例 Prompt 带入新会话。
|
|
589
977
|
* connectWorkspace 与 DSH 的「新会话」按钮同源:优先复用当前工作区的
|
|
@@ -815,10 +1203,21 @@ window.__ModuleLoader__.load({
|
|
|
815
1203
|
}, [open, updateOperation?.operationId, updateProviderSelection?.provider?.id, expectedUpdateVersion]);
|
|
816
1204
|
(0, react.useEffect)(() => {
|
|
817
1205
|
if (!open) return void 0;
|
|
1206
|
+
const opener = document.activeElement;
|
|
818
1207
|
closeRef.current?.focus?.();
|
|
819
|
-
const onKeyDown = (event) => {
|
|
820
|
-
|
|
821
|
-
|
|
1208
|
+
const onKeyDown = (event) => {
|
|
1209
|
+
if (event.key !== "Escape") return;
|
|
1210
|
+
event.preventDefault();
|
|
1211
|
+
event.stopPropagation();
|
|
1212
|
+
actions.close();
|
|
1213
|
+
};
|
|
1214
|
+
// Capture at window before the underlying Settings dialog receives
|
|
1215
|
+
// Escape on document; only the topmost connector dialog should close.
|
|
1216
|
+
window.addEventListener("keydown", onKeyDown, true);
|
|
1217
|
+
return () => {
|
|
1218
|
+
window.removeEventListener("keydown", onKeyDown, true);
|
|
1219
|
+
if (opener?.isConnected !== false) opener?.focus?.();
|
|
1220
|
+
};
|
|
822
1221
|
}, [open, actions]);
|
|
823
1222
|
if (!open) return null;
|
|
824
1223
|
const updateRunning = updateStarting || updateOperation !== null && ["queued", "running"].includes(updateOperation.state);
|
|
@@ -1084,7 +1483,7 @@ window.__ModuleLoader__.load({
|
|
|
1084
1483
|
});
|
|
1085
1484
|
};
|
|
1086
1485
|
const src = window.location.origin + "/mcp-connector/ui/";
|
|
1087
|
-
|
|
1486
|
+
const modal = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1088
1487
|
style: {
|
|
1089
1488
|
position: "fixed",
|
|
1090
1489
|
inset: 0,
|
|
@@ -1092,7 +1491,7 @@ window.__ModuleLoader__.load({
|
|
|
1092
1491
|
display: "flex",
|
|
1093
1492
|
alignItems: "center",
|
|
1094
1493
|
justifyContent: "center",
|
|
1095
|
-
zIndex:
|
|
1494
|
+
zIndex: CONNECTOR_MODAL_Z_INDEX
|
|
1096
1495
|
},
|
|
1097
1496
|
onClick: (event) => { if (event.target === event.currentTarget) actions.close(); },
|
|
1098
1497
|
children: [
|
|
@@ -1182,14 +1581,28 @@ window.__ModuleLoader__.load({
|
|
|
1182
1581
|
})
|
|
1183
1582
|
]
|
|
1184
1583
|
});
|
|
1584
|
+
// shell.overlay lives inside a z-index:20 stacking context, while DSH
|
|
1585
|
+
// Settings is a root-level z-index:1000 modal. Portal to body so the
|
|
1586
|
+
// quick-open action can reliably place this dialog above Settings.
|
|
1587
|
+
if (document.body !== null && document.body !== void 0
|
|
1588
|
+
&& typeof react_dom.createPortal === "function") {
|
|
1589
|
+
return react_dom.createPortal(modal, document.body);
|
|
1590
|
+
}
|
|
1591
|
+
return modal;
|
|
1185
1592
|
}
|
|
1186
1593
|
|
|
1187
1594
|
/** 左栏入口按钮:使用 DSH Button 组件,与社区插件市场一致。 */
|
|
1188
1595
|
function SidebarEntry(props) {
|
|
1189
1596
|
const { wide, useStore, actions } = props;
|
|
1190
1597
|
const open = useStore((state) => state.open);
|
|
1598
|
+
const visible = useStore((state) => state.sidebarVisible !== false);
|
|
1191
1599
|
const [topMount, setTopMount] = (0, react.useState)(null);
|
|
1192
1600
|
(0, react.useEffect)(() => {
|
|
1601
|
+
if (!visible) {
|
|
1602
|
+
setTopMount(null);
|
|
1603
|
+
return void 0;
|
|
1604
|
+
}
|
|
1605
|
+
const removeStyles = installSidebarStyles();
|
|
1193
1606
|
let disposed = false;
|
|
1194
1607
|
const ownedMounts = new Set();
|
|
1195
1608
|
const syncMount = () => {
|
|
@@ -1208,8 +1621,10 @@ window.__ModuleLoader__.load({
|
|
|
1208
1621
|
disposed = true;
|
|
1209
1622
|
observer?.disconnect();
|
|
1210
1623
|
for (const mount of ownedMounts) mount.remove();
|
|
1624
|
+
removeStyles();
|
|
1211
1625
|
};
|
|
1212
|
-
}, []);
|
|
1626
|
+
}, [visible]);
|
|
1627
|
+
if (!visible) return null;
|
|
1213
1628
|
const launcher = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1214
1629
|
type: "button",
|
|
1215
1630
|
className: "mcpConnectorLauncher",
|
|
@@ -1232,7 +1647,8 @@ window.__ModuleLoader__.load({
|
|
|
1232
1647
|
console.log('[mcp-connector] client apply() called');
|
|
1233
1648
|
try {
|
|
1234
1649
|
const marketView = createMarketViewStore();
|
|
1235
|
-
ctx.effect(() =>
|
|
1650
|
+
ctx.effect(() => installOverlayStyles(), "mcp-connector: overlay styles");
|
|
1651
|
+
installClientSettings(ctx, marketView);
|
|
1236
1652
|
|
|
1237
1653
|
// 弹框:注册到 shell.overlay(类似社区插件市场)
|
|
1238
1654
|
ctx.slots.inject("shell.overlay", () => {
|
package/lib/index.js
CHANGED
|
@@ -62,6 +62,7 @@ import {
|
|
|
62
62
|
scopeLabel,
|
|
63
63
|
scopeTargets,
|
|
64
64
|
} from './connection-scopes.js';
|
|
65
|
+
import { installConnectorSettings } from './settings.js';
|
|
65
66
|
|
|
66
67
|
export const name = 'mcp-connector';
|
|
67
68
|
|
|
@@ -105,9 +106,12 @@ export const Config = z.object({
|
|
|
105
106
|
openBrowser: z.boolean().default(true),
|
|
106
107
|
/** 授权账号标识(预留多账号) */
|
|
107
108
|
account: z.string().default(DEFAULT_ACCOUNT),
|
|
109
|
+
/** 是否在 DSH 主侧边栏显示 MCP连接器快捷入口 */
|
|
110
|
+
showSidebarEntry: z.boolean().default(true),
|
|
108
111
|
});
|
|
109
112
|
|
|
110
113
|
export async function apply(ctx, config) {
|
|
114
|
+
installConnectorSettings(ctx, config);
|
|
111
115
|
const logger = ctx.logger('mcp-connector');
|
|
112
116
|
const versionStatusService = createVersionStatusService({
|
|
113
117
|
timeoutMs: config.requestTimeoutMs,
|
package/lib/settings.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import z from '@deepseek-ai/schemastery';
|
|
2
|
+
|
|
3
|
+
export const CONNECTOR_SETTINGS_NAMESPACE = 'mcp-connector';
|
|
4
|
+
export const SHOW_SIDEBAR_ENTRY_FIELD = 'showSidebarEntry';
|
|
5
|
+
|
|
6
|
+
export const ConnectorSettings = z.object({
|
|
7
|
+
[SHOW_SIDEBAR_ENTRY_FIELD]: z.boolean().default(true),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Register the connector's user-facing settings only while a Settings provider
|
|
12
|
+
* is present. The provider owns persistence; older DSH hosts keep the composed
|
|
13
|
+
* config and continue loading the connector normally.
|
|
14
|
+
*/
|
|
15
|
+
export function installConnectorSettings(ctx, config = {}) {
|
|
16
|
+
if (typeof ctx.inject !== 'function') return;
|
|
17
|
+
ctx.inject(['settings'], (settingsCtx) => {
|
|
18
|
+
settingsCtx.settings.register(CONNECTOR_SETTINGS_NAMESPACE, ConnectorSettings, {
|
|
19
|
+
base: {
|
|
20
|
+
[SHOW_SIDEBAR_ENTRY_FIELD]: config[SHOW_SIDEBAR_ENTRY_FIELD] !== false,
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mcp-connector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.39",
|
|
4
4
|
"description": "DeepSeek Harness MCP Connector and MCP Server marketplace with over one hundred MCP connectors, continuously updated. Discover, authorize, and manage connections in one place; supports OAuth 2.0 PKCE, API keys, stdio/HTTP, mcpServers JSON import, and tool and prompt discovery. Maintained by Qichacha/QCC.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
],
|
|
42
42
|
"scripts": {
|
|
43
43
|
"test": "node --test",
|
|
44
|
-
"lint": "node --check lib/index.js && node --check lib/web.js && node --check lib/client.js && node --check lib/version-status.js && node --check lib/schema.js && node --check lib/catalog.js && node --check lib/prompts.js && node --check lib/probe.js && node --check lib/diagnostics.js && node --check lib/connection-backup.js && node --check lib/connection-scopes.js && node --check lib/governance.js && node --check lib/mcp-validation.js && node --check lib/mcp-http.js && node --check lib/migration.js && node --check lib/stores.js && node --check lib/grant-journal.js && node --check lib/oauth.js && node --check lib/grant-lifecycle.js && node --check lib/callback-server.js && node --check lib/mcp-provision.js && node --check lib/util.js && node --check lib/constants.js && node --check lib/tools.js && node --check lib/connectors/oauth-connector.js && node --check lib/connectors/manual-connector.js && node --check lib/connectors/json-connector.js && node --check scripts/probe-connector.mjs && node --check scripts/build-registry.mjs && node --check scripts/ui-harness.mjs && node --check scripts/check-market-registration.mjs && node --check scripts/check-readme-version.mjs && node --check scripts/check-marketing-metadata.mjs && node --check scripts/check-storefront-screenshots.mjs && node --check scripts/sync-registry-stats.mjs && node --check scripts/verify-pack.mjs",
|
|
44
|
+
"lint": "node --check lib/index.js && node --check lib/web.js && node --check lib/client.js && node --check lib/settings.js && node --check lib/version-status.js && node --check lib/schema.js && node --check lib/catalog.js && node --check lib/prompts.js && node --check lib/probe.js && node --check lib/diagnostics.js && node --check lib/connection-backup.js && node --check lib/connection-scopes.js && node --check lib/governance.js && node --check lib/mcp-validation.js && node --check lib/mcp-http.js && node --check lib/migration.js && node --check lib/stores.js && node --check lib/grant-journal.js && node --check lib/oauth.js && node --check lib/grant-lifecycle.js && node --check lib/callback-server.js && node --check lib/mcp-provision.js && node --check lib/util.js && node --check lib/constants.js && node --check lib/tools.js && node --check lib/connectors/oauth-connector.js && node --check lib/connectors/manual-connector.js && node --check lib/connectors/json-connector.js && node --check scripts/probe-connector.mjs && node --check scripts/build-registry.mjs && node --check scripts/ui-harness.mjs && node --check scripts/check-market-registration.mjs && node --check scripts/check-readme-version.mjs && node --check scripts/check-marketing-metadata.mjs && node --check scripts/check-storefront-screenshots.mjs && node --check scripts/sync-registry-stats.mjs && node --check scripts/verify-pack.mjs",
|
|
45
45
|
"registry:build": "node scripts/build-registry.mjs",
|
|
46
46
|
"registry:validate": "node scripts/probe-connector.mjs catalog/catalog.json --validate-only",
|
|
47
47
|
"dev:ui": "node scripts/ui-harness.mjs",
|