dsh-mcp 1.8.0 → 1.9.0
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.en.md +6 -0
- package/CHANGELOG.md +6 -0
- package/lib/index.js +10 -0
- package/lib/mcp-client.js +21 -4
- package/package.json +1 -1
package/CHANGELOG.en.md
CHANGED
|
@@ -9,6 +9,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [1.9.0] - 2026-08-28
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Tool-list stability (better prompt-cache hits)**: tool schemas are canonicalized (recursive key sorting) before registration, so servers reordering schema keys no longer triggers dispose/re-register churn; MCP tools in the system prompt are rendered in stable name order, so the same tool set renders byte-identically no matter the hot-set or `tools/list` order
|
|
17
|
+
|
|
12
18
|
## [1.8.0] - 2026-08-27
|
|
13
19
|
|
|
14
20
|
### Added
|
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,12 @@
|
|
|
9
9
|
|
|
10
10
|
## [Unreleased]
|
|
11
11
|
|
|
12
|
+
## [1.9.0] - 2026-08-28
|
|
13
|
+
|
|
14
|
+
### 新增
|
|
15
|
+
|
|
16
|
+
- **工具列表稳定化增强(提升 prompt cache 命中)**:注册前对工具 schema 做规范化(递归排序键),服务器返回的键顺序变化不再导致工具被误判为变化而注销重注册;系统提示词中 MCP 工具按名称稳定排序,同一工具集合的渲染文本恒定——热注入集(search 模式每次调用都会变动)与服务器 `tools/list` 顺序不再影响提示词稳定性
|
|
17
|
+
|
|
12
18
|
## [1.8.0] - 2026-08-27
|
|
13
19
|
|
|
14
20
|
### 新增
|
package/lib/index.js
CHANGED
|
@@ -1182,6 +1182,16 @@ let McpManagerService = (() => {
|
|
|
1182
1182
|
});
|
|
1183
1183
|
}
|
|
1184
1184
|
assembly.tools = kept;
|
|
1185
|
+
// Canonical tool order: render MCP tools sorted by name so the
|
|
1186
|
+
// system prompt stays byte-stable for the same tool set no
|
|
1187
|
+
// matter the registration or hot-set order (hot tools move on
|
|
1188
|
+
// every call, and servers may reorder tools/list) — stable
|
|
1189
|
+
// output is what preserves prompt-cache hits.
|
|
1190
|
+
const mcpKept = [];
|
|
1191
|
+
const otherKept = [];
|
|
1192
|
+
for (const tool of assembly.tools) (tool.name.startsWith("mcp__") ? mcpKept : otherKept).push(tool);
|
|
1193
|
+
mcpKept.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
|
|
1194
|
+
assembly.tools = [...otherKept, ...mcpKept];
|
|
1185
1195
|
return next();
|
|
1186
1196
|
});
|
|
1187
1197
|
this.ctx.on("tools/result", (exec) => {
|
package/lib/mcp-client.js
CHANGED
|
@@ -205,9 +205,22 @@ function toolPublicEqual(a, b) {
|
|
|
205
205
|
if (!jsonEqual(a.parameters, b.parameters)) return false;
|
|
206
206
|
return jsonEqual(a.output && a.output.schema, b.output && b.output.schema);
|
|
207
207
|
}
|
|
208
|
-
/**
|
|
208
|
+
/**
|
|
209
|
+
* Recursively sort object keys so semantically identical JSON compares equal
|
|
210
|
+
* regardless of key order (servers often reorder schema keys between lists).
|
|
211
|
+
*/
|
|
212
|
+
function canonicalize(value) {
|
|
213
|
+
if (Array.isArray(value)) return value.map(canonicalize);
|
|
214
|
+
if (value !== null && typeof value === "object") {
|
|
215
|
+
const out = {};
|
|
216
|
+
for (const key of Object.keys(value).sort()) out[key] = canonicalize(value[key]);
|
|
217
|
+
return out;
|
|
218
|
+
}
|
|
219
|
+
return value;
|
|
220
|
+
}
|
|
221
|
+
/** Deep equality of JSON-serializable values, ignoring object key order. */
|
|
209
222
|
function jsonEqual(a, b) {
|
|
210
|
-
return JSON.stringify(a ?? null) === JSON.stringify(b ?? null);
|
|
223
|
+
return JSON.stringify(canonicalize(a ?? null)) === JSON.stringify(canonicalize(b ?? null));
|
|
211
224
|
}
|
|
212
225
|
/** Keep a supported advertised schema; unsupported MCP vocabulary falls back to JsonValue. */
|
|
213
226
|
function supportedOutputSchema(candidate) {
|
|
@@ -225,7 +238,11 @@ function createDefinition(client, ctx, publicName, rawName, description, paramet
|
|
|
225
238
|
return {
|
|
226
239
|
name: publicName,
|
|
227
240
|
description,
|
|
228
|
-
|
|
241
|
+
// Canonicalize before registration: servers often return JSON Schema
|
|
242
|
+
// with unstable key ordering; sorting keys keeps the model-visible tool
|
|
243
|
+
// list byte-stable across re-syncs and reconnects, which is what
|
|
244
|
+
// preserves prompt-cache hits.
|
|
245
|
+
parameters: canonicalize(parameters),
|
|
229
246
|
output: createOutput(rawName, structuredSchema),
|
|
230
247
|
execute: createExecutor(client, ctx, rawName, taskRequired, opts, projections),
|
|
231
248
|
finalizeContent(exec, result) {
|
|
@@ -249,7 +266,7 @@ function createOutput(rawName, structuredSchema) {
|
|
|
249
266
|
type: "array",
|
|
250
267
|
items: {}
|
|
251
268
|
},
|
|
252
|
-
structuredContent: structuredSchema ?? {}
|
|
269
|
+
structuredContent: canonicalize(structuredSchema ?? {})
|
|
253
270
|
},
|
|
254
271
|
required: structuredSchema === void 0 ? ["content"] : ["content", "structuredContent"],
|
|
255
272
|
additionalProperties: false
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"description": "MCP 管理界面 + tool search:可视化配置/启停/刷新 MCP 服务器与工具勾选,按需检索(tool search)热注入;工具列表稳定命中缓存、不撑爆上下文。DeepSeek Harness plugin: MCP management UI + tool search — stable tool list, cache-friendly, no context bloat.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|