@sunshaobei/dsh-mcp-manager 0.0.0-stage → 0.5.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.
Files changed (144) hide show
  1. package/LICENSE +1 -0
  2. package/README.en.md +482 -0
  3. package/README.md +385 -2
  4. package/cordis.patch.yml +9 -0
  5. package/lib/THIRD-PARTY-LICENSES +43 -0
  6. package/lib/client/core/api.d.ts +42 -0
  7. package/lib/client/core/constants.d.ts +58 -0
  8. package/lib/client/core/current-session.d.ts +39 -0
  9. package/lib/client/core/dom.d.ts +19 -0
  10. package/lib/client/core/i18n.d.ts +12 -0
  11. package/lib/client/core/session.d.ts +27 -0
  12. package/lib/client/core/state.d.ts +120 -0
  13. package/lib/client/float/float.d.ts +126 -0
  14. package/lib/client/float/panel.d.ts +31 -0
  15. package/lib/client/float/quick-add.d.ts +38 -0
  16. package/lib/client/float/servers.d.ts +60 -0
  17. package/lib/client/index.d.ts +26 -0
  18. package/lib/client/locales.d.ts +123 -0
  19. package/lib/client/settings/settings-card.d.ts +47 -0
  20. package/lib/client.js +2469 -0
  21. package/lib/index.d.ts +86 -0
  22. package/lib/index.js +10298 -0
  23. package/lib/server/api/deps.d.ts +36 -0
  24. package/lib/server/api/impl/health/type.d.ts +12 -0
  25. package/lib/server/api/impl/service/index.d.ts +28 -0
  26. package/lib/server/api/interface.d.ts +27 -0
  27. package/lib/server/api/routes-controllers.d.ts +61 -0
  28. package/lib/server/api/routes-helpers.d.ts +8 -0
  29. package/lib/server/api/routes.d.ts +58 -0
  30. package/lib/server/catalog/deps.d.ts +51 -0
  31. package/lib/server/catalog/impl/cache-view/index.d.ts +48 -0
  32. package/lib/server/catalog/impl/digest/index.d.ts +19 -0
  33. package/lib/server/catalog/impl/directory/index.d.ts +168 -0
  34. package/lib/server/catalog/impl/entries/index.d.ts +129 -0
  35. package/lib/server/catalog/impl/entries/type.d.ts +19 -0
  36. package/lib/server/catalog/impl/history/index.d.ts +36 -0
  37. package/lib/server/catalog/impl/injection/index.d.ts +45 -0
  38. package/lib/server/catalog/impl/search/type.d.ts +59 -0
  39. package/lib/server/catalog/impl/service/index.d.ts +25 -0
  40. package/lib/server/catalog/interface.d.ts +45 -0
  41. package/lib/server/catalog/search.d.ts +108 -0
  42. package/lib/server/config/config-schema.d.ts +85 -0
  43. package/lib/server/config/impl/env/index.d.ts +24 -0
  44. package/lib/server/config/impl/env/policy.d.ts +54 -0
  45. package/lib/server/config/impl/model/type.d.ts +39 -0
  46. package/lib/server/config/impl/ui/type.d.ts +20 -0
  47. package/lib/server/config/import.d.ts +20 -0
  48. package/lib/server/config/interface.d.ts +15 -0
  49. package/lib/server/config/normalize.d.ts +24 -0
  50. package/lib/server/config/sources-sync.d.ts +32 -0
  51. package/lib/server/config/sources.d.ts +50 -0
  52. package/lib/server/connection/interface.d.ts +95 -0
  53. package/lib/server/connection/orchestrator/deps.d.ts +93 -0
  54. package/lib/server/connection/orchestrator/impl/service/index.d.ts +27 -0
  55. package/lib/server/connection/orchestrator/interface.d.ts +25 -0
  56. package/lib/server/connection/orchestrator/manager.d.ts +502 -0
  57. package/lib/server/connection/orchestrator/tool-names.d.ts +14 -0
  58. package/lib/server/connection/runtime/deps.d.ts +142 -0
  59. package/lib/server/connection/runtime/impl/middleware/type.d.ts +45 -0
  60. package/lib/server/connection/runtime/impl/service/index.d.ts +28 -0
  61. package/lib/server/connection/runtime/interface.d.ts +29 -0
  62. package/lib/server/connection/runtime/limits.d.ts +19 -0
  63. package/lib/server/connection/runtime/middleware.d.ts +196 -0
  64. package/lib/server/erasure/impl/guard/index.d.ts +35 -0
  65. package/lib/server/erasure/interface.d.ts +31 -0
  66. package/lib/server/inject/deps.d.ts +54 -0
  67. package/lib/server/inject/impl/call-timeout/index.d.ts +1 -0
  68. package/lib/server/inject/impl/image-admission/index.d.ts +81 -0
  69. package/lib/server/inject/impl/service/index.d.ts +25 -0
  70. package/lib/server/inject/interface.d.ts +27 -0
  71. package/lib/server/inject/middleware-register.d.ts +114 -0
  72. package/lib/server/pipeline/deps.d.ts +27 -0
  73. package/lib/server/pipeline/impl/args/index.d.ts +26 -0
  74. package/lib/server/pipeline/impl/authorize/index.d.ts +43 -0
  75. package/lib/server/pipeline/impl/msg/index.d.ts +8 -0
  76. package/lib/server/pipeline/impl/project/index.d.ts +43 -0
  77. package/lib/server/pipeline/impl/redact/index.d.ts +13 -0
  78. package/lib/server/pipeline/impl/service/index.d.ts +25 -0
  79. package/lib/server/pipeline/impl/timeout/index.d.ts +8 -0
  80. package/lib/server/pipeline/interface.d.ts +32 -0
  81. package/lib/server/servers/dispatch/deps.d.ts +100 -0
  82. package/lib/server/servers/dispatch/impl/call/index.d.ts +49 -0
  83. package/lib/server/servers/dispatch/impl/redact/index.d.ts +13 -0
  84. package/lib/server/servers/dispatch/interface.d.ts +18 -0
  85. package/lib/server/servers/lifecycle/deps.d.ts +62 -0
  86. package/lib/server/servers/lifecycle/impl/ledger/index.d.ts +52 -0
  87. package/lib/server/servers/lifecycle/impl/logs/index.d.ts +48 -0
  88. package/lib/server/servers/lifecycle/impl/mount/index.d.ts +83 -0
  89. package/lib/server/servers/lifecycle/impl/service/index.d.ts +26 -0
  90. package/lib/server/servers/lifecycle/impl/state/index.d.ts +35 -0
  91. package/lib/server/servers/lifecycle/impl/timeout/index.d.ts +39 -0
  92. package/lib/server/servers/lifecycle/interface.d.ts +56 -0
  93. package/lib/server/shared/compose.d.ts +38 -0
  94. package/lib/server/shared/constants.d.ts +62 -0
  95. package/lib/server/shared/file-io.d.ts +8 -0
  96. package/lib/server/shared/host-faces.d.ts +206 -0
  97. package/lib/server/shared/interface.d.ts +14 -0
  98. package/lib/server/shared/paths.d.ts +66 -0
  99. package/lib/server/shared/tool-names.d.ts +11 -0
  100. package/lib/server/stats/impl/collector.d.ts +68 -0
  101. package/lib/server/stats/impl/type.d.ts +41 -0
  102. package/lib/server/stats/interface.d.ts +13 -0
  103. package/lib/server/store/impl/middleware-state.d.ts +45 -0
  104. package/lib/server/store/impl/store.d.ts +43 -0
  105. package/lib/server/store/interface.d.ts +9 -0
  106. package/lib/server/upgrade/deps.d.ts +25 -0
  107. package/lib/server/upgrade/impl/chain/index.d.ts +2 -0
  108. package/lib/server/upgrade/impl/service/index.d.ts +9 -0
  109. package/lib/server/upgrade/impl/steps/index.d.ts +19 -0
  110. package/lib/server/upgrade/impl/steps/project-layout.d.ts +24 -0
  111. package/lib/server/upgrade/impl/steps/storage-layout.d.ts +17 -0
  112. package/lib/server/upgrade/impl/version/index.d.ts +7 -0
  113. package/lib/server/upgrade/interface.d.ts +21 -0
  114. package/lib/server/visibility/impl/mask/index.d.ts +7 -0
  115. package/lib/server/visibility/interface.d.ts +46 -0
  116. package/lib/server/workspace/impl/full-name/index.d.ts +24 -0
  117. package/lib/server/workspace/impl/root-resolution/index.d.ts +18 -0
  118. package/lib/server/workspace/impl/scope/index.d.ts +14 -0
  119. package/lib/server/workspace/impl/server-id/index.d.ts +17 -0
  120. package/lib/server/workspace/interface.d.ts +22 -0
  121. package/lib/shared/constants.d.ts +22 -0
  122. package/lib/shared/dto.d.ts +62 -0
  123. package/lib/shared/frames.d.ts +19 -0
  124. package/lib/shared/interface.d.ts +22 -0
  125. package/lib/shared/placement-math.d.ts +81 -0
  126. package/lib/shared/routes.d.ts +43 -0
  127. package/lib/shared/service.d.ts +85 -0
  128. package/lib/shared/status.d.ts +23 -0
  129. package/lib/vendor/shared/README.md +147 -0
  130. package/lib/vendor/shared/client/ensure-style.d.ts +23 -0
  131. package/lib/vendor/shared/client/i18n.d.ts +30 -0
  132. package/lib/vendor/shared/client/ui/index.d.ts +214 -0
  133. package/lib/vendor/shared/dsh-home.d.ts +26 -0
  134. package/lib/vendor/shared/host-utils.d.ts +82 -0
  135. package/lib/vendor/shared/loopback.d.ts +12 -0
  136. package/lib/vendor/shared/package.json +12 -0
  137. package/lib/vendor/shared/paths.d.ts +35 -0
  138. package/lib/vendor/shared/settings-namespace.d.ts +82 -0
  139. package/lib/vendor/shared/sse-hub.d.ts +75 -0
  140. package/lib/vendor/shared/upgrade-chain.d.ts +140 -0
  141. package/lib/vendor/shared/upgrade-tick.d.ts +17 -0
  142. package/locale/en.json +6 -0
  143. package/locale/zh.json +6 -0
  144. package/package.json +170 -4
