diff --git a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.i18n.yaml b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.i18n.yaml index 9115d89318..0eddfa1740 100644 --- a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.i18n.yaml +++ b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write .agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.md -2026-07-31-third-party-memory-mcp-examples.md: 512a222d1f8406d11ef5c58c5f2749c9b571d846 -2026-07-31-third-party-memory-mcp-examples.zh.md: 8bdc4ae371b7b3c4a8e78eeceed1f965e515a475 +2026-07-31-third-party-memory-mcp-examples.md: e82d65a3a5a60cafcc47df5a6873cf5768cd8b8f +2026-07-31-third-party-memory-mcp-examples.zh.md: ee0e9f2e1378f9787e09e32cc05dd13a3648254c diff --git a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.md b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.md index 512a222d1f..e82d65a3a5 100644 --- a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.md +++ b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.md @@ -27,9 +27,9 @@ These third-party configurations are provided as interoperability examples only. | Account, auth, model, embedding, storage initialization | No | Yes | | Vendor data migration, retry, crash recovery | No | Yes | -The generic stdio transport scrubs ambient credential-shaped and `DSH_*` variables. Baseline examples explicitly map only the variables they require; optional provider secrets must be added to `config.env` or configured in the provider's own files. +The generic stdio transport scrubs ambient credential-shaped and `DSH_*` variables while inheriting other ambient variables. Baseline examples add only required overrides; optional provider secrets must be added to `config.env` or configured in the provider's own files. -## Pins and identity +## Pins, storage, and identity | Provider | Tested contract | |---|---| @@ -37,7 +37,7 @@ The generic stdio transport scrubs ambient credential-shaped and `DSH_*` variabl | MCP Reference Memory | npm `2026.7.4`, package commit `6dd0a683e198783e30feabf7abaf42f925bd18b1` | | Engram | tag `v1.20.0`, commit `ba9e46ced152c37a7cb9e576153c41995873e2fc` | -`DSH_MEMORY_USER_ID` is a stable user partition, not a DSH session id. Each example maps it to a separate provider data path under `$DSH_HOME`. +Storage remains provider-owned. Memorix uses `~/.memorix/data` and Engram uses `~/.engram` by default. The Reference Memory example sets a stable `$HOME/.dsh-mcp-reference-memory.jsonl` path instead of writing into the installed npm package directory. Each provider's own environment variable can override these locations before DSH starts. Project identity remains provider-owned: Memorix and Engram use the DSH working directory's Git project, with Engram optionally accepting `ENGRAM_PROJECT`. @@ -56,7 +56,7 @@ Remote CI never contacts third-party services or consumes secrets. The keyless s Before merge, manual evidence for every pinned provider must separately show: 1. DSH session A calls a write tool and receives success for a unique value. -2. Fresh DSH session B, under the same provider/user scope, calls search or recall and returns that value without session A's transcript. +2. Fresh DSH session B, under the same provider storage scope, calls search or recall and returns that value without session A's transcript. 3. Session B uses the recalled value in a subsequent answer. "Fresh session" means a new DSH session in the same Host. No Host restart is required. The generic MCP client discovers asynchronously and has no automatic reconnect after a child or HTTP transport closes; validation waits for tools before the first turn and uses HMR or a Host restart only after a crash. diff --git a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.zh.md b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.zh.md index 8bdc4ae371..ee0e9f2e13 100644 --- a/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.zh.md +++ b/.agents/notes/implemented/feature/2026-07-31-third-party-memory-mcp-examples.zh.md @@ -27,9 +27,9 @@ Status: implemented | 账户、认证、模型、embedding、存储初始化 | 否 | 是 | | 提供方数据迁移、重试、崩溃恢复 | 否 | 是 | -通用 stdio 传输会清除环境中名称类似凭据的变量和 `DSH_*` 变量。基线示例仅显式映射自己需要的变量;可选的提供方密钥必须添加到 `config.env`,或配置在提供方自己的文件中。 +通用 stdio 传输会清除环境中名称类似凭据的变量和 `DSH_*` 变量,同时继承其他环境变量。基线示例仅添加必需的覆盖项;可选的提供方密钥必须添加到 `config.env`,或配置在提供方自己的文件中。 -## 版本固定与身份 +## 版本固定、存储与身份 | 提供方 | 已测试契约 | |---|---| @@ -37,7 +37,7 @@ Status: implemented | MCP Reference Memory | npm `2026.7.4`,package commit `6dd0a683e198783e30feabf7abaf42f925bd18b1` | | Engram | tag `v1.20.0`,commit `ba9e46ced152c37a7cb9e576153c41995873e2fc` | -`DSH_MEMORY_USER_ID` 是稳定的用户分区,不是 DSH 会话 id。每份示例都将其映射到 `$DSH_HOME` 下相互独立的提供方数据路径。 +存储仍由提供方负责。Memorix 默认使用 `~/.memorix/data`,Engram 默认使用 `~/.engram`。Reference Memory 示例设置稳定的 `$HOME/.dsh-mcp-reference-memory.jsonl` 路径,而不是写入已安装的 npm 包(package)目录。每个提供方自己的环境变量都可以在 DSH 启动前覆盖这些位置。 项目身份仍由提供方负责:Memorix 和 Engram 使用 DSH 工作目录中的 Git 项目,其中 Engram 还可以选择接受 `ENGRAM_PROJECT`。 @@ -56,7 +56,7 @@ Status: implemented 合并前,每个固定版本的提供方都必须分别提供以下人工证据: 1. DSH 会话 A 调用写入工具,为一个唯一值写入记忆,并收到成功结果。 -2. 新的 DSH 会话 B 在相同提供方/用户范围下调用搜索或召回,不借助会话 A 的 transcript(文本记录)便可返回该值。 +2. 新的 DSH 会话 B 在相同的提供方存储范围下调用搜索或召回,不借助会话 A 的 transcript(文本记录)便可返回该值。 3. 会话 B 在后续回答中使用该召回值。 「新会话」是指同一个 Host 中新建的 DSH 会话,不需要重启 Host。通用 MCP 客户端以异步方式发现工具,子进程或 HTTP 传输关闭后不会自动重连;验证会在第一轮之前等待工具出现,并且只在崩溃后使用 HMR 或重启 Host。 diff --git a/apps/cli/tests/memory-mcp-configs.spec.ts b/apps/cli/tests/memory-mcp-configs.spec.ts index a8940a13ae..7069b22738 100644 --- a/apps/cli/tests/memory-mcp-configs.spec.ts +++ b/apps/cli/tests/memory-mcp-configs.spec.ts @@ -90,7 +90,7 @@ describe('third-party memory MCP example overlays', () => { expect(row.name).toBe('@deepseek-ai/dsh-mcp-client') expect(row.config?.serverName).toBe(contract.serverName) expect(row.config?.transport).toBe(contract.transport) - expect(source).toContain(contract.pin) + expect(source.split('\n', 1)[0]).toContain(contract.pin) expect(source).not.toMatch(/\bsk-[A-Za-z0-9_-]{8,}\b/) expect(source).not.toContain('DEEPSEEK_API_KEY') }) @@ -121,12 +121,12 @@ describe('third-party memory MCP example overlays', () => { baseConfig, [...patches, fixturePatch], (ctx) => { + liveContexts.add(ctx) ctx.loader.builtins['memory-test-system-prompt'] = SystemPrompt ctx.loader.builtins['memory-test-tools'] = ToolRegistry ctx.loader.builtins['memory-test-mcp-client'] = McpClient }, ) - liveContexts.add(ctx) await waitForTool(ctx, `mcp__${contract.serverName}__greet`) }, 15_000) }) diff --git a/examples/mcp-memory/README.i18n.yaml b/examples/mcp-memory/README.i18n.yaml index b69766153c..def44e65e3 100644 --- a/examples/mcp-memory/README.i18n.yaml +++ b/examples/mcp-memory/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write examples/mcp-memory/README.md -README.md: 97d7da66bad3b7b4a14d54a94788108b3831ccc4 -README.zh.md: 5d7c19ae76f10b795dc8e1b39c768851921b0703 +README.md: b5dd7ffc4ad248d38e108d9aa28c7c26e0c76913 +README.zh.md: 1249ae40bb344fc81836cb49d71dd5656457b1b3 diff --git a/examples/mcp-memory/README.md b/examples/mcp-memory/README.md index 97d7da66ba..b5dd7ffc4a 100644 --- a/examples/mcp-memory/README.md +++ b/examples/mcp-memory/README.md @@ -10,7 +10,7 @@ These third-party configurations are provided as interoperability examples only. DSH parses the selected Cordis overlay, starts a configured stdio command or connects to a configured Streamable HTTP URL, discovers MCP tools, and exposes them as `mcp____`. DSH does **not** download the server, initialize its database, choose its model or embedding provider, create a cloud account, migrate vendor data, or supervise a separate HTTP service. For stdio, the generic client launches and stops the child with the DSH plugin lifecycle; for HTTP, the upstream service must already be running. -The stdio bridge deliberately removes ambient credential-shaped and `DSH_*` variables before launching a child. Each example explicitly forwards only the variables needed for its baseline. If an optional upstream feature needs another secret, add that variable to the row's `config.env` instead of putting the secret directly in YAML. +The stdio bridge deliberately removes ambient credential-shaped and `DSH_*` variables before launching a child; other ambient variables remain inherited. Each example adds only the baseline override it needs. If an optional upstream feature needs another secret, add that variable to the row's `config.env` instead of putting the secret directly in YAML. ## Choose one @@ -28,7 +28,7 @@ Pass one overlay to DSH: dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml" ``` -Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. Those two examples also accept `DSH_MEMORY_USER_ID` for stable per-user storage. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--config` keeps all three disabled. +Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--config` keeps all three disabled. Without a repository checkout, download the selected overlay directly: @@ -59,11 +59,10 @@ Memorix works in local heuristic mode without an LLM or embedding service. Confi ```sh npm install --global @modelcontextprotocol/server-memory@2026.7.4 -export DSH_MEMORY_USER_ID=alice dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml" ``` -This reference server stores a local knowledge graph and exposes entity, relation, observation, read, search, and open tools. It needs no model or embedding service. The example maps `DSH_MEMORY_USER_ID` to an isolated `MEMORY_FILE_PATH`. +This reference server stores a local knowledge graph and exposes entity, relation, observation, read, search, and open tools. It needs no model or embedding service. The example stores its JSONL at `$HOME/.dsh-mcp-reference-memory.jsonl` instead of the installed npm package directory. Set `MEMORY_FILE_PATH` before starting DSH to override it. Search is case-insensitive substring matching over entity names, types, and observations, not semantic retrieval. The server does not add embeddings, automatic summarization, conflict resolution, or a forgetting policy. @@ -71,11 +70,10 @@ Search is case-insensitive substring matching over entity names, types, and obse ```sh go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0 -export DSH_MEMORY_USER_ID=alice dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml" ``` -The example maps the user id to an isolated `ENGRAM_DATA_DIR`. Engram still owns project selection: it detects the Git project from the DSH working directory, or accepts `ENGRAM_PROJECT` as an explicit override. +Engram owns storage and project selection: it uses `~/.engram` by default, detects the Git project from the DSH working directory, and accepts `ENGRAM_DATA_DIR` or `ENGRAM_PROJECT` as ambient overrides. ## Optional shared model instruction @@ -93,7 +91,7 @@ Use one unique value and keep the provider's storage scope unchanged throughout: 2. Create DSH session B in the same running Host. Do not copy session A's conversation. Ask: `What is my validation drink? Check memory.` Confirm the model called the provider's search or recall tool and returned the value. 3. Still in session B, ask: `Use that preference to suggest one drink for the meeting.` Confirm the answer uses the recalled value. -A new DSH session is required; a Host restart is not. Restart or HMR is needed only after an MCP child crashes because the current generic client unregisters tools on disconnect and does not auto-reconnect. Initial discovery is asynchronous, so wait for the provider's `mcp__...` tools before sending the first validation prompt. +A new DSH session is required; a Host restart is not. Restart or HMR is needed only after an MCP child crashes because the current generic client does not auto-reconnect; its tool registrations remain until plugin disposal or a successful re-sync, and calls can fail against the closed transport. Initial discovery is asynchronous, so wait for the provider's `mcp__...` tools before sending the first validation prompt. ## Bring another MCP server diff --git a/examples/mcp-memory/README.zh.md b/examples/mcp-memory/README.zh.md index 5d7c19ae76..1249ae40bb 100644 --- a/examples/mcp-memory/README.zh.md +++ b/examples/mcp-memory/README.zh.md @@ -10,7 +10,7 @@ DSH 解析选中的 Cordis overlay,启动已配置的 stdio 命令或连接已配置的 Streamable HTTP URL,发现 MCP 工具,并以 `mcp____` 的形式公开这些工具。DSH **不负责** 下载服务器、初始化其数据库、选择模型或 embedding 提供方、创建云端账户、迁移提供方数据,也不监管独立的 HTTP 服务。对于 stdio,通用客户端会随 DSH 插件生命周期启动和停止子进程;对于 HTTP,上游服务必须已经运行。 -stdio 桥接器在启动子进程前会主动移除环境中名称类似凭据的变量和 `DSH_*` 变量。每份示例仅显式转发其基线运行所需的变量。如果某个可选的上游功能还需要其他密钥,请将该变量添加到配置项的 `config.env`,不要把密钥直接写进 YAML。 +stdio 桥接器在启动子进程前会主动移除环境中名称类似凭据的变量和 `DSH_*` 变量;其余环境变量仍会继承。每份示例仅添加其基线所需的覆盖项。如果某个可选的上游功能还需要其他密钥,请将该变量添加到配置项的 `config.env`,不要把密钥直接写进 YAML。 ## 选择一个 @@ -28,7 +28,7 @@ stdio 桥接器在启动子进程前会主动移除环境中名称类似凭据 dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml" ``` -请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。另外两份示例也接受 `DSH_MEMORY_USER_ID`,用于稳定的逐用户存储。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--config` 就会让这三项全部保持关闭。 +请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--config` 就会让这三项全部保持关闭。 如果本地没有仓库 checkout,可直接下载所选 overlay: @@ -59,11 +59,10 @@ Memorix 无需 LLM(大语言模型)或 embedding 服务,即可在本地启 ```sh npm install --global @modelcontextprotocol/server-memory@2026.7.4 -export DSH_MEMORY_USER_ID=alice dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml" ``` -该参考服务器存储本地知识图谱,并公开实体、关系、观察、读取、搜索和打开工具。它不需要模型或 embedding 服务。该示例将 `DSH_MEMORY_USER_ID` 映射到隔离的 `MEMORY_FILE_PATH`。 +该参考服务器存储本地知识图谱,并公开实体、关系、观察、读取、搜索和打开工具。它不需要模型或 embedding 服务。该示例将 JSONL 存储在 `$HOME/.dsh-mcp-reference-memory.jsonl`,而不是已安装的 npm 包(package)目录中。若要覆盖该路径,请在启动 DSH 前设置 `MEMORY_FILE_PATH`。 搜索只对实体名称、类型和 observation 进行不区分大小写的子字符串匹配,不是语义检索。该服务器不提供 embedding、自动摘要、冲突消解或遗忘策略。 @@ -71,11 +70,10 @@ dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml" ```sh go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0 -export DSH_MEMORY_USER_ID=alice dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml" ``` -该示例将用户 id 映射到隔离的 `ENGRAM_DATA_DIR`。Engram 仍负责选择项目:它从 DSH 工作目录检测 Git 项目,也接受 `ENGRAM_PROJECT` 作为显式覆盖。 +Engram 负责存储和项目选择:它默认使用 `~/.engram`,从 DSH 工作目录检测 Git 项目,并接受 `ENGRAM_DATA_DIR` 或 `ENGRAM_PROJECT` 作为环境覆盖项。 ## 可选的共用模型指令 @@ -93,7 +91,7 @@ dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml" 2. 在同一个仍在运行的 Host 中创建 DSH 会话 B。不要复制会话 A 的对话。提出:`What is my validation drink? Check memory.`。确认模型调用了提供方的搜索或召回工具,并返回该值。 3. 继续在会话 B 中提出:`Use that preference to suggest one drink for the meeting.`。确认回答使用了召回的值。 -必须新建 DSH 会话,但不需要重启 Host。只有 MCP 子进程崩溃后才需要重启或执行 HMR(热模块替换),因为当前的通用客户端会在连接断开时注销工具,且不会自动重连。初始发现过程是异步的,因此发送第一条验证提示词前,请等待提供方的 `mcp__...` 工具出现。 +必须新建 DSH 会话,但不需要重启 Host。只有 MCP 子进程崩溃后才需要重启或执行 HMR(热模块替换),因为当前的通用客户端不会自动重连;其工具注册会一直保留到插件完成资源释放或成功重新同步,针对已关闭传输的调用可能失败。初始发现过程是异步的,因此发送第一条验证提示词前,请等待提供方的 `mcp__...` 工具出现。 ## 接入其他 MCP 服务器 diff --git a/examples/mcp-memory/engram.cordis.yml b/examples/mcp-memory/engram.cordis.yml index 100e12ddc7..018df88b6f 100644 --- a/examples/mcp-memory/engram.cordis.yml +++ b/examples/mcp-memory/engram.cordis.yml @@ -1,5 +1,5 @@ # Opt-in reference for Engram 1.20.0. Install the pinned `engram` executable -# first; project selection remains Engram's cwd/ENGRAM_PROJECT contract. +# first; storage and project selection remain Engram-owned. - insert: - id: memory-engram name: '@deepseek-ai/dsh-mcp-client' @@ -9,7 +9,3 @@ command: engram args: [mcp] cwd: !!js process.cwd() - env: - ENGRAM_PROJECT: !!js process.env.ENGRAM_PROJECT ?? '' - ENGRAM_DATA_DIR: !!js >- - process.env.ENGRAM_DATA_DIR ?? (() => { const path = process.getBuiltinModule('node:path'); const os = process.getBuiltinModule('node:os'); const crypto = process.getBuiltinModule('node:crypto'); const configured = process.env.DSH_HOME; const root = configured !== undefined && configured.trim().length > 0 ? configured : path.join(os.homedir(), '.dsh'); const user = process.env.DSH_MEMORY_USER_ID?.trim() || 'default'; const scope = crypto.createHash('sha256').update(user).digest('hex').slice(0, 16); return path.join(path.resolve(root), 'mcp-memory', 'engram', scope) })() diff --git a/examples/mcp-memory/mcp-reference-memory.cordis.yml b/examples/mcp-memory/mcp-reference-memory.cordis.yml index 315144e955..d89fbe2673 100644 --- a/examples/mcp-memory/mcp-reference-memory.cordis.yml +++ b/examples/mcp-memory/mcp-reference-memory.cordis.yml @@ -10,4 +10,4 @@ cwd: !!js process.cwd() env: MEMORY_FILE_PATH: !!js >- - (() => { const path = process.getBuiltinModule('node:path'); const os = process.getBuiltinModule('node:os'); const crypto = process.getBuiltinModule('node:crypto'); const configured = process.env.DSH_HOME; const root = configured !== undefined && configured.trim().length > 0 ? configured : path.join(os.homedir(), '.dsh'); const user = process.env.DSH_MEMORY_USER_ID?.trim() || 'default'; const scope = crypto.createHash('sha256').update(user).digest('hex').slice(0, 16); return path.join(path.resolve(root), `mcp-reference-memory-${scope}.jsonl`) })() + process.env.MEMORY_FILE_PATH?.trim() || process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:os').homedir(), '.dsh-mcp-reference-memory.jsonl') diff --git a/packages/mcp/mcp-client/README.i18n.yaml b/packages/mcp/mcp-client/README.i18n.yaml index 487742d907..c16e004674 100644 --- a/packages/mcp/mcp-client/README.i18n.yaml +++ b/packages/mcp/mcp-client/README.i18n.yaml @@ -2,5 +2,5 @@ # side as of the last confirmed-consistent state. Both languages carry equal authority; # after editing either side, bring the other along and re-record with: # pnpm run verify-translation-pairing --write packages/mcp/mcp-client/README.md -README.md: 82d974635cb35878d6f0365b1aa7a9745436240e -README.zh.md: e687c620158955f954dcfebf682503225ee710de +README.md: fe6531054b00a72050b989013297bf14db85ac66 +README.zh.md: 61a1f555e2355a9761f76ac079e90dad675d6914 diff --git a/packages/mcp/mcp-client/README.md b/packages/mcp/mcp-client/README.md index 82d974635c..fe6531054b 100644 --- a/packages/mcp/mcp-client/README.md +++ b/packages/mcp/mcp-client/README.md @@ -61,7 +61,7 @@ Every MCP tool has two names: the raw MCP name (sent on the wire in `tools/call` - Tool execute: `client.callTool({ name: rawName, arguments }, { signal })` with timeout + abort support—the public name is never sent to the server. - Canonical success is `{ content: JsonValue[], structuredContent? }`; complete JSON MCP blocks survive for programmatic callers. A supported advertised `outputSchema` validates `structuredContent`; unsupported schema vocabulary falls back to unconstrained `JsonValue`. - Native/model rendering keeps the existing text projection: text blocks join with newlines while image, audio, resource, and unsupported blocks become placeholders. -- On disconnect/crash: all tools are unregistered; no auto-reconnect. +- On disconnect/crash: no auto-reconnect. Registered tools remain until plugin disposal or a successful re-sync, and calls can fail against the closed transport; reload with HMR or restart the Host to reconnect. ## Services consumed diff --git a/packages/mcp/mcp-client/README.zh.md b/packages/mcp/mcp-client/README.zh.md index e687c62015..61a1f555e2 100644 --- a/packages/mcp/mcp-client/README.zh.md +++ b/packages/mcp/mcp-client/README.zh.md @@ -61,7 +61,7 @@ MCP 客户端桥接插件:连接外部 [Model Context Protocol](https://modelc - 工具执行:`client.callTool({ name: rawName, arguments }, { signal })`,支持超时 + 中止;公开名称绝不会发给服务器。 - 规范成功值是 `{ content: JsonValue[], structuredContent? }`;完整的 JSON MCP 块会保留给编程调用方。受支持且已声明的 `outputSchema` 会验证 `structuredContent`;不受支持的 schema 词汇会回退为不受约束的 `JsonValue`。 - Native/模型渲染保留现有文本投影:文本块以换行连接,图片、音频、资源和不受支持的块会变成占位符。 -- 断开/崩溃时:注销所有工具;不自动重新连接。 +- 断开/崩溃时:不自动重新连接。已注册工具会一直保留到插件完成资源释放或成功重新同步,针对已关闭传输的调用可能失败;请通过 HMR 重新加载或重启 Host 来重新连接。 ## 消费的服务