dsh-mcp-connector 0.2.18 → 0.2.19

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 CHANGED
@@ -4,6 +4,22 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.19] - 2026-08-24
8
+
9
+ ### Fixed
10
+
11
+ - 所有对话工具结果在交给 DSH Host 前统一转换为 lossless JSON,清理 `undefined`、非有限数字、`BigInt`、稀疏数组和循环引用,修复 Windows DSH Desktop 的 `value is not lossless JSON` 错误。
12
+ - UI 静态文件路由不再使用平台相关的 `path.normalize` 处理 URL,Windows 下保持正斜杠语义并继续拒绝路径穿越,修复市场 iframe 返回 404。
13
+
14
+ ### Documentation
15
+
16
+ - 中英文 README 更新为公共 Registry 61 条、与 4 张随包卡片合并后 65 张市场卡片的当前规模;重新采集市场总览并重建 16 秒演示 GIF。
17
+
18
+ ### Verification
19
+
20
+ - 插件 94 项自动测试、lint、npm 发布文件白名单/敏感内容扫描和 `git diff --check` 通过。
21
+ - 手动执行最新 Registry `main` 的 61 项健康巡检:60 项通过、1 项部分通过;44 个远程 MCP Server 全部可达并识别成功,28 个 stdio Server 按安全策略未执行本地命令。
22
+
7
23
  ## [0.2.18] - 2026-08-24
8
24
 
9
25
  ### Added
@@ -315,7 +331,8 @@
315
331
  - 外部 URL 与导入 Header 执行安全校验。
316
332
  - iframe 消息校验同源和消息来源。
317
333
 