package/README.md CHANGED
@@ -1,3 +1,386 @@
1
- # Temporary Holding Version
1
+ # dsh-mcp-manager
2
+ [![npm](https://img.shields.io/npm/v/dsh-mcp-manager)](https://www.npmjs.com/package/dsh-mcp-manager)
3
+ [![GitHub Releases](https://img.shields.io/github/v/release/wingsky-1/dsh-plugin-hub)](https://github.com/wingsky-1/dsh-plugin-hub/releases)
2
4
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
5
+ DSH(DeepSeek Harness)的 **MCP 服务器管理插件**:会话界面右上角浮窗 + 分级面板 +
6
+ 快速接入(手工表单 + 粘贴 mcpServers JSON 导入,**不预设任何服务器**)。
7
+ 连接与协议交官方 `@deepseek-ai/dsh-mcp-client`(宿主 cordis loader 按包名装载到 dsh 安装内的副本),本插件只留配置面与模型可见面;官方客户端不随包分发,也无需额外安装。
8
+
9
+ 模型可见面只有四个原子工具(`ws_mcp_list` / `ws_mcp_detail` / `ws_mcp_search` /
10
+ `ws_mcp_call`):项目级、全局级与运行时注入的封装定义条目**一律经中间层访问**,两级发现
11
+ (`ws_mcp_list` 完整盘点 → `ws_mcp_detail` 按需拉完整 schema);cwd 无项目时回落全局虚拟
12
+ root `@global`。宿主仍按 `mcp__<id>__<tool>` 注册工具(`id` 是本次装配按
13
+ (工作空间, 服务器名) 分配的不透明短串,不能由服务器名推导),但这些名字**会被从模型的
14
+ 工具列表中摘除**,禁止直呼。
15
+ 两级配置文件中的服务器列表(增删/启停/改配置)支持热加载、即时生效,无需重启。
16
+ (`middleware` / `middlewarePolicy` 两个配置键已在 #767 笔 2 废除——旧配置里写了不生效、
17
+ 也不会被本插件改写。)
18
+
19
+ > **升级后历史会话打不开?**
20
+ > 当前版本只生成 producer-owned V4 source;旧 source 仅通过一次性维护脚本处理,详见[升级与历史会话边界](#升级与历史会话边界)。
21
+
22
+ ## 一键安装
23
+
24
+ ```sh
25
+ dsh plugin --profile web add dsh-mcp-manager
26
+ ```
27
+
28
+ > 安装 / 卸载 / 更新后都需**重启一次** `dsh web`(bundle 层只在启动时组合)生效。
29
+
30
+ ## 核心优势
31
+
32
+ - **上下文成本可控**:全部 MCP 经中间层收敛,模型面只占 `ws_mcp_list` /
33
+ `ws_mcp_detail` / `ws_mcp_search` / `ws_mcp_call` 四个原子工具位——接多少台
34
+ 服务器、多少个工具都不膨胀系统提示词(两级发现:`ws_mcp_list` 完整盘点 →
35
+ `ws_mcp_detail` 按需拉完整 schema)
36
+ - **分工作目录维护**:项目级配置 `<项目根>/.dsh/dsh-mcp-manager/mcp.json` 随仓库走、可提交 git 团队共享;
37
+ 全局配置 `<DSH_HOME>/dsh-mcp-manager/mcp.json` 常连;切换会话自动加载当前目录的 MCP 集
38
+ - **工作空间隔离**:中间层以会话 cwd 路由到对应连接池,server 全名一致性校验防跨空间
39
+ 串台;不同目录注入同名 server 也互不冲突
40
+ - **安全的默认值**:配置只存 `${ENV}` 引用、不落盘密钥本身(0600 权限 + 原子写入);
41
+ stdio 子进程环境净化,宿主凭据形状变量不透传;目录摘要与错误路径经 redactor 脱敏
42
+ - **运维省心**:运行中/连接中/失败等分级状态一目了然;断线有界指数退避自动重连;
43
+ 调用超时可按 server 覆盖(`toolCallTimeoutMs`),中间层调用按在用服务器的最大值 + 25s
44
+ 内部尾结算(默认 15s + 25s = 40s)
45
+
46
+ ## 安装
47
+
48
+ 前提:已安装 DeepSeek Harness 且 `dsh web` 可正常启动(未全局安装 dsh 见下方「未全局安装 dsh」)。
49
+
50
+ ### 安装插件(add)
51
+
52
+ ```sh
53
+ dsh plugin --profile web add dsh-mcp-manager
54
+ ```
55
+
56
+ ### 卸载插件(remove)
57
+
58
+ ```sh
59
+ dsh plugin --profile web remove dsh-mcp-manager
60
+ ```
61
+
62
+ ### 更新插件(update)
63
+
64
+ ```sh
65
+ dsh plugin --profile web update dsh-mcp-manager
66
+ ```
67
+
68
+ > 安装 / 卸载 / 更新后都需**重启一次** `dsh web`(bundle 层只在启动时组合)生效。
69
+
70
+ ### 指定版本号(@version)
71
+
72
+ 省略 `@版本号` 即安装默认 latest(推荐)。仅当 registry 尚未同步到最新、或最新版在你的环境有问题时,在包名后追加 `@版本号`:
73
+
74
+ ```sh
75
+ dsh plugin --profile web add dsh-mcp-manager@<版本号>
76
+ ```
77
+
78
+ ### 未全局安装 dsh
79
+
80
+ 若本机没有全局 `dsh` 命令,用 `npx` 临时拉起(底层调用 `pnpm`,仍需本机装好 `pnpm` 与 `Node.js`):
81
+
82
+ ```sh
83
+ npx @deepseek-ai/dsh plugin --profile web add dsh-mcp-manager
84
+ npx @deepseek-ai/dsh plugin --profile web remove dsh-mcp-manager
85
+ npx @deepseek-ai/dsh plugin --profile web update dsh-mcp-manager
86
+ ```
87
+
88
+ ## 能力
89
+
90
+ | 能力 | 说明 |
91
+ | --- | --- |
92
+ | 右上角浮窗 | 状态点 + 计数摘要(`MCP 2/3`),点击展开下拉面板;随会话切换自动刷新 |
93
+ | 项目级 MCP | 服务器分「项目级 / 全局」两级:项目级存 `<项目根>/.dsh/dsh-mcp-manager/mcp.json`(随项目走、可提交 git),全局存 `<DSH_HOME>/dsh-mcp-manager/mcp.json` 常连 |
94
+ | 分级展示 | 运行中 / 连接中 / 重连中 / 未连接 / 已停用 / 失败;每台显示传输、端点、工具数;客户端未知状态按「未连接」投影、不丢卡(C13 统一口径) |
95
+ | 服务器管理 | 增删改查(可选项目级/全局)、连接 / 断开 / 重连;配置版本化 JSON,原子写入 |
96
+ | 两种传输 | stdio(本地子进程,env 支持 `${ENV}` 引用)与 streamable-http(远程,header 支持 `${ENV}` 引用,自动回传 `Mcp-Session-Id`) |
97
+ | JSON 导入 | 粘贴 mcpServers JSON 文本导入(仅 JSON 格式;不扫描任何应用配置文件) |
98
+ | 模型工具 | 全部服务器(项目级 / 全局 / runtime 注入)一律经中间层四个原子工具访问:`ws_mcp_list` / `ws_mcp_detail` / `ws_mcp_search` / `ws_mcp_call`,不同工作空间互不冲突;宿主注册名 `mcp__<id>__<tool>`(`id` 按 (工作空间, 服务器名) 随机分配、同一次装配内稳定、不透明;工具名仍受 64 字符 / `[A-Za-z0-9_-]` / 冲突哈希后缀约束)会被从模型工具列表摘除——模型不可见、不得直呼 |
99
+ | 工作空间隔离 | 中间层按调用方会话当前 cwd 路由到对应工作空间的连接池;server 全名 `@<root>/<server>` 一致性校验防跨空间串台 |
100
+ | 断线重连 | 有界指数退避(500ms 起、30s 上限、10 次后停止后台重试;用户手动连接或 ws_mcp_call 触发可再试) |
101
+ | 结果体积 | 本包**不做结果截断**,工具结果原样返回。目录装箱限额(每工具 4KB / 总 256KB)约束的是**目录**、不是执行结果;需要限长请在 MCP 服务器侧或宿主 compaction 策略里做 |
102
+ | 超时下探 | 工具调用超时默认 60s → 15s(可按服务器 `toolCallTimeoutMs` 覆盖);中间层 `ws_mcp_call` 按在用服务器最大值 + 25s 内部尾结算,**不是固定值** |
103
+ | 状态推送自愈 | SSE 通道共享 sse-hub(#515):服务端每 30s data ping 心跳 + stalled 超窗回收 + maxAge 轮换(120min 无业务帧主动断开);客户端 60s 无帧即关旧建新(watchdog)、页面回前台重建 SSE 并 POST resume 做非强制可用性恢复(携带本次会话 cwd,服务端固定本次 root;旧无 body 请求回落既有绑定);SSE 连续失败降级 10s 轮询,期间每 5 个轮询周期自动探测恢复推送(C2,页面失联自愈)——移动端切后台被静默掐断的半开连接由客户端自愈 + 服务端确定性回收,不堆积僵尸连接。自动恢复复用官方管理机制的已存在状态投影与在途去重,不强制重建健康/connecting/reconnecting 连接;**不声称检测真实健康**(有工具注册的健康连接与半开连接无法实时区分),半开仍由用户显式重连恢复 |
104
+
105
+ ## 配置(浮窗位置)
106
+
107
+ 配置页入口:**Plugin Manager → dsh-mcp-manager → Configure**。浮窗按钮(MCP 胶囊)的位置与偏移(`position` / `offset`)在此保存,canonical row id 为 `dsh-mcp-manager`,settings namespace 为 `dsh-mcp-manager`,保存后即时生效。
108
+
109
+ > 非回环 LAN 地址(例如 `192.168.*:3081`)默认不提供持久化设置面,Configure 按钮按 DSH 安全策略隐藏;请从 `127.0.0.1:3080` / `127.0.0.1:3081` 或 SSH 回环隧道管理。只有在可信 LAN、明确接受共享控制面风险时,才通过 dsh-lan-proxy 的 `ownsHostCompat` 恢复远程设置入口。
110
+
111
+ | 键 | 值域 | 默认 |
112
+ | --- | --- | --- |
113
+ | `position` | `top-right`(右上,默认)/ `top-left`(左上)/ `bottom-right`(右下)/ `bottom-left`(左下) | `top-right` |
114
+ | `offset.x` | 非负整数(水平偏移,单位 px) | `8` |
115
+ | `offset.y` | 非负整数(垂直偏移,单位 px) | `8` |
116
+ | `offset.blankY` | 非负整数(空白会话垂直偏移,单位 px) | `40` |
117
+ | `zIndexBase` | 整数,clamp 到 1–9000(浮窗层级基准;**胶囊与点击后弹出的主面板同取该配置值**,模态管理面板不受影响) | `10` |
118
+
119
+ #### Settings namespace
120
+
121
+ DSH 官方 importer 会按同名 section 直接导入 `dsh-mcp-manager`;本插件不再运行第二套 namespace migration。`settings.yaml.imported` 仅为已消费文档的审计副本,不应整体复制。
122
+
123
+ 当 `position = bottom-right` 或 `bottom-left` 时,下拉面板会**在胶囊上方展开**(底部
124
+ 锚点向上弹出),不溢出视口、内容完整可见可点击;顶部锚点向下展开(历史行为,默认不变)。
125
+
126
+ **移动端 / 平板端适配**(issue #128):断点判定基准是会话容器(conversationHost)
127
+ 的视口宽度而非窗口媒体查询——窄屏(≤480px,手机竖屏 / 极窄分栏)下面板近全屏宽、
128
+ 服务器卡片重排、操作按钮触控目标加大到 ≈44px;平板档(≤834px)过渡;桌面维持现状。
129
+ 浮窗最终坐标经 JS 视口 clamp(safe-area 语义:宿主无 `viewport-fit=cover`,
130
+ `env(safe-area-inset-*)` 恒 0 时自然退化为普通 clamp);软键盘弹出经
131
+ `visualViewport` resize 跟随,横竖屏切换后下一帧重算。
132
+
133
+ **跨包避让契约(源自 issue #116,不可回退)**:本插件浮窗默认 `top-right` 且距顶
134
+ 8px、高约 26px;dsh-provider-usage 用量胶囊依赖这一默认位置以 `offsetY: 48`
135
+ 在其正下方让位(两胶囊默认互不重叠)。修改本插件默认锚点 / 垂直偏移会使该避让
136
+ 失效,属跨包行为契约,回退前须同步调整 provider-usage 默认值。
137
+
138
+ 在设置页保存后即时生效,**无需重启 dsh web**、也无需手动刷新页面:宿主端经既有
139
+ SSE events 通道推送一变,客户端自动重新拉取 `/api/dsh-mcp/config` 并就地更新浮窗位置。
140
+
141
+ ## 配置(中间层)
142
+
143
+ 全部 MCP 经中间层访问(单池,**没有模式开关**):任何服务器都不产生模型可见的 `mcp__`
144
+ 直呼工具,统一经四个原子工具访问(两级发现,业界标准形态)——
145
+ `ws_mcp_list`(完整盘点当前工作空间全部服务器 + 每台完整工具清单,不受
146
+ `ws_mcp_search` 的 limit 截断;支持 `server` 全名/裸名过滤,`perServerLimit`
147
+ 每服务器工具条数上限默认 50 / 上限 500,超限置 `toolsTruncated`;空返回附明确
148
+ `message`,带 `server` 过滤 0 命中时 message 归因到过滤条件并列出可见项目级
149
+ 服务器)/ `ws_mcp_detail`(按 `@<root>/<server>` + tool 裸名精确查询单工具
150
+ 完整 `inputSchema`,错误三分:发现失败附原因 / 服务器未连接或未发现 / 工具
151
+ 不存在)/ `ws_mcp_search`(关键词检索,先搜后调,输出 `truncated` 标志提示结果是否因
152
+ limit 截断)/ `ws_mcp_call`(按 `@<root>/<server>` 全名调用,参数 schema 用
153
+ `ws_mcp_detail` 核对),执行时按调用方会话当前 cwd 路由到对应工作空间
154
+ 连接池,不同工作空间注入不同 MCP、无命名冲突;cwd 无项目时回落全局虚拟 root
155
+ `@global`,list/search/detail 恒合并查询「项目 root 单元 + `@global` 单元」,
156
+ call 放行 `@global` root(全局配置跨工作空间共享,语义成立)。宿主注册名形如
157
+ `mcp__<id>__<tool>`,`id` 不透明、以工具清单为准;它只作内部标识(模型工具列表里看不到),
158
+ 封装定义条目(`toolDefinitions`)只经 `ws_mcp_call` 按 `@<root>/<server>` 触达。
159
+ 注:全局服务器增删改后需重启或触发会话触达才刷新目录(既有行为)。
160
+
161
+ ### 顶层配置键(Config schema)
162
+
163
+ 顶层键(`packages/dsh-mcp-manager/src/server/config/config-schema.ts` 的 `Config`)默认值与语义:
164
+
165
+ | 键 | 默认值 | 语义 |
166
+ | --- | --- | --- |
167
+ | `enabled` | `true` | 是否启用本插件(插件级总开关)。 |
168
+ | `announceToAgent` | `true` | 是否向 Agent 宣告插件(能力清单由 `<available_mcp_servers>` 承担)。 |
169
+ | `storePath` | 留空(默认 `<DSH_HOME>/dsh-mcp-manager/mcp.json`) | 全局服务器配置路径,留空用默认路径。 |
170
+ | `announceCatalog` | `true` | 是否注入 MCP 能力目录(`<available_mcp_servers>`)。 |
171
+ | `catalogMaxEntries` | `6` | 目录注入条目上限。 |
172
+ | `debug.callStats` | `false` | 是否开启调用统计调试与落盘(默认关闭,仅可通过配置文件开启;详见下节“调用统计与 Debug 模式”)。 |
173
+ | `debug.statsFile` | 留空(默认 `<DSH_HOME>/dsh-mcp-manager/stats.json`) | 统计落盘路径,留空使用默认路径。 |
174
+ | `ui` | 见“配置(浮窗位置)”节(`position` 默认 `top-right`;`offset.x` / `offset.y` 默认 `8`,`blankY` 默认 `40`;`zIndexBase` 默认 `10`,clamp 到 1–9000) | 浮窗位置与层级配置,详见“配置(浮窗位置)”节。 |
175
+
176
+ **已废除的配置键**(#767 笔 2):`middleware`(`off` / `project` / `all` 三档模式)与
177
+ `middlewarePolicy`(`allowTools` / `denyTools` 策略)。设置页的模式下拉已删除;旧配置里写了
178
+ 这两个键**不报错也不生效**(键被原样带过、没有任何消费者),本插件也不会改写用户的配置文件。
179
+ 工具级禁用是唯一的准入裁决。
180
+
181
+ **已退役的实现**:S1-5c 自研连接栈退役(`runtime/supervisor.ts`、`runtime/reconnect.ts` 等四文件整体退役,连接改走官方引擎);W11b2a `src/types` 与 `src/integration` 删除(无迁移动作)。
182
+
183
+ ### 工具级禁用(浮窗)
184
+
185
+ - 服务器卡片的「工具(N)」折叠区展开后为 **checkbox 列表**,逐个启停,点击即
186
+ 经 `PATCH /api/dsh-mcp/tool-disable` 持久化(落盘 `<DSH_HOME>/dsh-mcp-manager/user-state.json`
187
+ 的 `disabledTools`,合并写盘、重启保留);
188
+ - 语义:**项目级与全局级服务器的工具都可禁用**(单池后两类都经中间层;全局记录以
189
+ `@global` 为 key 跨工作空间共享);默认全部启用;
190
+ - 工具级禁用**独立于服务器级 enabled 开关**(服务器级复活不清工具级状态);
191
+ - **作用于 mcp-manager 管辖的全部 MCP 工具**(mcp__ 前缀直呼与中间层 ws_mcp_*
192
+ 一致生效,runtime 封装工具同样受控);插件侧自行声明的纪律裸名工具
193
+ 不受影响;
194
+ - 超长工具名(>64 字符哈希后缀)不可逆 → 按未知 server 处理,不禁用/不误禁;
195
+ - 浮窗与管理面板的「项目级」「全局级」分组**都渲染工具开关**(单池后两类都经中间层,
196
+ 全局组的开关同样生效);
197
+ - 浮窗与管理面板均按「项目级 / 全局级」两大分组展示(各自内部再按连接状态);
198
+ - 全名形态 `@@global/<name>` 或 `@<绝对路径>/<name>`(与宿主 `parseFullServerName`
199
+ 归一化一致);宿主重启后 `projectRoot` 暂缺时客户端防御性跳过提交(不发送非法
200
+ `@/name`,C6);浮窗与管理面板的连接 / 断开 / 重连 / 启停操作携带当前会话 cwd,
201
+ 宿主重启场景可自愈恢复会话(C7)。
202
+
203
+ ## 路由(全部 loopback 围栏)
204
+
205
+ | 路由 | 说明 |
206
+ | --- | --- |
207
+ | `/api/dsh-mcp/health` | 健康检查(注意与目录名不同) |
208
+ | `/api/dsh-mcp/tool-disable` | 工具级禁用开关(PATCH,loopback-only) |
209
+ | `/api/dsh-mcp/*` | 服务器管理 / 连接控制 / 工具清单 / SSE 事件等 |
210
+
211
+ ## 运行时注入(registerServer.toolDefinitions)
212
+
213
+ 其他插件可经 `ctx.mcpManager.registerServer` 运行时注册 MCP 服务器(内存态不落盘,
214
+ 同名幂等)。注册入参支持可选 `toolDefinitions`(调用方封装工具定义,`ToolDefinition[]`,
215
+ 工具名用**裸名**):
216
+
217
+ - **有 `toolDefinitions`**:该服务器工具**全部用封装定义注册**——execute 来自调用方
218
+ (调用方可先做预处理再内部转发底层命令),跳过远端 schema 投影与
219
+ 通用 callTool,底层真实实现不外泄;
220
+ - **没有**:维持现状(远端 schema + 通用 callTool),其他服务器零影响;
221
+ - **模型不可见 `mcp__` 直呼工具:只经 `ws_mcp_call` 用裸名调用**(`@<root>/<server>`
222
+ + 裸名;封装的 execute 是调用方 JS,没有远端实现可直呼)。调用名派生仍走
223
+ `publicToolName`(64 字符 / 哈希后缀规则不变),但它只作为中间层 callTool 的转发名;
224
+ - **工具级禁用 / 可见性 / 能力目录对封装工具照常生效**(按服务器 + 工具名判定,与
225
+ `mcp__` 前缀工具同口径);
226
+ - 仅运行时注入面(runtimeRegistry)消费,不随 store 落盘、不随 mcpServers 导入透传。
227
+
228
+ ```ts
229
+ await ctx.mcpManager.registerServer({
230
+ name: "my-mcp",
231
+ transport: "stdio",
232
+ command: "my-mcp-server",
233
+ args: ["serve", "--mcp"],
234
+ toolDefinitions: [
235
+ {
236
+ name: "my_tool", // 裸名
237
+ description: "调用方自定义的封装工具",
238
+ parameters: { type: "object", properties: { query: { type: "string" } }, required: ["query"] },
239
+ output: { schema: { ... }, render(args, value) { ... } },
240
+ execute: async (args) => { await prepare(); return forwarded; }, // 内部转发,不外泄
241
+ },
242
+ ],
243
+ });
244
+ ```
245
+
246
+ ### 会话加载与工作区开关
247
+
248
+ MCP 连接检查在应用启动后于后台预热全局配置及官方工作区列表中的项目;配置编辑保存或来源文件变化时更新相应连接。切换会话只读取对应工作区的缓存快照,不等待 MCP 连接、发现或重试,也不重新检查已预热的连接。应用启动后新添加的工作区会在后台首次准备。
249
+
250
+ 全局 MCP 的连接由应用共享,但启用开关按工作区持久化:在 A 工作区关闭不会影响 B 工作区。该开关同时约束界面、目录注入、搜索、详情和工具执行。快速切换时使用目标工作区的快照,尚无缓存时暂不显示计数;旧工作区的迟到响应不会覆盖当前界面。
251
+
252
+ ## 数据与安全
253
+
254
+ - 服务器配置:`<DSH_HOME>/dsh-mcp-manager/mcp.json`(仅存 `${ENV}` 引用,**不落盘密钥本身**);
255
+ 落盘 0600 权限 + 同目录临时文件原子替换;Windows 上替换遇到 `EPERM` / `EBUSY` 时会有界异步重试,重试期间检测到外部修改则中止以保留外部内容
256
+ - 所有 `/api/dsh-mcp/*` 路由仅限 loopback 访问(非回环 403 / 方法错 405)
257
+ - **stdio 子进程环境净化(官方 dsh-mcp-client 口径)**:净化只作用于**继承的父环境**——
258
+ 凭据词根(`KEY` / `PASSWORD` / `SECRET` / `TOKEN`)与全部 `DSH_*` 变量从父环境摘掉,
259
+ 避免把宿主机密隐式透传给 MCP 子进程;**用户在配置里显式声明的 `env` 原样传给子进程**
260
+ (显式层在净化之后合并)——`env` 不是脱敏面,要隔离就别往里写凭据
261
+ - **stdio 子进程继承宿主权限**:MCP 服务器命令在宿主进程权限下执行,
262
+ 仅配置可信的服务器。信任边界:同进程插件注入(`ctx.mcpManager.registerServer`)
263
+ 与宿主同权限、不构成提权;**随仓库提交的项目级 `mcp.json` 才是需要你审慎对待的那一面**
264
+ - **统计只落元数据**:debug 统计(`debug.callStats`)记录调用次数/时长/成败与渐进式披露
265
+ 漏斗;**搜索词只以 SHA-256 哈希桶落盘**(`h:<12 位 hex>`,空查询为 `<empty>`),旧版本
266
+ 落的明文键在读回时丢弃(丢弃发生在**读回那一刻**,下次落盘即不再写回;若统计此后无活动,
267
+ 旧明文键会留到下一次有活动为止)。哈希是**假名化不是匿名**:搜索词熵低,仍有字典攻击面。
268
+ 漏斗的另两维仍落明文:`ws_mcp_list` 的 server 过滤项、`ws_mcp_detail` 的 server/tool——
269
+ 它们是服务器与工具名,本就在配置面与目录面里,不是自由文本
270
+ - **MCP 工具在真实服务器上执行,先确认再操作**;工具结果原样返回,
271
+ 可能含敏感信息;工具描述/结果按不可信输入对待
272
+ - **注入信任分级**:远端工具描述/结果为不可信输入,仅展示与传参,不作指令执行;本地配置与用户显式操作为可信
273
+ - **工作空间隔离(中间层)**:路由以调用方会话当前 cwd 为唯一输入;server
274
+ 全名一致性校验(参数声明的 root ≠ 路由 root → 拒绝)防跨空间串台;
275
+ 工具级禁用表按 `@<root>/<server>` 全名或裸名裁决(全名优先;`@global` 记录跨工作空间共享)
276
+ - **中间层工具只读边界**:`ws_mcp_list` / `ws_mcp_detail` / `ws_mcp_search` 不执行远端
277
+ 工具,但**首次触达某工作空间时会创建连接单元并触发后台建连**(不等同于纯本地读);`ws_mcp_call`
278
+ 是唯一执行远端工具的入口,并受工具级禁用表约束;`ws_mcp_call` 错误消息按
279
+ 「显式 + 下一步」规范给出(确认 server 连接 / 用 `ws_mcp_detail` 核对参数 /
280
+ 检查工具级禁用状态)
281
+ - **禁直呼是机器强制的(#1014)**:`mcp__<id>__<tool>` 是内部注册名,pre-execute guard
282
+ **默认拒绝**一切非我方转发的 `mcp__` 直呼——不再依赖模型遵守提示词,也不依赖声明面遮蔽
283
+ (连接翻转期遮蔽必有泄漏窗口)。唯一放行位是宿主赋予的**飞行中** token:本包
284
+ `ws_mcp_call` → dispatch → `ctx.tools.execute` 的子调用凭 `parent` 放行,结算即摘除,
285
+ 同一 token 重放会被拒。拒绝文案指路 `ws_mcp_call` 并写明不要重试本次调用。
286
+ - **工具级禁用(三入口一致)**:`ws_mcp_call`(callTool 查禁用表)、
287
+ pre-execute guard(`mcp__` 前缀直呼工具)、插件侧声明的纪律裸名工具
288
+ 统一走 `isToolDenied` 裁决;禁用只作用于 `mcp__` 前缀工具,拒绝原因附语义声明;
289
+ 禁用记录 `<DSH_HOME>/dsh-mcp-manager/user-state.json` 的 `disabledTools`(`@global` key
290
+ 跨工作空间共享,合并写盘不整表覆盖)
291
+ - **凭据脱敏**:目录摘要与错误路径经 redactor 把 env/headers/URL 用户信息
292
+ (username/password/searchParams)等凭据形状替换为 `[REDACTED]`;URL 主机与
293
+ 路径无凭据部分保留可读(可诊断性,B8 口径);percent-encoding 的 raw 形态与
294
+ decoded 形态双注册,防编码绕过;supervisor/manager 错误日志与 HTTP body 同口径
295
+ 脱敏
296
+ - **调用统计与 Debug 模式(Metadata-Only)**:默认关闭;启用后把 MCP 调用指标与渐进式披露漏斗防抖原子持久化至 `<DSH_HOME>/dsh-mcp-manager/stats.json`,且控制台输出单行跟踪;严格不持久化用户 arguments 与返回 content
297
+ - 能力目录注入含来源标注与“不代表当前连接状态”说明
298
+ - **能力目录 source**:`dsh-mcp-manager` 是 canonical row/settings 条目 id;目录消息的当前业务格式是 producer-owned V4:`{ kind: "plugin:dsh-mcp-manager", form: "snapshot", sections: [{ name: "mcp-catalog", text }] }`
299
+
300
+ <a id="升级与历史会话边界"></a>
301
+ ## 升级与历史会话边界
302
+
303
+ 当前写入与业务读取只认 producer-owned V4;本包不提供旧 V0/V2/V3 parser,也不把旧格式写成业务兼容。
304
+
305
+ 旧 `mcp-catalog` source 属于一次性维护责任。`scripts/maintenance/repair-mcp-catalog-sessions.mjs` 只把旧 source 元数据修为 V3 wrapper,保留消息正文与事件序列;它不写 V4,也不实现或伪造 v3→v4 迁移。修复后由目标 dsh(版本见 catalog)的官方迁移链依次恢复旧产物并转为 V4,当前 V4 产物不动。
306
+
307
+ ```sh
308
+ # 先停止 dsh web;默认预演,只列出受影响会话
309
+ node scripts/maintenance/repair-mcp-catalog-sessions.mjs
310
+
311
+ # 核对后落盘;自动备份,随后重启 dsh web
312
+ node scripts/maintenance/repair-mcp-catalog-sessions.mjs --apply
313
+ ```
314
+
315
+ 默认处理 v0/v1/v2 与 v3 中残留的旧 source;`--legacy-only` 只处理 v0/v1/v2。脚本幂等,可用 `--home` 或 `DSH_HOME` 指定目录、用 `--session <id>` 限定单个会话。
316
+
317
+ ## 验证
318
+
319
+ 测试单份维护、变异自动覆盖:单元测试只维护 `test/*.test.ts`(`import "../lib/index.js"` 测产物);stryker 经 lib→src hook 复用同一份断言,无需手工同步副本。
320
+
321
+ ```sh
322
+ # 健康检查(回环)
323
+ curl -s http://127.0.0.1:3080/api/dsh-mcp/health
324
+
325
+ # 源码在 src/,改后必须 build
326
+ pnpm --filter dsh-mcp-manager build
327
+ pnpm --filter dsh-mcp-manager test
328
+ ```
329
+
330
+ ## 已知限制
331
+
332
+ - **`mcp__` 注册名只作内部标识**:服务器由官方 dsh-mcp-client 装载,宿主注册名为
333
+ `mcp__<id>__<tool>`,`id` 是按 (工作空间, 服务器名) 分配的 **随机短串**(同一次插件装配内
334
+ 稳定;插件重载或宿主重启后变化;不透明,不能由服务器名推导)。这些名字会被从模型工具列表
335
+ 摘除,模型经 `ws_mcp_call` 转发触达——**不要在任何脚本或提示词里写死工具名**,
336
+ 一律用 `ws_mcp_list` / `ws_mcp_detail` 取名字
337
+ - 不订阅 MCP 的 `tools/list_changed` 通知(无 SSE 长连接);工具列表变化在
338
+ 重连 / 手动刷新时重新同步
339
+ - 中间层目录是「采集边界内的 last-good 快照」(单服务器 ≤512 工具 / ≤256KB 总量),
340
+ 发现失败时 list 透出 `unavailable` 原因
341
+ - 仅桥接工具能力;MCP 的 resources 与 prompts 尚无 harness 消费接口
342
+ - **多标签页各自绑定不同会话时,项目级 MCP 只能跟随一个会话**(issue #1028 未解决项):
343
+ 宿主 `projectRoot` 是单例,多个页签会互相覆盖,且每次切回前台的 `rebindSession` 会
344
+ 放大覆盖。本包不自行仲裁「哪个页签优先」。
345
+ - **读不到当前会话时保持既有绑定、不做清空**(#1028):官方会话快照就绪前、或该页签
346
+ 暂未被官方 `mainView` 持有时,本包判定为「未知」并**不**向宿主发送 `cwd:""`——未知
347
+ 不等于无项目,误清会造成面板只剩全局条目、项目级导入报
348
+ `no active project session`。告警口径:**首帧未知是官方快照尚未就绪的竞态
349
+ (每次冷启动必现),不告警**;只有「已解析过又读不到」或「连续多帧仍读不到」才打
350
+ 一次告警,以免正常态与异常态显示同一条黄警而丢掉判别价值。
351
+ - **切回前台的自动恢复是非强制的(#1120),不是用户显式强制重连**:复用官方管理机制的
352
+ 已存在状态投影与 per-root/server 在途去重,不以每次 visibilitychange 为由
353
+ dispose/restart;connected/connecting/reconnecting 保留现有代际与官方退避,
354
+ entry 缺失与真正失败走正常路径恢复,userDisabled 绝不复活。官方挂载层只提供
355
+ ready/disposed/工具注册面,**有工具注册的健康连接与半开连接无法实时区分**——自动恢复
356
+ 不声称已检测真实健康、不发自研 ping;半开仍可由用户显式重连恢复。resume 携带本次会话
357
+ cwd,服务端在本次调用中解析并固定 root(旧无 body 请求回落既有绑定,新请求明确无工作区
358
+ 即 `cwd:""` 固定 `@global`,不回落到别人的 projectRoot);客户端恢复节流按 cwd 分键覆盖
359
+ resume,不同 cwd 的恢复不互吞。
360
+ - 依赖 Node ≥ 20
361
+
362
+ ## 类型依赖
363
+
364
+ 宿主端与客户端类型均来自官方 `@deepseek-ai/*` 包(`cordis` / `dsh-host-webserver` /
365
+ `dsh-agent` / `dsh-tools` / `dsh-system-prompt` / `dsh-llm` / `dsh-client-ui-slots` /
366
+ `dsh-api-session-controller` / `dsh-client-ui-session`,版本统一锁在仓库
367
+ `pnpm-workspace.yaml` catalog,随 DSH 发布节奏升级):**仅 `import type` 编译期使用**,
368
+ 编译产物零官方运行时导入。包以 optional peerDependencies 声明这一宿主耦合;对插件做
369
+ 类型检查的消费者需可解析这些官方包(跳过类型检查则无影响)。
370
+
371
+ 客户端的「当前会话」读数经 `src/client/core/current-session.ts` 单一接缝,判据用官方
372
+ 口径 `retainedBy.mainView > 0` 并以官方 `SessionListState` / `SessionSummary` 类型锚定
373
+ (**不自建镜像类型**):DSH 0.1.7-rc.2 起会话列表快照已删除 `current` 字段,官方
374
+ `ISessions` 也不提供「当前会话」访问器,因此不再自造 `{current, byId}` 形状。
375
+
376
+ ## License
377
+
378
+ MIT
379
+
380
+ ## 0.3.0 变更摘要
381
+
382
+ - 包名去 scope:`@wingsky-1/dsh-mcp-manager` → `dsh-mcp-manager`(identity / 数据目录 / 文档全量同步)
383
+ - JSON 导入支持完整文件:自动解包 `{ "mcpServers": {...} }` 顶层包裹
384
+ - 服务器名允许内部空格(`SERVER_NAME_PATTERN` 放宽),`Figma AI Bridge` 类名字原生合法
385
+ - `/api/dsh-mcp/import/json` 新增 `{ path }` 导入:服务端直接读 mcp.json(支持 `~` 展开)
386
+ - Web 面板 Quick add 新增「从 mcp.json 文件导入」路径输入与按钮
@@ -0,0 +1,9 @@
1
+ # dsh-mcp-manager bundle patch:向 web profile 名册插入 MCP 管理器。
2
+ # 主机端(exports ".")在宿主进程运行,注入 tools / webServer / systemPrompt:
3
+ # 管理 <DSH_HOME>/dsh-mcp.json 中的 MCP 服务器(stdio / streamable-http),
4
+ # 把已连接服务器的工具注册为 mcp__<id>__<tool>(id 不透明,按 (工作空间, 服务器名) 分配,不可由服务器名推导),并提供 /api/dsh-mcp/* 路由;
5
+ # 浏览器端(exports "./client")提供侧边栏入口与分级面板。
6
+ # 配置走 schema 默认值(enabled / announceToAgent),行内不带 config。
7
+ - insert:
8
+ - id: dsh-mcp-manager
9
+ name: "dsh-mcp-manager"
@@ -0,0 +1,43 @@
1
+ THIRD-PARTY LICENSES
2
+ ===================
3
+
4
+ 本发布物遵循「运行时依赖 = 构建期内联」模型,将下列第三方库打包进产物
5
+ (随包分发的 vendored 裸二进制单列一段并标出来源);
6
+ 依其许可证条款随附许可文本与版权声明。
7
+ 生成:scripts/collect-licenses.ts(issue #13)。本仓库自身以 MIT 许可发布。
8
+
9
+
10
+ =====================================================================
11
+ cosmokit@1.8.1 — MIT
12
+ 来源:https://www.npmjs.com/package/cosmokit
13
+ =====================================================================
14
+
15
+ MIT License
16
+
17
+ Copyright (c) 2021-present Shigma
18
+
19
+ Permission is hereby granted, free of charge, to any person obtaining a copy
20
+ of this software and associated documentation files (the "Software"), to deal
21
+ in the Software without restriction, including without limitation the rights
22
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
23
+ copies of the Software, and to permit persons to whom the Software is
24
+ furnished to do so, subject to the following conditions:
25
+
26
+ The above copyright notice and this permission notice shall be included in all
27
+ copies or substantial portions of the Software.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
31
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
32
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
33
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
34
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35
+ SOFTWARE.
36
+
37
+
38
+ =====================================================================
39
+ schemastery@3.18.0 — MIT
40
+ 来源:https://www.npmjs.com/package/schemastery
41
+ =====================================================================
42
+
43
+ 上游 npm 包未附带 license 文件;以 package.json SPDX 声明为准(MIT)。
@@ -0,0 +1,42 @@
1
+ /**
2
+ * dsh-mcp-manager — 客户端 HTTP API 请求与请求参数拼装(core 层)。
3
+ *
4
+ * 阶段 7 分层:本文件拆出自原 dom.ts(dom.ts 保留 DOM 工具职责 el(),
5
+ * HTTP 请求职责独立成 api.ts),与宿主 ROUTES 的对接面收拢一处。
6
+ * 仅 export 纯函数,不依赖任何状态。
7
+ */
8
+ import type { ApiRequestOptions, McpState, McpServerListEntry } from "./state.js";
9
+ /**
10
+ * tool-disable 的服务器全名形态(C6/C-DTO-4):`@@global/<name>` 或
11
+ * `@<绝对路径>/<name>`,与宿主 parseFullServerName 归一化一致;projectRoot
12
+ * 缺失(宿主重启 #412)时返回 undefined——调用方必须跳过提交,不得拼非法
13
+ * `@/name`(宿主 parseFullServerName slash<=1 会 400 拒绝)。
14
+ */
15
+ export declare function toolDisableServerKey(server: McpServerListEntry, state: McpState): string | undefined;
16
+ /**
17
+ * 会话 cwd 查询参数(C7/#412 自愈):connect/reconnect/disable 等操作携带
18
+ * 当前会话 cwd,宿主 maybeSession 据此恢复会话(项目级连接需要;
19
+ * 宿主 setSession 幂等短路,正常时零副作用)。空 cwd 返回空串。
20
+ */
21
+ export declare function cwdQueryOf(state: McpState): string;
22
+ /**
23
+ * resume 请求体(#1120):本次会话 cwd 随请求固定服务端 root。
24
+ * - 未知会话(sessionResolved=false):回 undefined(不带 body,服务端回落既有绑定,
25
+ * 不把「读不到」变成「清空」);
26
+ * - 已知会话:恒带 { cwd }(空即 ""=明确无工作区,服务端固定 @global,
27
+ * 不回落到别人的 projectRoot)。
28
+ */
29
+ export declare function resumeBodyOf(state: McpState): {
30
+ cwd: string;
31
+ } | undefined;
32
+ /**
33
+ * HTTP API 请求。
34
+ * 返回 JSON 解析后的 body;非 2xx 抛 Error。
35
+ * 带默认超时(10s,AbortSignal),防挂起请求占用连接(#111 变更点驱动)。
36
+ * 调用方自带 signal 时:超时兜底不启用(调用方 signal 优先,避免双取消竞争)。
37
+ *
38
+ * C14 备忘:当前全部路由返回 JSON body;未来新增 204 无 body 路由时,
39
+ * response.json() 抛错会落到 body=undefined,调用方不得静默把 undefined
40
+ * 当成功结果消费(需在新增 204 路由时显式补状态码分支)。
41
+ */
42
+ export declare function api<T = unknown>(path: string, options?: ApiRequestOptions): Promise<T>;
@@ -0,0 +1,58 @@
1
+ /**
2
+ * dsh-mcp-manager — 客户端常量与状态映射。
3
+ *
4
+ * 状态排序、状态点颜色、API 路径等纯常量,不依赖任何状态。
5
+ * i18n(issue #348):状态文案存字典 key(title/STATUS_TEXT),渲染期经 t 求值
6
+ * (模块加载时 t 尚未装配,不能固化文案字符串)。
7
+ *
8
+ * 跨端契约(路径清单 / 六态状态键)的物理定义在 src/shared/,本文件只做客户端投影;
9
+ * 展示顺序、CSS 颜色与字典 key 是纯展示数据,留在原处(D5 单一事实源判据)。
10
+ */
11
+ import type { McpLocaleKey } from "../locales.js";
12
+ /** 路径表:逐键取宿主同一份 ROUTES(一致性锁 test/e2e/cross-end-lock.test.ts 盯这条)。 */
13
+ export declare const API: {
14
+ servers: string;
15
+ connect: string;
16
+ disconnect: string;
17
+ reconnect: string;
18
+ importJson: string;
19
+ sources: string;
20
+ sourceSave: string;
21
+ sourceActivate: string;
22
+ session: string;
23
+ resume: string;
24
+ config: string;
25
+ events: string;
26
+ health: string;
27
+ toolDisable: string;
28
+ };
29
+ /** 状态分组排序(按优先级降序;titleKey 为字典 key,渲染期 t(titleKey))。 */
30
+ export declare const STATUS_ORDER: ({
31
+ key: "connected";
32
+ titleKey: McpLocaleKey;
33
+ dot: string;
34
+ } | {
35
+ key: "connecting";
36
+ titleKey: McpLocaleKey;
37
+ dot: string;
38
+ } | {
39
+ key: "reconnecting";
40
+ titleKey: McpLocaleKey;
41
+ dot: string;
42
+ } | {
43
+ key: "stopped";
44
+ titleKey: McpLocaleKey;
45
+ dot: string;
46
+ } | {
47
+ key: "disabled";
48
+ titleKey: McpLocaleKey;
49
+ dot: string;
50
+ } | {
51
+ key: "failed";
52
+ titleKey: McpLocaleKey;
53
+ dot: string;
54
+ })[];
55
+ /** 状态 → 字典 key 映射(渲染期 t(STATUS_TEXT[status]);未知状态回落原始 key 显示)。 */
56
+ export declare const STATUS_TEXT: Record<string, McpLocaleKey>;
57
+ /** 状态点颜色(与 STATUS_ORDER 一致)。 */
58
+ export declare function statusDot(status: string): string;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * dsh-mcp-manager — 当前会话读取(唯一接缝,issue #1028)。
3
+ *
4
+ * 0.1.7-rc.2 起官方会话列表快照不再有 `current` 字段(`SessionListState` 现为
5
+ * `{ ids, byId, phase, projectionsBySession }`)。旧实现读 `snapshot.current` 恒得
6
+ * undefined → `currentCwd` 恒空 → 切回前台的 `rebindSession` 把「未知」序列化成
7
+ * `cwd:""` 上报 → 宿主 `setSession("")` 主动清空 projectRoot/projectStore → 面板只剩
8
+ * 全局条目、项目级操作抛 `no active project session`。
9
+ *
10
+ * 官方自己判定「当前会话」的口径是 `retainedBy.mainView > 0`(写入方是
11
+ * dsh-client-ui-workspace 的 `retain(target,{source:"mainView"})`,读取方遍布
12
+ * dsh-client-ui-session / ui-workspace / ui-layout 等官方包)。本接缝照该口径读,
13
+ * 并把「读不到」与「读到但无 cwd」**分成两态**返回——这是 #1028 的核心教训:
14
+ * - unknown:读不到当前会话(服务未就绪 / 快照不可读 / 无 main-view 行)。
15
+ * 调用方**不得**据此清空宿主绑定,否则把「不知道」变成「破坏」。
16
+ * - session:读到了。cwd 为空即「已知无项目」(blank 会话),此时才可显式清空。
17
+ */
18
+ import type { ISessions, SessionSummary } from "@deepseek-ai/dsh-api-session-controller/client";
19
+ /**
20
+ * 会话列表读面:从官方 `ISessions["list"]` 派生,只取本包用到的两个成员。
21
+ * 不重抄签名——官方 `ObservableSnapshot` 的 `getSnapshot` 必返快照、不带 undefined,
22
+ * 旧实现那个 `| undefined` 与 `getSnapshot?` 的 optional 都是自建镜像的产物。
23
+ */
24
+ export type SessionListFace = Pick<ISessions["list"], "getSnapshot" | "subscribe">;
25
+ /** 当前会话读数(两态;与宿主 isBlankCwd 的两态不在同一层,不要混用)。 */
26
+ export type CurrentSessionRead = {
27
+ readonly kind: "unknown";
28
+ } | {
29
+ readonly kind: "session";
30
+ readonly row: SessionSummary;
31
+ /** 会话工作目录;空串与 undefined 同义(宿主侧都归「无项目」)。 */
32
+ readonly cwd: string | undefined;
33
+ readonly blank: boolean;
34
+ };
35
+ /**
36
+ * 读当前会话。服务未注入 / list 缺失 / getSnapshot 不可用或抛错 / 快照不可读 /
37
+ * 无 main-view 行,一律回 unknown——不抛、不猜、不用启发式顶替。
38
+ */
39
+ export declare function readCurrentSession(list: SessionListFace | undefined): CurrentSessionRead;
@@ -0,0 +1,19 @@
1
+ /**
2
+ * dsh-mcp-manager — 客户端 DOM 工具函数(core 层)。
3
+ *
4
+ * 阶段 7 分层:HTTP API 请求已拆出至 ./api.ts(拆出自原 dom.ts——dom.ts
5
+ * 保留 DOM 元素创建职责,api.ts 收 HTTP 请求职责)。
6
+ * 仅 export 纯函数,不依赖任何状态。
7
+ */
8
+ /**
9
+ * 盘古之白:CJK 与拉丁字母/数字之间自动插入半角空格。
10
+ * 用于状态摘要等中英混排文案(不要对纯标识符/服务器名调用)。
11
+ * 覆盖面说明:仅 CJK 统一表意文字(U+3400–U+4DBF、U+4E00–U+9FFF)与兼容区
12
+ * (U+F900–U+FAFF),假名/谚文/扩展 B+ 不在范围内——状态文案均为中文标点+
13
+ * 拉丁数字/括号,该范围已够用;如需扩面先补单测再放宽。
14
+ * 连字符说明:类内不得出现裸 `-`(旧写法 `㐀-鿿-鿿` 被解析为字面连字符,
15
+ * 会把 `project-1` 撕成 `project- 1`——连字符标识符必须保持原样)。
16
+ */
17
+ export declare function pangu(text: string): string;
18
+ /** 创建带属性/子节点的 DOM 元素(泛型按标签名收窄返回)。 */
19
+ export declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, attrs?: Record<string, unknown>, children?: unknown[]): HTMLElementTagNameMap[K];
@@ -0,0 +1,12 @@
1
+ /**
2
+ * dsh-mcp-manager — 客户端 i18n 渲染辅助(core 层)。
3
+ *
4
+ * 阶段 7 分层:本文件拆出自 locales.ts(字典数据与 McpLocaleKey 类型留在
5
+ * 根目录 locales.ts 供 LocaleNamespaceMap 声明合并;渲染期文案求值辅助收
6
+ * 到本文件,与状态映射 constants.ts 协作)。
7
+ */
8
+ /**
9
+ * 状态文案求值:已知状态取字典翻译,未知状态回落原始 key 原样显示
10
+ * (C13:未知状态按 stopped 投影、不丢卡——文案层同样不丢原文案)。
11
+ */
12
+ export declare function tStatus(status: string): string;