MCP 配置里的明文令牌:如何把它们移出去

各编码代理把 MCP 服务器设置保存在哪里,如何找出写在其中的令牌,zn-gate init --wrap-mcp 如何处理它们(不会删除),以及如何移出这些值并撤销每一步。

查看 .md

MCP 服务器常常需要一个令牌,最快的给法是把它粘贴到代理配置文件里该服务器的 env 或 headers 中。这样令牌就留在你个人文件夹或项目里的一个纯文本文件中。本页列出各代理把该文件放在哪里,说明如何在其中找出令牌,解释 zn-gate init --wrap-mcp 对它们做什么、不做什么,并说明如何移出这些值以及如何撤销每一步。关于密钥与编码代理的整体情况,请见检查清单指南。

各代理把 MCP 服务器保存在哪里

代理 用户文件 项目文件 init --wrap-mcp 会改写
Claude Code ~/.claude.json 项目根目录的 .mcp.json ~/.claude.json
Claude Desktop claude_desktop_config.json(macOS ~/Library/Application Support/Claude/,Windows %APPDATA%\Claude\,Linux ~/.config/Claude/) 无 该文件
Cursor ~/.cursor/mcp.json .cursor/mcp.json ~/.cursor/mcp.json
Codex CLI ~/.codex/config.toml(或 $CODEX_HOME/config.toml) .codex/config.toml(仅限受信任的项目) 用户文件
OpenCode ~/.config/opencode/opencode.json (或 opencode.jsonc) 项目中的 opencode.json 用户文件
Antigravity ~/.gemini/config/mcp_config.json .agents/mcp_config.json 用户文件(zn-gate 也会查找 ~/.gemini/antigravity/mcp_config.json)

~/.claude.json 还在 projects 下保存只针对单个项目配置的服务器。init --wrap-mcp 只包装该文件顶层的 mcpServers,所以各项目下的条目不会被包装;audit 会检查它们。

Claude Code、Cursor、Codex CLI 和 OpenCode 的路径来自各代理自己的文档;Claude Desktop 和 Antigravity 的路径依据 zn-gate 的文档和 Antigravity 页面。init --wrap-mcp 不会改动项目文件:项目文件里的令牌原样保留。关于 VS Code、Windsurf、Cline、Zed、JetBrains 和 Continue,请见编辑器。

找出令牌

npx -y zn-gate reach
npx -y zn-gate audit --include-home

reach 需要 zn-gate 1.12.0 或更高版本。两者都是只读的。它们会报告写在代理配置中的密钥值(规则 ZNA011),并且从不打印该值。在项目文件夹中运行 audit 还会检查该项目的文件;--include-home 会加入上表中位于你个人文件夹的文件(Claude Desktop 和 Antigravity 的除外)。两者都使用 zn-gate 自己的检测,因此格式它不认识的令牌可能被漏掉:请你自己也读一遍配置文件。

zn-gate init --wrap-mcp 如何处理令牌

它不会删除令牌。对每个本地(stdio)服务器,它只改启动命令:原命令变成 npx -y zn-gate shield -- 的参数。条目中的其余内容,包括 env,保持原样。shield 随后检查工具描述、调用参数和工具输出,并在你的代理读取之前,从输出中移除它能识别的密钥(详情)。这保护的是代理从服务器收到的内容,而不是这个文件。

关于该命令的其他事实:

  • 远程(URL)服务器保持不变,因此 headers 条目里的令牌依然在。
  • 写入文件之前,它会在原文件旁复制一份,命名为 <文件>.bak.<时间戳>。这份副本是文件原来的样子,包含令牌。
  • 带注释的 OpenCode 文件和 args 跨多行的 Codex 条目不会被改写;init 会把它们报告为 "wrap manually"。
npx -y zn-gate init --dry-run    # 预览,不做任何更改
npx -y zn-gate init --shadow     # 包装,只记录
npx -y zn-gate init --wrap-mcp   # 包装并强制执行
npx -y zn-gate init --revert     # 恢复每个文件最近的备份

把值移出去

