dsh-mcp-connector 0.2.9 → 0.2.10

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,12 @@
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.2.10] - 2026-08-22
8
+
9
+ ### Fixed
10
+
11
+ - 工具发现遇到瞬时网络断开或 MCP 5xx 时自动重试一次;鉴权、协议、4xx 和超时仍直接返回,减少 QVeris 等远程服务偶发 TLS reset 导致的连接状态误报。
12
+
7
13
  ## [0.2.9] - 2026-08-22
8
14
 
9
15
  ### Added
@@ -194,7 +200,8 @@
194
200
  - 外部 URL 与导入 Header 执行安全校验。
195
201
  - iframe 消息校验同源和消息来源。
196
202
 
197
- [Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.9...HEAD
203
+ [Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.10...HEAD
204
+ [0.2.10]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.9...v0.2.10
198
205
  [0.2.9]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.8...v0.2.9
199
206
  [0.2.8]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.7...v0.2.8
200
207
  [0.2.7]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.6...v0.2.7
package/lib/mcp-http.js CHANGED
@@ -115,7 +115,7 @@ async function closeSession(record, { grants, sessionId, protocolVersion, fetchI
115
115
  } catch {}
116
116
  }
117
117
 
118
- export async function listMcpTools(record, {
118
+ async function listMcpToolsOnce(record, {
119
119
  timeoutMs = 15_000,
120
120
  fetchImpl = fetch,
121
121
  grants = new Map(),
@@ -192,3 +192,44 @@ export async function listMcpTools(record, {
192
192
  await closeSession(record, { grants, sessionId, protocolVersion, fetchImpl });
193
193
  }
194
194
  }
195
+
196
+ function errorChain(error) {
197
+ const parts = [];
198
+ let current = error;
199
+ for (let depth = 0; current && depth < 4; depth += 1) {
200
+ parts.push(current.code, current.name, current.message);
201
+ current = current.cause;
202
+ }
203
+ return parts.filter(Boolean).join(' ');
204
+ }
205
+
206
+ function isRetryableDiscoveryError(error) {
207
+ if (error instanceof McpHttpError) {
208
+ return error.kind === 'http' && Number(error.status) >= 500;
209
+ }
210
+ const text = errorChain(error);
211
+ if (/AbortError|timeout|timed out|ETIMEDOUT/i.test(text)) return false;
212
+ return /ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|fetch failed|socket disconnected|connection reset|network error/i.test(text);
213
+ }
214
+
215
+ /**
216
+ * 获取完整工具目录。瞬时网络错误或 5xx 最多自动重试一次;鉴权、协议、
217
+ * 4xx 和超时不会重试,避免掩盖无效凭据或延长确定性失败。
218
+ */
219
+ export async function listMcpTools(record, options = {}) {
220
+ const retryCount = Math.max(0, Math.min(Number(options.retryCount ?? 1), 2));
221
+ const retryDelayMs = Math.max(0, Math.min(Number(options.retryDelayMs ?? 250), 2_000));
222
+ const requestOptions = { ...options };
223
+ delete requestOptions.retryCount;
224
+ delete requestOptions.retryDelayMs;
225
+
226
+ for (let attempt = 0; ; attempt += 1) {
227
+ try {
228
+ const result = await listMcpToolsOnce(record, requestOptions);
229
+ return { ...result, attempts: attempt + 1 };
230
+ } catch (error) {
231
+ if (attempt >= retryCount || !isRetryableDiscoveryError(error)) throw error;
232
+ if (retryDelayMs > 0) await new Promise((resolve) => setTimeout(resolve, retryDelayMs));
233
+ }
234
+ }
235
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mcp-connector",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
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",