1.4 持久化、密钥与验证排错

一次性 vs 持久化

--patch 是一次性的:这次启动生效,重启就没了。要跨次运行保留,得把 insert patch 合并进用户 patch 层。

范围 写入位置
只对一个 profile 生效 $DSH_HOME/profiles/<name>/cordis.patch.yml
对本机所有 profile 生效 $DSH_HOME/cordis.patch.yml

官方特别叮嘱:不要覆盖已有文件,里面可能已经包含无关的用户 patch。正确做法是读取现有内容,把新的 insert 项追加进去。

全局级与 profile 级怎么选

两个写入位置作用域不同,决策很简单:

你想达到的效果 写哪
这个 MCP 只在这个项目 / 这个 profile 下用 $DSH_HOME/profiles/<name>/cordis.patch.yml
本机任何 dsh 会话都要用到(如通用记忆) $DSH_HOME/cordis.patch.yml

profile 级的好处是隔离——不同项目接不同的服务器,互不干扰;全局级的好处是一处配置处处生效,适合基础设施类的服务器。

一个安全的合并脚本思路

# 先看现有内容,确认没有同名 id
cat "$DSH_HOME/cordis.patch.yml" 2>/dev/null || echo "(文件不存在)"
# 目标形态:同一份文件里多个 insert 项
- insert:
    - id: memory-my-server
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: my_memory
        transport: stdio
        command: mcp-server-memory
- insert:
    - id: fetch
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: fetch
        transport: stdio
        command: uvx
        args: ["mcp-server-fetch"]

id 在各自 insert 内唯一即可,但建议全局唯一,便于日后删除时定位。多个 insert 项可以并列写在同一份 patch 文件里,dsh 启动时会全部加载。

避免 id 冲突

新增配置前,先确认文件里没有同名的 id。冲突的 id 不会报错,但会让你“删除 A 却把 B 也删了”或者“改 A 命中 B”。一个实用的习惯:用 <用途>-<serverName> 的命名,比如 memory-my_memory、fetch-mcp-server-fetch,一眼能区分。

密钥管理三条纪律

纪律 原因
不写明文进 YAML YAML 会进 git、会被分享
用 !!js 从环境读取 配置文件与密钥分离
需要继承时显式加进 config.env stdio 桥接器会主动剥离凭据类变量与所有 DSH_* 变量

第二条的写法在前面章节已给示例。这里补一个易错点:!!js 表达式里别写死密钥本身,只写“从哪读”。例如 process.env.MY_TOKEN 是安全的,把 token 字符串直接粘进表达式里就失去了分离的意义。

官方三步验证法

这是官方文档给出的记忆服务器验证流程,但它适用于任何有状态 MCP。核心是跨会话召回:

第一步:写入。 在会话 A 里提一个唯一值:

Remember that my validation drink is lapsang-<唯一后缀>.

确认模型调用了提供方的写入工具,且工具返回成功。

第二步:召回。 在同一个仍在运行的 Host 中新建会话 B,不要复制 A 的对话:

What is my validation drink? Check memory.

确认模型调用了搜索或召回工具,并返回那个值。

第三步:使用。 继续在会话 B 提问:

Use that preference to suggest one drink for the meeting.

确认回答用了召回的值。

两个关键点:必须新建 DSH 会话,但不需要重启 Host。 这一步验证了“状态真的跨会话保留了”,而不是“同一次会话里模型刚好记得”。

重连与可用性

官方对故障行为有明确描述:

  • MCP 子进程崩溃后触发带退避的自动重连与工具重新同步;
  • 停机期间工具仍保持列出,调用只在停机期间失败;
  • 重连预算耗尽后工具会被注销,重连停止,直到重新加载或重启。

这条对排错极重要:工具还在列表里 ≠ 服务是好的。 看到工具却调用失败,先怀疑它处于停机未重连状态。此时重新加载配置或重启 Host 通常能恢复。

排错总表

现象 首选怀疑
工具完全不出现 上游未装 / 命令不在 PATH / 没等异步发现
工具出现但调用失败 停机未重连;上游报错
调用成功但结果不对 上游自身逻辑 / 数据未初始化
重启后配置没了 只用了 --patch,没合并进 patch 层
提示缺密钥 环境被剥离,需写进 config.env
远程 401 / 403 headers 令牌问题,或账号未授权

可选的模型指令

如果服务器工具描述不足以可靠触发使用,官方建议加一句与提供方无关的简短指令到现有模型指令里:

用户要求记住某事时调用记忆写入工具;历史信息可能相关时,检索记忆并使用相关结果。

这只是附加指导,不会替换 DSH 系统提示词中的 persona。

小结

  • --patch 一次性;持久化要合并 insert 进 $DSH_HOME/cordis.patch.yml(或 profile 级),且不要覆盖已有内容。
  • profile 级隔离项目、全局级处处生效,按作用域选。
  • 密钥三纪律:不写明文、用 !!js 读环境、需继承时显式进 config.env。
  • 验证用三步法:写入 → 新会话召回 → 使用召回值。
  • 工具仍在列表 ≠ 服务正常,重连预算耗尽后会注销工具。

延伸阅读