dsh-mcp-connector 0.2.7 → 0.2.8
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 +25 -1
- package/README.md +1 -1
- package/docs/MARKET-REGISTRATION.md +18 -10
- package/lib/index.js +17 -53
- package/lib/mcp-http.js +173 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,28 @@
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.2.8] - 2026-08-22
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- 工具详情改为执行完整的 Streamable HTTP MCP 会话流程:`initialize` 后保存 `Mcp-Session-Id`,发送 `notifications/initialized`,再携带会话、协议版本和凭据请求 `tools/list`,修复 QVeris 等有状态 MCP Server 返回 HTTP 400 的问题。
|
|
12
|
+
- 会话结束后尽力发送 `DELETE` 释放服务端资源;鉴权失败、限流、HTTP/协议错误继续按类型更新连接健康状态。
|
|
13
|
+
|
|
14
|
+
### Registry
|
|
15
|
+
|
|
16
|
+
- 将 QVeris 工具快照校正为托管端实际返回的 8 个工具;移除当前运行时不存在的 `probe`,补充 3 个兼容旧客户端的弃用别名。
|
|
17
|
+
- QVeris 精选 Prompt 仅使用实际可用的 `discover`、`inspect` 和用量审计工具;未经用户明确确认仍不执行可能消耗 Credits 的 `call`/`execute_tool`。
|
|
18
|
+
|
|
19
|
+
### Documentation
|
|
20
|
+
|
|
21
|
+
- 统一 QVerisMCP 品牌名称,记录官方 Logo 因 `same-origin` 策略需由 Registry 自托管的 Desktop 兼容方案。
|
|
22
|
+
- 将已于 `0.1.0`–`0.2.0` 完成的 v2 详情页实施计划标记为已完成/归档,避免与当前待办混淆。
|
|
23
|
+
|
|
24
|
+
### Verification
|
|
25
|
+
|
|
26
|
+
- 69 项自动测试、lint 与 44 个 npm 发布文件白名单/敏感内容扫描通过。
|
|
27
|
+
- 使用 DSH 本机已保存的 QVeris API Key 完成真实只读验收:协议版本 `2025-03-26`、有状态会话建立成功、`tools/list` 返回 8 个工具;未执行任何付费能力调用。
|
|
28
|
+
|
|
7
29
|
## [0.2.7] - 2026-08-22
|
|
8
30
|
|
|
9
31
|
### Added
|
|
@@ -20,6 +42,7 @@
|
|
|
20
42
|
|
|
21
43
|
- 自动化门禁通过 69 项测试与 43 个 npm 发布文件白名单/敏感内容扫描。
|
|
22
44
|
- QVeris Hosted MCP 无凭据公网探针返回预期的 HTTP 401,确认端点可达且正确要求 Bearer Key;未进行付费 `call`。
|
|
45
|
+
- DSH Desktop `web` profile 已精确对齐 `dsh-mcp-connector@0.2.7`;完全重启后左侧入口、中文单语界面、组合筛选和 8 张市场卡片通过,19 条连接和 4 组授权保持不变。
|
|
23
46
|
|
|
24
47
|
## [0.2.6] - 2026-08-21
|
|
25
48
|
|
|
@@ -164,7 +187,8 @@
|
|
|
164
187
|
- 外部 URL 与导入 Header 执行安全校验。
|
|
165
188
|
- iframe 消息校验同源和消息来源。
|
|
166
189
|
|
|
167
|
-
[Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.
|
|
190
|
+
[Unreleased]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.8...HEAD
|
|
191
|
+
[0.2.8]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.7...v0.2.8
|
|
168
192
|
[0.2.7]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.6...v0.2.7
|
|
169
193
|
[0.2.6]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.5...v0.2.6
|
|
170
194
|
[0.2.5]: https://github.com/duhu2000/dsh-mcp-connector/compare/v0.2.4...v0.2.5
|
package/README.md
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
- 平滑迁移:显式扫描并复制两个旧企查查 OAuth 插件授权;不删除原插件或原凭据。
|
|
29
29
|
- 对话工具:`mcp_connector_catalog`、`connect`、`configure`、`import_json`、`install_from_url`、`status`、`health_check`、`set_enabled`、`disconnect`、`refresh_catalog`、`publish`、`tools_list`。
|
|
30
30
|
|
|
31
|
-
随包目录前 4 张为企查查连接器,另含“北大法宝·法律检索”和“Wind·股票数据”。远程 Registry 刷新后还会加入“盈米·基金投顾”和“
|
|
31
|
+
随包目录前 4 张为企查查连接器,另含“北大法宝·法律检索”和“Wind·股票数据”。远程 Registry 刷新后还会加入“盈米·基金投顾”和“QVerisMCP”,当前共 8 张已发布市场卡片;插件架构不限定厂商。
|
|
32
32
|
|
|
33
33
|
## 界面与演示
|
|
34
34
|
|
|
@@ -117,26 +117,34 @@ Bearer/API Key 型连接器可在卡片上点「配置」,一次填写凭据
|
|
|
117
117
|
|
|
118
118
|
- https://aifinmarket.wind.com.cn/#/market?tab=mcps&detailType=mcp&detailId=wind_stock_data-0
|
|
119
119
|
|
|
120
|
-
## 8.
|
|
120
|
+
## 8. QVerisMCP 适配结论
|
|
121
121
|
|
|
122
122
|
QVeris Hosted MCP 提供单一 Streamable HTTP 端点 `https://mcp.qveris.ai/mcp`,
|
|
123
123
|
通过 `Authorization: Bearer <QVERIS_API_KEY>` 鉴权,与本插件现有的 Bearer
|
|
124
124
|
凭据表单、持久化前 `initialize` 校验和 Streamable HTTP 传输完全兼容。
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
2026-08-22 使用真实 API Key 完成只读 `tools/list` 验收,QVeris 托管端实际返回
|
|
127
|
+
8 个 MCP 工具:`discover`、`inspect`、`call`、`usage_history`、
|
|
128
|
+
`credits_ledger`,以及 3 个兼容旧客户端的弃用别名 `search_tools`、
|
|
129
|
+
`get_tools_by_ids`、`execute_tool`。当前运行时没有官网文档所列的 `probe`;
|
|
130
|
+
市场快照以实际端点为准。官方宣传的上万项能力是经 `discover` 找到的下游能力,
|
|
131
|
+
不写成上万个 MCP 工具。
|
|
129
132
|
|
|
130
133
|
由于 `call` 可能消耗 Credits,且查询内容可能由第三方服务商处理,
|
|
131
134
|
该卡片保持 `featured: false`,并执行以下产品约束:
|
|
132
135
|
|
|
133
|
-
- Prompt
|
|
134
|
-
-
|
|
136
|
+
- Prompt 默认只执行 `discover`/`inspect` 和用量审计工具;
|
|
137
|
+
- 未经用户明确确认,不执行可能消耗 Credits 的 `call` 或弃用别名 `execute_tool`;
|
|
135
138
|
- 卡片明确提醒用户不要提交未获授权的个人信息、商业秘密或敏感业务数据;
|
|
136
|
-
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
`
|
|
139
|
+
- 市场使用用户指定的 QVeris 官方 Logo;由于官网原图返回
|
|
140
|
+
`Cross-Origin-Resource-Policy: same-origin`,在 DSH Desktop 中直链会被浏览器拦截,
|
|
141
|
+
Registry 因此保留官方原图像素并自托管于
|
|
142
|
+
`assets/qveris-logo.png`,对外提供可跨域嵌入的 Raw GitHub URL。
|
|
143
|
+
|
|
144
|
+
公共无凭据探针已确认端点可达并正确返回 HTTP 401;使用 DSH 本机自有 API Key
|
|
145
|
+
执行完整 `initialize → notifications/initialized → tools/list` 后,服务返回
|
|
146
|
+
`Mcp-Session-Id`、协议版本 `2025-03-26` 和 8 个工具。验收未执行 `call` 或
|
|
147
|
+
`execute_tool`,没有产生付费能力调用。
|
|
140
148
|
|
|
141
149
|
参考:
|
|
142
150
|
|
package/lib/index.js
CHANGED
|
@@ -24,8 +24,9 @@ import { oauthAuthorize } from './connectors/oauth-connector.js';
|
|
|
24
24
|
import { buildManualRecord } from './connectors/manual-connector.js';
|
|
25
25
|
import { normalizeJsonImport } from './connectors/json-connector.js';
|
|
26
26
|
import { discoverServerMetadata, refreshAccessToken, revokeRefreshToken } from './oauth.js';
|
|
27
|
-
import { provision, disable, remove, entryIdFor
|
|
27
|
+
import { provision, disable, remove, entryIdFor } from './mcp-provision.js';
|
|
28
28
|
import { classifyConnectionError, validateConnectionRecords } from './mcp-validation.js';
|
|
29
|
+
import { listMcpTools, McpHttpError } from './mcp-http.js';
|
|
29
30
|
import { registerTools } from './tools.js';
|
|
30
31
|
import { mountWebRoutes } from './web.js';
|
|
31
32
|
import { assertSafeUrl } from './util.js';
|
|
@@ -793,70 +794,33 @@ export async function apply(ctx, config) {
|
|
|
793
794
|
|
|
794
795
|
const servers = [];
|
|
795
796
|
for (const record of records) {
|
|
796
|
-
const headers = {
|
|
797
|
-
'Content-Type': 'application/json',
|
|
798
|
-
'Accept': 'application/json, text/event-stream',
|
|
799
|
-
...authHeaders(record, grantMap()),
|
|
800
|
-
};
|
|
801
|
-
|
|
802
797
|
try {
|
|
803
|
-
const
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
body: JSON.stringify({
|
|
807
|
-
jsonrpc: '2.0',
|
|
808
|
-
id: 1,
|
|
809
|
-
method: 'tools/list',
|
|
810
|
-
params: {},
|
|
811
|
-
}),
|
|
812
|
-
signal: AbortSignal.timeout(config.requestTimeoutMs),
|
|
798
|
+
const listed = await listMcpTools(record, {
|
|
799
|
+
timeoutMs: config.requestTimeoutMs,
|
|
800
|
+
grants: grantMap(),
|
|
813
801
|
});
|
|
814
|
-
|
|
815
|
-
if (!response.ok) {
|
|
816
|
-
const error = response.status === 401 || response.status === 403
|
|
817
|
-
? `凭据无效、已过期或权限不足(HTTP ${response.status})`
|
|
818
|
-
: `HTTP ${response.status}`;
|
|
819
|
-
servers.push({
|
|
820
|
-
serverKey: record.serverKey || record.name,
|
|
821
|
-
serverName: record.serverName,
|
|
822
|
-
ok: false,
|
|
823
|
-
error,
|
|
824
|
-
errorKind: response.status === 401 || response.status === 403 ? 'auth' : 'http',
|
|
825
|
-
tools: [],
|
|
826
|
-
});
|
|
827
|
-
continue;
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
const contentType = response.headers.get('content-type') || '';
|
|
831
|
-
let result;
|
|
832
|
-
if (contentType.includes('text/event-stream')) {
|
|
833
|
-
// Parse SSE response
|
|
834
|
-
const text = await response.text();
|
|
835
|
-
const lines = text.split('\n');
|
|
836
|
-
for (const line of lines) {
|
|
837
|
-
if (line.startsWith('data: ')) {
|
|
838
|
-
try {
|
|
839
|
-
result = JSON.parse(line.slice(6));
|
|
840
|
-
break;
|
|
841
|
-
} catch {}
|
|
842
|
-
}
|
|
843
|
-
}
|
|
844
|
-
} else {
|
|
845
|
-
result = await response.json();
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
const tools = result?.result?.tools ?? [];
|
|
849
802
|
servers.push({
|
|
850
803
|
serverKey: record.serverKey || record.name,
|
|
851
804
|
serverName: record.serverName,
|
|
852
805
|
ok: true,
|
|
853
|
-
tools: tools.map((t) => ({
|
|
806
|
+
tools: listed.tools.map((t) => ({
|
|
854
807
|
name: t.name,
|
|
855
808
|
title: t.title || t.name,
|
|
856
809
|
description: t.description || '',
|
|
857
810
|
})),
|
|
858
811
|
});
|
|
859
812
|
} catch (error) {
|
|
813
|
+
if (error instanceof McpHttpError) {
|
|
814
|
+
servers.push({
|
|
815
|
+
serverKey: record.serverKey || record.name,
|
|
816
|
+
serverName: record.serverName,
|
|
817
|
+
ok: false,
|
|
818
|
+
error: error.message,
|
|
819
|
+
errorKind: error.kind,
|
|
820
|
+
tools: [],
|
|
821
|
+
});
|
|
822
|
+
continue;
|
|
823
|
+
}
|
|
860
824
|
const classified = classifyConnectionError(error);
|
|
861
825
|
servers.push({ serverKey: record.serverKey || record.name, serverName: record.serverName, ok: false, error: classified.message, errorKind: classified.kind, tools: [] });
|
|
862
826
|
}
|
package/lib/mcp-http.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Streamable HTTP MCP 会话客户端。
|
|
3
|
+
*
|
|
4
|
+
* 详情页不能直接向有状态的 MCP Server 发送 tools/list:必须先
|
|
5
|
+
* initialize,保留响应的 Mcp-Session-Id,发送 notifications/initialized,
|
|
6
|
+
* 再在后续每个请求中携带会话头和凭据。
|
|
7
|
+
*/
|
|
8
|
+
import { MCP_PROTOCOL_VERSION } from './constants.js';
|
|
9
|
+
import { authHeaders } from './mcp-provision.js';
|
|
10
|
+
|
|
11
|
+
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
12
|
+
|
|
13
|
+
export class McpHttpError extends Error {
|
|
14
|
+
constructor(message, { kind = 'protocol', status } = {}) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'McpHttpError';
|
|
17
|
+
this.kind = kind;
|
|
18
|
+
this.status = status;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function readLimitedText(response, maxBytes = MAX_RESPONSE_BYTES) {
|
|
23
|
+
const declared = Number(response.headers.get('content-length'));
|
|
24
|
+
if (Number.isFinite(declared) && declared > maxBytes) throw new McpHttpError('MCP 响应过大');
|
|
25
|
+
if (!response.body) return '';
|
|
26
|
+
const reader = response.body.getReader();
|
|
27
|
+
const chunks = [];
|
|
28
|
+
let total = 0;
|
|
29
|
+
for (;;) {
|
|
30
|
+
const { done, value } = await reader.read();
|
|
31
|
+
if (done) break;
|
|
32
|
+
total += value.byteLength;
|
|
33
|
+
if (total > maxBytes) {
|
|
34
|
+
await reader.cancel().catch(() => {});
|
|
35
|
+
throw new McpHttpError('MCP 响应过大');
|
|
36
|
+
}
|
|
37
|
+
chunks.push(value);
|
|
38
|
+
}
|
|
39
|
+
const bytes = new Uint8Array(total);
|
|
40
|
+
let offset = 0;
|
|
41
|
+
for (const chunk of chunks) {
|
|
42
|
+
bytes.set(chunk, offset);
|
|
43
|
+
offset += chunk.byteLength;
|
|
44
|
+
}
|
|
45
|
+
return new TextDecoder().decode(bytes);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function parseMcpPayload(text, contentType = '') {
|
|
49
|
+
if (contentType.includes('text/event-stream')) {
|
|
50
|
+
for (const line of text.split(/\r?\n/)) {
|
|
51
|
+
if (!line.startsWith('data:')) continue;
|
|
52
|
+
try { return JSON.parse(line.slice(5).trim()); } catch {}
|
|
53
|
+
}
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
try { return JSON.parse(text); } catch { return undefined; }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function responseError(response, payload, text) {
|
|
60
|
+
const rawMessage = String(payload?.error?.message ?? text ?? '').replace(/\s+/g, ' ').trim().slice(0, 180);
|
|
61
|
+
if (response.status === 401 || response.status === 403) {
|
|
62
|
+
return new McpHttpError(`凭据无效、已过期或权限不足(HTTP ${response.status})`, { kind: 'auth', status: response.status });
|
|
63
|
+
}
|
|
64
|
+
if (response.status === 429) {
|
|
65
|
+
return new McpHttpError('服务请求过于频繁(HTTP 429),请稍后重试', { kind: 'rate-limit', status: response.status });
|
|
66
|
+
}
|
|
67
|
+
const suffix = rawMessage ? `:${rawMessage}` : '';
|
|
68
|
+
return new McpHttpError(`MCP 请求失败(HTTP ${response.status})${suffix}`, { kind: 'http', status: response.status });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function payloadError(payload) {
|
|
72
|
+
if (!payload?.error) return null;
|
|
73
|
+
const rawMessage = String(payload.error.message ?? '').replace(/\s+/g, ' ').slice(0, 180);
|
|
74
|
+
const kind = /unauthori[sz]ed|forbidden|invalid.?token|invalid.?key|credential|access.?denied|未授权|无权|密钥|令牌/i.test(rawMessage)
|
|
75
|
+
? 'auth'
|
|
76
|
+
: 'protocol';
|
|
77
|
+
return new McpHttpError(`MCP 返回错误${rawMessage ? `:${rawMessage}` : ''}`, { kind });
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function requestHeaders(record, grants, { sessionId, protocolVersion } = {}) {
|
|
81
|
+
return {
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
Accept: 'application/json, text/event-stream',
|
|
84
|
+
...authHeaders(record, grants),
|
|
85
|
+
...(sessionId ? { 'Mcp-Session-Id': sessionId } : {}),
|
|
86
|
+
...(protocolVersion ? { 'MCP-Protocol-Version': protocolVersion } : {}),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function post(record, payload, { grants, sessionId, protocolVersion, signal, fetchImpl }) {
|
|
91
|
+
const response = await fetchImpl(record.url, {
|
|
92
|
+
method: 'POST',
|
|
93
|
+
headers: requestHeaders(record, grants, { sessionId, protocolVersion }),
|
|
94
|
+
body: JSON.stringify(payload),
|
|
95
|
+
signal,
|
|
96
|
+
redirect: 'follow',
|
|
97
|
+
});
|
|
98
|
+
const text = await readLimitedText(response);
|
|
99
|
+
const parsed = parseMcpPayload(text, response.headers.get('content-type') ?? '');
|
|
100
|
+
return { response, text, payload: parsed };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async function closeSession(record, { grants, sessionId, protocolVersion, fetchImpl }) {
|
|
104
|
+
if (!sessionId) return;
|
|
105
|
+
try {
|
|
106
|
+
const response = await fetchImpl(record.url, {
|
|
107
|
+
method: 'DELETE',
|
|
108
|
+
headers: requestHeaders(record, grants, { sessionId, protocolVersion }),
|
|
109
|
+
redirect: 'follow',
|
|
110
|
+
signal: AbortSignal.timeout(3_000),
|
|
111
|
+
});
|
|
112
|
+
await response.body?.cancel().catch(() => {});
|
|
113
|
+
} catch {}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export async function listMcpTools(record, {
|
|
117
|
+
timeoutMs = 15_000,
|
|
118
|
+
fetchImpl = fetch,
|
|
119
|
+
grants = new Map(),
|
|
120
|
+
} = {}) {
|
|
121
|
+
if (record.transport && record.transport !== 'streamable-http') {
|
|
122
|
+
throw new McpHttpError(`动态工具加载暂不支持 ${record.transport} 传输`, { kind: 'protocol' });
|
|
123
|
+
}
|
|
124
|
+
const controller = new AbortController();
|
|
125
|
+
const timer = setTimeout(() => controller.abort(new Error('timeout')), timeoutMs);
|
|
126
|
+
let sessionId = '';
|
|
127
|
+
let protocolVersion = MCP_PROTOCOL_VERSION;
|
|
128
|
+
try {
|
|
129
|
+
const initialized = await post(record, {
|
|
130
|
+
jsonrpc: '2.0',
|
|
131
|
+
id: 1,
|
|
132
|
+
method: 'initialize',
|
|
133
|
+
params: {
|
|
134
|
+
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
135
|
+
capabilities: {},
|
|
136
|
+
clientInfo: { name: 'dsh-mcp-connector', version: '1.0' },
|
|
137
|
+
},
|
|
138
|
+
}, { grants, signal: controller.signal, fetchImpl });
|
|
139
|
+
if (!initialized.response.ok) throw responseError(initialized.response, initialized.payload, initialized.text);
|
|
140
|
+
const initPayloadError = payloadError(initialized.payload);
|
|
141
|
+
if (initPayloadError) throw initPayloadError;
|
|
142
|
+
if (!initialized.payload?.result || typeof initialized.payload.result !== 'object') {
|
|
143
|
+
throw new McpHttpError('MCP Server 未返回有效的 initialize 结果');
|
|
144
|
+
}
|
|
145
|
+
protocolVersion = initialized.payload.result.protocolVersion || MCP_PROTOCOL_VERSION;
|
|
146
|
+
sessionId = initialized.response.headers.get('mcp-session-id') ?? '';
|
|
147
|
+
|
|
148
|
+
const notification = await post(record, {
|
|
149
|
+
jsonrpc: '2.0',
|
|
150
|
+
method: 'notifications/initialized',
|
|
151
|
+
params: {},
|
|
152
|
+
}, { grants, sessionId, protocolVersion, signal: controller.signal, fetchImpl });
|
|
153
|
+
if (notification.response.status === 401 || notification.response.status === 403) {
|
|
154
|
+
throw responseError(notification.response, notification.payload, notification.text);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const listed = await post(record, {
|
|
158
|
+
jsonrpc: '2.0',
|
|
159
|
+
id: 2,
|
|
160
|
+
method: 'tools/list',
|
|
161
|
+
params: {},
|
|
162
|
+
}, { grants, sessionId, protocolVersion, signal: controller.signal, fetchImpl });
|
|
163
|
+
if (!listed.response.ok) throw responseError(listed.response, listed.payload, listed.text);
|
|
164
|
+
const listPayloadError = payloadError(listed.payload);
|
|
165
|
+
if (listPayloadError) throw listPayloadError;
|
|
166
|
+
const tools = listed.payload?.result?.tools;
|
|
167
|
+
if (!Array.isArray(tools)) throw new McpHttpError('MCP tools/list 未返回工具数组');
|
|
168
|
+
return { tools, protocolVersion, sessionful: Boolean(sessionId) };
|
|
169
|
+
} finally {
|
|
170
|
+
clearTimeout(timer);
|
|
171
|
+
await closeSession(record, { grants, sessionId, protocolVersion, fetchImpl });
|
|
172
|
+
}
|
|
173
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mcp-connector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
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",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
],
|
|
32
32
|
"scripts": {
|
|
33
33
|
"test": "node --test",
|
|
34
|
-
"lint": "node --check lib/index.js && node --check lib/web.js && node --check lib/client.js && node --check lib/schema.js && node --check lib/catalog.js && node --check lib/prompts.js && node --check lib/probe.js && node --check lib/mcp-validation.js && node --check lib/migration.js && node --check lib/stores.js && node --check lib/oauth.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",
|
|
34
|
+
"lint": "node --check lib/index.js && node --check lib/web.js && node --check lib/client.js && node --check lib/schema.js && node --check lib/catalog.js && node --check lib/prompts.js && node --check lib/probe.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/oauth.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",
|
|
35
35
|
"registry:build": "node scripts/build-registry.mjs",
|
|
36
36
|
"registry:validate": "node scripts/probe-connector.mjs catalog/catalog.json --validate-only",
|
|
37
37
|
"dev:ui": "node scripts/ui-harness.mjs",
|