@deepseek-ai/dsh-mcp-client 0.1.3-alpha.2 → 0.1.5-alpha.2

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/mcp/mcp-client/README.md
5
- README.md: 19e0d46f54ae1f67dc3361d9694ce5b8fb348e4e
6
- README.zh.md: a89245cd272cdb5c0f7c405b196a7e8b51ec9238
5
+ README.md: de646256888f1c271ad94a4c863338dfb02551e6
6
+ README.zh.md: 2c71060ec309e823ff3456207881e27ab9aca553
package/README.md CHANGED
@@ -9,7 +9,7 @@ English | [中文](README.zh.md)
9
9
 
10
10
  ## Summary
11
11
 
12
- `dsh-mcp-client` attaches external Model Context Protocol (MCP) servers to the harness so their tools work like any native tool. With one configuration entry per server, the model can call that server's tools — a filesystem, GitHub, database, or memory server — under stable names such as `mcp__github__create_issue`. Add it when the model should work with an external tool server; nothing ships enabled, so you opt in. The main cost is the tokens those tool definitions add to every request, and a slow or crashed server can delay startup or leave its tools failing until it recovers. Only tools are bridged: MCP resources and prompts are not supported.
12
+ `dsh-mcp-client` lets the model call tools from external Model Context Protocol (MCP) servers as native harness tools. Configure one server per entry, and its tools appear under stable names such as `mcp__github__create_issue`. Use it for filesystem, GitHub, database, memory, or other MCP tool servers; no server is enabled by default. Tool definitions add tokens to every model request, while a slow or crashed server can delay startup or make its tools fail until recovery. The package bridges tools only; MCP resources and prompts are unsupported.
13
13
 
14
14
  ## Table of Contents
15
15
 
