dsh-mcp-connector 0.2.60 → 0.2.61
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 +6 -0
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/lib/probe.js +56 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.en.md
CHANGED
|
@@ -198,7 +198,7 @@ npm run dev:ui
|
|
|
198
198
|
|
|
199
199
|
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.
|
|
200
200
|
|
|
201
|
-
The current public version is [`dsh-mcp-connector@0.2.
|
|
201
|
+
The current public version is [`dsh-mcp-connector@0.2.61`](https://www.npmjs.com/package/dsh-mcp-connector), with [GitHub Release v0.2.61](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.61).
|
|
202
202
|
|
|
203
203
|
See [CHANGELOG.md](CHANGELOG.md) for version history and [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md) for the Desktop release checklist.
|
|
204
204
|
|
package/README.md
CHANGED
|
@@ -193,7 +193,7 @@ npm run dev:ui
|
|
|
193
193
|
|
|
194
194
|
公共 Registry 每次合并后会生成 `catalog-stats.json`;本仓库的定时工作流每小时同步中英文介绍和统计快照。npm 页面中的静态正文随版本发布更新,上方动态统计徽标则直接读取 Registry,可在不发布新 npm 版本时保持实时数量一致。
|
|
195
195
|
|
|
196
|
-
当前公开版本为 [`dsh-mcp-connector@0.2.
|
|
196
|
+
当前公开版本为 [`dsh-mcp-connector@0.2.61`](https://www.npmjs.com/package/dsh-mcp-connector),对应 [GitHub Release v0.2.61](https://github.com/duhu2000/dsh-mcp-connector/releases/tag/v0.2.61)。
|
|
197
197
|
|
|
198
198
|
版本能力与变更记录见 [CHANGELOG.md](CHANGELOG.md)。
|
|
199
199
|
Desktop 发版回归见 [docs/DESKTOP-E2E.md](docs/DESKTOP-E2E.md)。
|
package/lib/probe.js
CHANGED
|
@@ -29,6 +29,51 @@ function parseMcpPayload(text, contentType) {
|
|
|
29
29
|
try { return JSON.parse(text); } catch { return undefined; }
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
function probeErrorChain(error) {
|
|
33
|
+
const entries = [];
|
|
34
|
+
let current = error;
|
|
35
|
+
for (let depth = 0; current && depth < 8; depth += 1) {
|
|
36
|
+
entries.push({
|
|
37
|
+
code: typeof current.code === 'string' ? current.code.toUpperCase() : '',
|
|
38
|
+
name: typeof current.name === 'string' ? current.name : '',
|
|
39
|
+
message: typeof current.message === 'string' ? current.message : '',
|
|
40
|
+
});
|
|
41
|
+
current = current.cause;
|
|
42
|
+
}
|
|
43
|
+
return entries;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 将 fetch/undici 的嵌套错误转换为不包含端点参数或凭据的稳定诊断。
|
|
48
|
+
* 健康报告只公开错误类别和允许列表内的系统错误码。
|
|
49
|
+
*/
|
|
50
|
+
export function classifyProbeError(error) {
|
|
51
|
+
const entries = probeErrorChain(error);
|
|
52
|
+
const text = entries.flatMap((entry) => [entry.code, entry.name, entry.message]).join(' ');
|
|
53
|
+
const code = entries.map((entry) => entry.code).find((value) => [
|
|
54
|
+
'ENOTFOUND', 'EAI_AGAIN', 'ETIMEDOUT', 'ECONNRESET', 'ECONNREFUSED',
|
|
55
|
+
'CERT_HAS_EXPIRED', 'DEPTH_ZERO_SELF_SIGNED_CERT', 'SELF_SIGNED_CERT_IN_CHAIN',
|
|
56
|
+
'UNABLE_TO_VERIFY_LEAF_SIGNATURE', 'ERR_TLS_CERT_ALTNAME_INVALID',
|
|
57
|
+
].includes(value));
|
|
58
|
+
|
|
59
|
+
if (/AbortError|timeout|timed out|ETIMEDOUT/i.test(text)) {
|
|
60
|
+
return { kind: 'timeout', ...(code ? { code } : {}), message: code ? `Request timed out (${code})` : 'Request timed out' };
|
|
61
|
+
}
|
|
62
|
+
if (/ENOTFOUND|EAI_AGAIN|getaddrinfo/i.test(text)) {
|
|
63
|
+
return { kind: 'dns', ...(code ? { code } : {}), message: code ? `DNS lookup failed (${code})` : 'DNS lookup failed' };
|
|
64
|
+
}
|
|
65
|
+
if (/CERT_|certificate|self signed|ERR_TLS|TLS|SSL/i.test(text)) {
|
|
66
|
+
return { kind: 'tls', ...(code ? { code } : {}), message: code ? `TLS validation failed (${code})` : 'TLS validation failed' };
|
|
67
|
+
}
|
|
68
|
+
if (/ECONNRESET|socket disconnected|connection reset/i.test(text)) {
|
|
69
|
+
return { kind: 'connection-reset', ...(code ? { code } : {}), message: code ? `Connection reset (${code})` : 'Connection reset' };
|
|
70
|
+
}
|
|
71
|
+
if (/ECONNREFUSED/i.test(text)) {
|
|
72
|
+
return { kind: 'connection-refused', ...(code ? { code } : {}), message: code ? `Connection refused (${code})` : 'Connection refused' };
|
|
73
|
+
}
|
|
74
|
+
return { kind: 'network', message: 'Network request failed' };
|
|
75
|
+
}
|
|
76
|
+
|
|
32
77
|
async function probeServer(server, authMode, timeoutMs) {
|
|
33
78
|
const startedAt = Date.now();
|
|
34
79
|
if (server.transport === 'stdio') {
|
|
@@ -76,7 +121,10 @@ async function probeServer(server, authMode, timeoutMs) {
|
|
|
76
121
|
|| payload?.jsonrpc === '2.0' || !!payload?.result?.protocolVersion || !!payload?.error;
|
|
77
122
|
if (payload?.result?.tools) result.tools = payload.result.tools;
|
|
78
123
|
} catch (error) {
|
|
79
|
-
|
|
124
|
+
const diagnostic = classifyProbeError(error);
|
|
125
|
+
result.error = diagnostic.message;
|
|
126
|
+
result.errorKind = diagnostic.kind;
|
|
127
|
+
if (diagnostic.code) result.errorCode = diagnostic.code;
|
|
80
128
|
}
|
|
81
129
|
|
|
82
130
|
if (authMode === 'oauth2-pkce' && result.reachable) {
|
|
@@ -114,7 +162,13 @@ async function probeIcon(icon, timeoutMs) {
|
|
|
114
162
|
}
|
|
115
163
|
return { ok: response.ok, status: response.status };
|
|
116
164
|
} catch (error) {
|
|
117
|
-
|
|
165
|
+
const diagnostic = classifyProbeError(error);
|
|
166
|
+
return {
|
|
167
|
+
ok: false,
|
|
168
|
+
error: diagnostic.message,
|
|
169
|
+
errorKind: diagnostic.kind,
|
|
170
|
+
...(diagnostic.code ? { errorCode: diagnostic.code } : {}),
|
|
171
|
+
};
|
|
118
172
|
}
|
|
119
173
|
}
|
|
120
174
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mcp-connector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.61",
|
|
4
4
|
"description": "DeepSeek Harness MCP Connector: connect servers, search tools across active connections, and troubleshoot discovery. Includes a continuously updated catalog; supports OAuth 2.0 PKCE, API keys, Streamable HTTP/stdio, and mcpServers JSON import.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|