318
- [Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.18...HEAD
334
+ [Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.19...HEAD
335
+ [0.2.19]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.18...v0.2.19
319
336
  [0.2.18]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.17...v0.2.18
320
337
  [0.2.17]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.16...v0.2.17
321
338
  [0.2.16]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.15...v0.2.16
package/README.en.md CHANGED
@@ -28,7 +28,7 @@ Browse and install MCP connectors from different providers in DeepSeek Harness D
28
28
  - A standalone remote Registry, allowing new marketplace cards to appear after refresh without publishing a new npm version.
29
29
  - Explicit, non-destructive migration of authorization from the two earlier Qichacha OAuth plugins.
30
30
 
31
- The first four bundled cards are Qichacha connectors, followed by PKULaw and Wind. After a remote Registry refresh, Yingmi, QVeris, Bazhuayu Cloud Collection, GitHub, Cloudflare, Notion, Tavily, and the Ace Data Cloud-hosted Seedream connector are also available, for 14 published marketplace cards after deduplication. Recommendations are limited to the four Qichacha cards, PKULaw, and Wind; all other connectors remain discoverable in their business categories.
31
+ As of August 24, 2026, the public Registry publishes 61 connector descriptors. After merging and deduplicating them with the four bundled Qichacha cards, the Marketplace exposes 65 cards across nine business categories. Recommendations remain limited to the four Qichacha cards, PKULaw, and Wind, for six featured cards in total. The Registry can evolve independently, so the badge shown after a client refresh is the authoritative current count.
32
32
 
33
33
  ## Interface and demo
34
34
 
@@ -105,7 +105,7 @@ npm run dev:ui
105
105
 
106
106
  `npm run check` performs syntax checks, automated tests, and an npm package allowlist/sensitive-content audit. `npm run market:check` tracks the external DSH marketplace PR and live directory. Tags matching `v*` trigger GitHub Actions; the tag must match `package.json`. npm releases use Trusted Publishing through GitHub OIDC and do not require a long-lived `NPM_TOKEN`.
107
107
 
108
- The current public version is [`dsh-mcp-connector@0.2.18`](https://www.npmjs.com/package/dsh-mcp-connector), with [GitHub Release v0.2.18](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.18).
108
+ The current public version is [`dsh-mcp-connector@0.2.19`](https://www.npmjs.com/package/dsh-mcp-connector), with [GitHub Release v0.2.19](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.19).
109
109
 
110
110
  See [CHANGELOG.md](CHANGELOG.md) for version history and [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md) for the Desktop release checklist.
111
111
 
package/README.md CHANGED
@@ -30,7 +30,7 @@
30
30
  - 平滑迁移:显式扫描并复制两个旧企查查 OAuth 插件授权;不删除原插件或原凭据。
31
31
  - 对话工具:`mcp_connector_catalog`、`connect`、`configure`、`import_json`、`install_from_url`、`status`、`health_check`、`set_enabled`、`disconnect`、`refresh_catalog`、`publish`、`tools_list`。
32
32
 
33
- 随包目录前 4 张为企查查连接器,另含“北大法宝·法律检索”和“Wind·股票数据”。远程 Registry 刷新后还会加入“盈米·基金投顾”、“QVerisMCP”、“八爪鱼·云采集”、GitHub、Cloudflare、Notion、Tavily 和由 Ace Data Cloud 托管的 Seedream,合并去重后当前共 14 张已发布市场卡片。推荐位严格保留 4 张企查查卡片、北大法宝和 Wind;其他连接器按业务分类展示。
33
+ 截至 2026-08-24,公共 Registry 已发布 61 条连接器描述;与随包的 4 张企查查卡片合并去重后,市场页可浏览 65 张卡片,覆盖企业数据、金融投资、法律合规、开发工具、办公协作、调研分析、设计创意、效率工具和其他 9 类。推荐位严格保留 4 张企查查卡片、北大法宝和 Wind,共 6 张;其他连接器按业务分类展示。Registry 可独立持续更新,实际数量以客户端刷新后的市场页签徽标为准。
34
34
 
35
35
  ## 界面与演示
36
36
 
@@ -100,7 +100,7 @@ npm run dev:ui
100
100
 
101
101
  `check` 执行语法检查、自动测试和 npm 发布包白名单校验;`market:check` 检查外部 DSH 市场 PR 与线上目录;`dev:ui` 启动不含真实凭据的本地 mock 市场。CI 使用 `--legacy-peer-deps` 安装显式测试依赖,DSH 运行期 peer 仍由 Host 提供。`v*` Tag 会触发 GitHub Actions;Tag 必须与 `package.json` 版本一致。Release 通过 npm Trusted Publishing (GitHub OIDC) 发布,不依赖长期 `NPM_TOKEN`。
102
102
 
103
- 当前公开版本为 [`dsh-mcp-connector@0.2.18`](https://www.npmjs.com/package/dsh-mcp-connector),对应 [GitHub Release v0.2.18](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.18)。
103
+ 当前公开版本为 [`dsh-mcp-connector@0.2.19`](https://www.npmjs.com/package/dsh-mcp-connector),对应 [GitHub Release v0.2.19](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.19)。
104
104
 
105
105
  版本能力与变更记录见 [CHANGELOG.md](CHANGELOG.md)。
106
106
  Desktop 发版回归见 [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md)。
package/lib/tools.js CHANGED
@@ -61,9 +61,46 @@ const statusOutput = {
61
61
 
62
62
  const noArgs = { type: 'object', properties: {}, additionalProperties: false };
63
63
 
64
+ /**
65
+ * DSH tools require a lossless JSON value at the execute boundary. Normalize
66
+ * values that JSON.stringify would otherwise drop or rewrite, and always emit
67
+ * plain objects so transport-specific undefined fields cannot reject a tool
68
+ * result on stricter Desktop hosts.
69
+ */
70
+ export function toLossless(value, seen = new Set()) {
71
+ if (value === null) return null;
72
+ const type = typeof value;
73
+ if (type === 'string' || type === 'boolean') return value;
74
+ if (type === 'number') {
75
+ if (!Number.isFinite(value)) return null;
76
+ return Object.is(value, -0) ? 0 : value;
77
+ }
78
+ if (type === 'undefined' || type === 'function' || type === 'symbol' || type === 'bigint') return null;
79
+ if (type !== 'object' || seen.has(value)) return null;
80
+
81
+ seen.add(value);
82
+ let output;
83
+ if (Array.isArray(value)) {
84
+ output = [];
85
+ for (let index = 0; index < value.length; index += 1) {
86
+ output[index] = Object.hasOwn(value, index) ? toLossless(value[index], seen) : null;
87
+ }
88
+ } else {
89
+ output = {};
90
+ for (const key of Object.keys(value)) output[key] = toLossless(value[key], seen);
91
+ }
92
+ seen.delete(value);
93
+ return output;
94
+ }
95
+
64
96
  export function registerTools(ctx, api) {
65
97
  const disposers = [];
66
- const reg = (def) => disposers.push(ctx.tools.register(def));
98
+ const reg = (def) => disposers.push(ctx.tools.register({
99
+ ...def,
100
+ async execute(args, exec) {
101
+ return toLossless(await def.execute(args, exec));
102
+ },
103
+ }));
67
104
 
68
105
  reg({
69
106
  name: 'mcp_connector_catalog',
package/lib/web.js CHANGED
@@ -9,7 +9,7 @@
9
9
  * 本模块只依赖 ctx.webServer / ctx.webRuntime;在非 web 部署(无这两个服务)时
10
10
  * 调用方应跳过挂载,保证插件仍可用于纯对话工具场景。
11
11
  */
12
- import { dirname, join, normalize, relative, resolve } from 'node:path';
12
+ import { dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
13
13
  import { readFile } from 'node:fs/promises';
14
14
  import { fileURLToPath } from 'node:url';
15
15
 
@@ -131,20 +131,26 @@ function extOf(pathname) {
131
131
  }
132
132
 
133
133
  /** 把 URL pathname 安全地映射到 ui 目录内的文件(防目录穿越)。 */
134
- function resolveUiFile(pathname) {
135
- let rel;
134
+ export function splitUiPath(pathname) {
135
+ let decoded;
136
136
  try {
137
- rel = decodeURIComponent(pathname);
137
+ decoded = decodeURIComponent(pathname);
138
138
  } catch {
139
- return { ok: false };
139
+ return undefined;
140
140
  }
141
- rel = normalize(rel.replace(/\\/g, '/')).replace(/^\/+/, '');
142
- if (rel === '.' || rel === '') return { ok: true, path: join(UI_DIR, 'index.html'), rel: 'index.html' };
143
- if (rel.startsWith('..')) return { ok: false };
144
- const abs = resolve(UI_DIR, rel);
141
+ const segments = decoded.replace(/\\/g, '/').split('/').filter((segment) => segment !== '' && segment !== '.');
142
+ if (segments.includes('..')) return undefined;
143
+ return segments;
144
+ }
145
+
146
+ export function resolveUiFile(pathname) {
147
+ const segments = splitUiPath(pathname);
148
+ if (segments === undefined) return { ok: false };
149
+ if (segments.length === 0) return { ok: true, path: join(UI_DIR, 'index.html'), rel: 'index.html' };
150
+ const abs = resolve(UI_DIR, ...segments);
145
151
  const relAbs = relative(UI_DIR, abs);
146
- if (relAbs.startsWith('..') || relAbs === '') return { ok: false };
147
- return { ok: true, path: abs, rel: relAbs };
152
+ if (relAbs === '..' || relAbs.startsWith(`..${sep}`) || isAbsolute(relAbs) || relAbs === '') return { ok: false };
153
+ return { ok: true, path: abs, rel: segments.join('/') };
148
154
  }
149
155
 
150
156
  /* ───────────────────────── 路由挂载 ───────────────────────── */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mcp-connector",
3
- "version": "0.2.18",
3
+ "version": "0.2.19",
4
4
  "description": "General-purpose MCP connector, connection manager, plugin extension, and integration marketplace for DeepSeek Harness, initiated and maintained by Qichacha/QCC.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",