把令牌放进环境变量,让配置按名称引用它。各代理文档的说法如下:

  • Claude Code,在 .mcp.json 中:${VAR}(以及 ${VAR:-default})会在 command、args、env、url 和 headers 中展开。对于远程服务器的 url 和 headers,Claude Code 的文档对凭据变量另有限制;在那里依赖这一做法之前请先阅读。
  • Cursor,在 mcp.json 中:${env:NAME} 会在 command、args、env、url 和 headers 中解析。
  • Codex CLI,在 config.toml 中:env_vars 把 Codex 环境中的变量转发给 stdio 服务器,bearer_token_env_var 指定保存 bearer 令牌的变量名,env_http_headers 把请求头名称对应到变量名。文件里只保存名称。
  • OpenCode:配置文件中会替换 {env:VARIABLE_NAME},其 MCP 文档在请求头中展示了它。
  • Claude Desktop、Antigravity 和其他编辑器:我们没有验证在它们的 MCP 文件中引用环境变量的方法,所以本页不提供。

Cursor 示例,服务器和变量均为虚构(EXAMPLE_API_TOKEN):

{
  "mcpServers": {
    "example": {
      "command": "npx",
      "args": ["-y", "example-mcp-server"],
      "env": { "EXAMPLE_API_TOKEN": "${env:EXAMPLE_API_TOKEN}" }
    }
  }
}

该变量必须存在于代理进程的环境中:在你启动代理的地方设置它(你的 shell 配置文件,或操作系统设置变量的方式),重启代理,并检查服务器是否连接成功。请注意,shell 配置文件本身也是代理可以读取的纯文本文件,把令牌放在那里只是把它挪到了另一个文件。更好的做法是使用操作系统的钥匙串或密钥管理工具,在启动代理时提供该变量;至少也要把令牌放在代理打开的任何文件夹之外的文件里。

稳妥的顺序

  1. 运行 npx -y zn-gate reach,记下哪些文件里有令牌。
  2. 按上文把每个令牌换成环境变量引用,并重启代理。
  3. 如果该文件曾被提交、备份、共享或推送,或者代理曾能读取它,或者令牌出现在了某份对话记录中,请轮换所有曾在其中出现过的令牌。你从文件里删掉的值,在你到服务商处吊销之前仍然有效。
  4. 这之后再运行 npx -y zn-gate init --dry-run,然后 --shadow,然后 --wrap-mcp。它写下的备份里是不含令牌的文件。
  5. 如果你是先包装的:令牌移出之后,删除配置文件旁的 .bak.<时间戳> 文件,因为它们仍然保存着旧值。
  6. 再次运行 npx -y zn-gate reach。

zn env shadow 的用途与非用途

zn env shadow .env 会把 .env 文件中的值移入 zn-gate 的本地保险库,并在文件里留下标记(Scrubber)。它读取 KEY=value 形式的行。MCP 配置文件是 JSON 或 TOML,zn-gate 的文档没有描述把 env shadow 用于它们,所以不要对它们使用。

如何撤销每一步

  • 包装: npx -y zn-gate init --revert 会把最近的 .bak.<时间戳> 复制回每个配置文件。你在包装之后对文件所做的任何修改都会丢失;如果备份里有令牌,它们也会回来。完成上面的第 2 步之后,请改为手动撤销:在每个条目中,把原来的命令和参数放回 npx -y zn-gate shield -- 的位置。
  • 环境变量引用: 只有迫不得已才把值放回文件,并且绝不要放进你会提交的文件。
  • env shadow: zn env unshadow 文件 --backup 名称,名称为 env shadow 打印出的那个。

局限

  • 检测只能找出已知格式;没有已知格式的令牌可能被漏掉。
  • 包装检查的是服务器返回的内容和代理发给它的内容,并不能阻止其他程序读取配置文件。
  • 像 .mcp.json 这样的项目文件不在 init --wrap-mcp 的范围内。
  • 你移到环境变量中的令牌,对任何以该环境启动的程序都是可见的。

常见问题

zn-gate init --wrap-mcp 会从我的 MCP 配置中删除令牌吗? 不会。它改的是本地服务器的启动命令,env 和 headers 保持原样。

备份里有我的令牌吗? 有,如果你包装时令牌在文件里。把值移出之后,请删除 .bak.<时间戳> 文件。

我可以对 mcp.json 使用 zn env shadow 吗? 它只记录了用于 .env 文件。

怎么确认没有遗留? 运行 npx -y zn-gate reach 和 npx -y zn-gate audit --include-home,并自己阅读这些文件。

来源