明文 Key 写进 MCP 配置,等于写进整机磁盘
Claude Code、Cursor 接 MCP 时,很多人图省事把 API Key、GitHub PAT、云厂商令牌直接写进 ~/.claude.json、项目 .mcp.json 或等价配置。看起来「能跑」,代价很实在:
- 密钥落在磁盘明文,备份、同步盘、误提交到 Git 都会带走一份。
- 代理会话若读过密钥,摘要可能留在
~/.claude/projects一类日志里。 - 常开机器上配置长期在线,泄露窗口比笔记本「偶尔开机」更长。
更稳的做法是:配置文件只描述「怎么拿令牌」,不写令牌本身。用 macOS 钥匙串(或你信任的本机凭据方案)做中介,MCP 启动脚本向钥匙串要作用域令牌,再注入子进程环境;代理侧尽量只看到临时、窄权限凭证,而不是长期明文。
这篇把「盘点 → 清明文 → 钥匙串中介 → 验收 → 日志自查」放在同一台整机独享的新加坡 Mac mini 上做完。
/help 与官方文档为准。文中的服务名、钥匙串条目名是占位示例,请换成你自己的可信来源。第一步:先盘点三层 MCP 配置,找出明文
SSH 进新加坡 Mac mini(或用 UU 远程连接打开终端):
claude --version
claude mcp list
配置常见三层(路径以你本机为准):
- 用户 / 本机:
~/.claude.json - 项目:仓库
.mcp.json - 会话临时:
claude mcp add当场加的
只做只读扫描,不要把命中内容贴进聊天或工单:
# 粗筛:常见密钥形态与 env 字段(按你实际前缀再收紧)
grep -nE 'sk-|sk_live_|ghp_|api[_-]?key|token|Authorization|"env"' \
~/.claude.json 2>/dev/null | head -60
ls -la .mcp.json 2>/dev/null
grep -nE 'sk-|sk_live_|ghp_|api[_-]?key|token|"env"' .mcp.json 2>/dev/null | head -60
Cursor 用户再查项目或用户级 MCP 配置(常见在工作区 .cursor / 用户配置目录下的 mcp 相关 JSON)。原则相同:凡是把长期密钥写进 JSON 的条目,都列入改造清单。
第二步:立刻轮换已暴露的密钥,再改配置
如果扫描已命中明文:
- 到原厂(模型厂商、GitHub、云控制台等)轮换 / 吊销旧密钥。
- 确认 Git 历史、备份盘、截图里没有同一串。
- 再改配置——否则只是「文件干净了,旧钥仍有效」。
轮换完成前,先把 MCP 服务停用或移除,避免代理继续用旧钥:
# 示例:按你的服务名操作;具体 flag 以 /help 为准
claude mcp list
claude mcp remove some-mcp
第三步:用钥匙串存密钥,用启动脚本注入环境
目标形态:
- 钥匙串里存一条「服务名 + 账号」的通用密码(或应用密码)。
- MCP 的
command指向本机包装脚本;脚本用security find-generic-password取密,再export给真正的 MCP 进程。 - JSON 里只有命令路径与无敏感参数,没有
sk-...。
创建钥匙串条目(在 Mac mini 本机终端执行一次):**
# 交互输入密钥;-U 表示已存在则更新
security add-generic-password -a "$USER" -s "mcp-some-service" -w -U
包装脚本示例 ~/bin/mcp-some-service.sh:
#!/bin/zsh
set -euo pipefail
TOKEN="$(security find-generic-password -a "$USER" -s "mcp-some-service" -w)"
export SOME_MCP_TOKEN="$TOKEN"
# 用你钉死的包版本,避免再追 latest
exec npx -y [email protected]
chmod 700 ~/bin/mcp-some-service.sh
登记到 Claude Code(字段以当前版本为准):
claude mcp remove some-mcp 2>/dev/null || true
claude mcp add --transport stdio some-mcp -- "$HOME/bin/mcp-some-service.sh"
claude mcp list
若手写 JSON,形态接近:
{
"mcpServers": {
"some-mcp": {
"command": "/Users/你的用户名/bin/mcp-some-service.sh",
"args": []
}
}
}
不要写:
{
"env": { "SOME_MCP_TOKEN": "sk-把密钥写在这里" }
}
可选加强:脚本只向 MCP 暴露短期、窄 scope 的派生令牌(若上游支持),而不是把根密钥原样交给工具进程。代理侧若只需「列仓库」「读 issue」,就不要给写权限令牌。
第四步:验收——列表在线,配置无明文
固定顺序:
claude mcp list:目标服务在线 / 可连接。- 再扫一遍配置文件:不应再出现旧密钥前缀。
- 新开一条 Claude Code 会话,对只读工具做一次无害调用;确认需批准的危险工具仍被拦。
- 故意拿错钥匙串条目名启动一次,应失败且不回退到明文环境变量——避免「脚本坏了还在用 shell 里的旧 export」。
claude mcp list
grep -nE 'sk-|sk_live_|ghp_' ~/.claude.json .mcp.json 2>/dev/null || echo "配置侧未扫到常见前缀"
把「该服务用钥匙串条目 mcp-xxx,包装脚本路径,钉死版本」写进项目 CLAUDE.md 或 docs/mcp-credentials.md(仍不要写密钥),方便一周后的自己与另一个会话对齐。
第五步:会话日志自查(相关护栏)
配置干净不等于历史干净。若代理曾经读过或回显过密钥,明文可能留在 Claude Code 会话记录里。在 Mac mini 上定期扫(前缀按你实际密钥调整):
grep -rlE 'sk-[A-Za-z0-9_-]{20,}|sk_live_|ghp_[A-Za-z0-9]{20,}' \
~/.claude/projects 2>/dev/null | head
有命中就:轮换密钥 → 按官方指引清理或归档相关会话 → 确认 MCP 与 shell 启动脚本不再注入明文。不要把 grep 输出贴到公开渠道。
第六步:常开整机上的操作习惯
- 同一台权威环境:用户级 MCP、钥匙串条目、包装脚本都放在这台新加坡 Mac mini;笔记本只做只读检查,避免多机各写一套明文。
- 保住会话:
tmux new -s claude-dev,需要时再配合caffeinate,减少半夜进程被休眠打断。 - 远程接回:SSH 进 tmux 改脚本与验收;需要看桌面时用 UU 远程连接。每台机器一个固定专属地址,浏览器即可 SSH / VNC(以交付说明为准)。
- 账号边界:Claude 账号由你自己开通和登录;这里提供的是稳定合规的使用环境,不是共享或转售账号方案。
为什么放在新加坡的常开 Mac mini 上做
- 钥匙串与脚本要长期一致:凭据中介只在「同一台长期开机的 macOS」上最好维护;换机、重装会打乱「脚本路径 + 钥匙串条目」的对应关系。
- 真 Mac 工具链:需要 macOS 钥匙串、
security命令、以及部分只在 Darwin 上顺手的开发 MCP。 - 整机独享:代码、登录态、钥匙串与其他客户隔离;退租抹机时密钥生命周期也跟着结束。
- 远程可接回:出问题可以 SSH 或 UU 远程连接当场轮换与复验;实际延迟取决于你本地的网络线路。
Zumac.Ai 提供位于新加坡的实体 Mac mini M6,整机独享,支持 SSH 与 UU 远程连接,FileVault 全盘加密,退租时抹机重装。新客户整机租用 ¥999/月起,季付 ¥2,697.30,半年付 6 送 1 为 ¥5,994,年付 12 送 2 为 ¥11,988;已购买客户续费保持原价。新客户首单自审核开通当天起租,续费及老客户新订单自付款当天起租。建议先租一个月,把「盘点明文 → 钥匙串中介 → mcp list 验收 → 日志 grep」跑通。
小结
- MCP 配置文件里不要放长期明文 Key / PAT。
- 用 macOS 钥匙串存密,用包装脚本在启动时注入环境;JSON 只留命令路径。
claude mcp list+ 配置再扫描做验收;升级或换钥时同步改钥匙串条目。- 定期 grep
~/.claude/projects,命中即轮换。 - 把权威运行环境固定在新加坡常开 Mac mini,比多台设备各塞一份明文更可控。