@@ -76,6 +76,7 @@ The model sees each tool under a stable server-qualified name: `mcp__<serverName
76
76
  - Two servers publishing the same tool name (for example `search`) coexist under their own namespaces.
77
77
  - Two entries using the same server name: the later one fails to load with a clear error.
78
78
  - A server that lists the same tool twice gets its tool list rejected as invalid, and the previous tool set stays active.
79
+ - A repeated non-empty `tools/list` continuation cursor rejects that update immediately, including cycles through empty pages; the previous tool set stays active and later updates can still succeed.
79
80
  - An update that conflicts with an already-registered tool name is rejected entirely — you never get a partial tool set from that server.
80
81
 
81
82
  ### Calling tools and reading results
package/README.zh.md CHANGED
@@ -9,7 +9,7 @@ kind: "package-reference"
9
9
 
10
10
  ## 概述
11
11
 
12
- `dsh-mcp-client` 把外部 MCP(Model Context Protocol)服务器挂载到 harness 上,让它们的工具像原生工具一样可用。每台服务器一条配置项,模型就能调用该服务器的工具——文件系统、GitHub、数据库或记忆服务器——名称稳定,例如 `mcp__github__create_issue`。当模型需要使用外部工具服务器时添加它;默认不启用任何服务器,因此由你开启。主要成本是这些工具定义给每次请求增加的 token,而且缓慢或崩溃的服务器可能延迟启动,或在恢复前让它的工具一直调用失败。只桥接工具能力:MCP resources 与 prompts 不受支持。
12
+ `dsh-mcp-client` 让模型把外部 MCP(Model Context Protocol)服务器的工具当作 harness 原生工具调用。每台服务器配置一条记录,其工具便会以稳定名称出现,例如 `mcp__github__create_issue`。可将它用于文件系统、GitHub、数据库、记忆或其他 MCP 工具服务器;默认不启用任何服务器。工具定义会为每次模型请求增加 token;缓慢或崩溃的服务器可能延迟启动,或让工具调用失败直至恢复。本包只桥接工具;MCP resources 与 prompts 不受支持。
13
13
 
14
14
  ## 目录
15
15
 
@@ -76,6 +76,7 @@ kind: "package-reference"
76
76
  - 发布相同工具名称(例如 `search`)的两个服务器会在各自的 namespace 下共存。
77
77
  - 两条配置项使用相同的服务器名称时,后加载的一条会在加载时以明确错误失败。
78
78
  - 服务器在工具列表中两次列出同一工具时,其工具列表会被作为无效列表拒绝,上一组工具保持可用。
79
+ - `tools/list` 返回重复的非空续传游标时会立即拒绝本次更新,包括经过空页的循环;上一组工具保持可用,后续更新仍可成功。
79
80
  - 工具更新与已有工具名称冲突时,该更新会被整体拒绝——绝不会得到该服务器的部分工具集。
80
81
 
81
82
  ### 调用工具与读取结果
package/lib/index.js CHANGED
@@ -131,8 +131,8 @@ function publicToolName(serverName, rawName) {
131
131
  *
132
132
  * 1. Fetch: drain uncached `tools/list` pagination and build the full next
133
133
  * generation of `ToolDefinition`s under public names. Any failure here
134
- * (network error, duplicate raw name in the server's list) rejects and
135
- * leaves the previous generation registered untouched.
134
+ * (network error, duplicate raw name, repeated continuation cursor) rejects
135
+ * and leaves the previous generation registered untouched.
136
136
  * 2. Swap: dispose the previous generation, register the new one. A registry
137
137
  * conflict here can only mean a foreign registration squats on this
138
138
  * server's `mcp__<serverName>__` namespace — the partial generation is
@@ -150,6 +150,7 @@ function publicToolName(serverName, rawName) {
150
150
  */
151
151
  async function syncTools(client, ctx, opts, previous) {
152
152
  const definitions = /* @__PURE__ */ new Map();
153
+ const seenCursors = /* @__PURE__ */ new Set();
153
154
  let cursor;
154
155
  do {
155
156
  const response = await listToolsUncached(client, cursor);
@@ -159,6 +160,10 @@ async function syncTools(client, ctx, opts, previous) {
159
160
  definitions.set(publicName, createDefinition(client, ctx, publicName, tool.name, tool.description ?? "", tool.inputSchema, supportedOutputSchema(tool.outputSchema), tool.execution?.taskSupport === "required", opts));
160
161
  }
161
162
  cursor = response.nextCursor;
163
+ if (cursor) {
164
+ if (seenCursors.has(cursor)) throw new Error(`mcp-client(${opts.serverName}): server repeated a tools/list continuation cursor — invalid tool list`);
165
+ seenCursors.add(cursor);
166
+ }
162
167
  } while (cursor);
163
168
  for (const dispose of previous.values()) dispose();
164
169
  const disposers = /* @__PURE__ */ new Map();
@@ -50,8 +50,8 @@ export declare function publicToolName(serverName: string, rawName: string): str
50
50
  *
51
51
  * 1. Fetch: drain uncached `tools/list` pagination and build the full next
52
52
  * generation of `ToolDefinition`s under public names. Any failure here
53
- * (network error, duplicate raw name in the server's list) rejects and
54
- * leaves the previous generation registered untouched.
53
+ * (network error, duplicate raw name, repeated continuation cursor) rejects
54
+ * and leaves the previous generation registered untouched.
55
55
  * 2. Swap: dispose the previous generation, register the new one. A registry
56
56
  * conflict here can only mean a foreign registration squats on this
57
57
  * server's `mcp__<serverName>__` namespace — the partial generation is
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-mcp-client",
3
3
  "description": "MCP client bridge: connects to MCP servers and registers their tools on ctx.tools",
4
- "version": "0.1.3-alpha.2",
4
+ "version": "0.1.5-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,12 +27,12 @@
27
27
  ],
28
28
  "license": "MIT",
29
29
  "peerDependencies": {
30
- "@deepseek-ai/dsh-attachment": "^0.1.3-alpha.2",
31
- "@deepseek-ai/dsh-llm": "^0.1.3-alpha.2",
32
- "@deepseek-ai/dsh-scope": "^0.1.3-alpha.2",
33
- "@deepseek-ai/dsh-subprocess": "^0.1.3-alpha.2",
34
- "@deepseek-ai/dsh-timeout": "^0.1.3-alpha.2",
35
- "@deepseek-ai/dsh-tools": "^0.1.3-alpha.2",
30
+ "@deepseek-ai/dsh-llm": "^0.1.5-alpha.2",
31
+ "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.2",
32
+ "@deepseek-ai/dsh-scope": "^0.1.5-alpha.2",
33
+ "@deepseek-ai/dsh-subprocess": "^0.1.5-alpha.2",
34
+ "@deepseek-ai/dsh-tools": "^0.1.5-alpha.2",
35
+ "@deepseek-ai/dsh-timeout": "^0.1.5-alpha.2",
36
36
  "@deepseek-ai/cordis": "^4.0.2"
37
37
  },
38
38
  "dependencies": {
@@ -43,14 +43,14 @@
43
43
  "devDependencies": {
44
44
  "@modelcontextprotocol/server-everything": "^2026.7.4",
45
45
  "@modelcontextprotocol/server-filesystem": "^2026.7.4",
46
- "@deepseek-ai/dsh-attachment": "^0.1.3-alpha.2",
47
- "@deepseek-ai/dsh-attachment-local": "^0.1.3-alpha.2",
48
- "@deepseek-ai/dsh-llm": "^0.1.3-alpha.2",
49
- "@deepseek-ai/dsh-scope": "^0.1.3-alpha.2",
50
- "@deepseek-ai/dsh-subprocess": "^0.1.3-alpha.2",
51
- "@deepseek-ai/dsh-timeout": "^0.1.3-alpha.2",
52
- "@deepseek-ai/dsh-tools": "^0.1.3-alpha.2",
46
+ "@deepseek-ai/dsh-attachment": "^0.1.5-alpha.2",
47
+ "@deepseek-ai/dsh-attachment-local": "^0.1.5-alpha.2",
48
+ "@deepseek-ai/dsh-llm": "^0.1.5-alpha.2",
49
+ "@deepseek-ai/dsh-scope": "^0.1.5-alpha.2",
50
+ "@deepseek-ai/dsh-subprocess": "^0.1.5-alpha.2",
51
+ "@deepseek-ai/dsh-timeout": "^0.1.5-alpha.2",
52
+ "@deepseek-ai/dsh-tools": "^0.1.5-alpha.2",
53
53
  "@deepseek-ai/cordis": "^4.0.2",
54
- "@deepseek-ai/dsh-http-proxy": "^0.1.3-alpha.2"
54
+ "@deepseek-ai/dsh-http-proxy": "^0.1.5-alpha.2"
55
55
  }
56
56
  }