Agent工坊

【Agent工坊】MCP Server 密钥管理实战:3种方案彻底杜绝 API Key 泄漏

打开同事的 MCP Server 代码,API Key 赫然躺在代码里——你不需要成为安全专家也能看出这是定时炸弹。今天分享 3 种经过生产验证的密钥管理方案,从基础环境变量到企业级凭证网关,每种都有可直接复制的配置。

痛点:AI Agent 的安全盲区

2026 年 7 月,OneCLI 在 HN 上获得了 103 个 upvote——这是一个专门为 AI Agent 设计的开源凭证网关。它之所以引发讨论,是因为戳中了 AI 创业者的一个集体痛点:

每个 AI Agent 都要接触 API Key,但没人认真管理过它们。

一个典型的 AI 创业者工作流里,至少涉及这些密钥:

- OpenAI API Key(GPT-4o / GPT-5)
- Anthropic API Key(Claude Opus 5 / Fable 5)
- GitHub Personal Access Token(代码仓库访问)
- 微信公众号 AppSecret(内容发布)
- Cloudflare API Key(网站部署)
- Notion / Airtable / Slack API Token(工作流集成)
- 数据库密码(PostgreSQL / Redis)

当你的 Agent 调用 MCP Server 来完成这些操作时,密钥是怎么传给它的?

最常见的做法——也是最危险的:直接写在代码或配置文件里。

# ❌ 危险:硬编码密钥
mcp_config = {
    "mcpServers": {
        "notion": {
            "command": "python",
            "args": ["-m", "notion_mcp"],
            "env": {
                "NOTION_API_KEY": "secret_abc123xyz...",  # 💣 定时炸弹
            }
        }
    }
}

一旦代码被不小心推到公开仓库,或者团队新成员 fork 了代码库,密钥就泄露了。而 AI Agent 的自动化特性让问题更严重——它可能在你睡觉时用泄露的密钥做了上千次 API 调用。

方案对比:选对工具,事半功倍

方案 安全等级 部署复杂度 适用场景
环境变量注入 ⭐⭐ 极低 个人项目、本地开发
Secret Manager 集成 ⭐⭐⭐⭐ 团队协作、CI/CD
凭证网关(OneCLI) ⭐⭐⭐⭐⭐ 中高 生产环境、多Agent

方案1:环境变量注入(最快上手)

这是最基础的方案,但做对了依然有效。核心原则:密钥不能出现在任何会被 git 追踪的文件里。

1.1 使用 .env 文件 + .gitignore

# .env(绝对不能提交到 git)
OPENAI_API_KEY=sk-proj-abc123...
ANTHROPIC_API_KEY=sk-ant-def456...
GITHUB_TOKEN=ghp_ghi789...
# .gitignore — 必须加这两行
.env
.env.local
.env.*.local

1.2 在 Claude Code 的 CLAUDE.md 中安全引用

Claude Code 启动时会自动读取项目根目录的 CLAUDE.md。你可以在这里描述密钥的位置和使用方式,而不是密钥本身:

# CLAUDE.md — 密钥管理说明

本项目使用以下 API,密钥存储在 `.env` 文件(不提交 git):

- OpenAI: 通过环境变量 OPENAI_API_KEY 自动加载
- GitHub: 通过环境变量 GITHUB_TOKEN,权限仅需 `repo` scope
- Cloudflare: 参考 `.env.example` 中的变量名

**安全规则**- 永远不要在代码中硬编码密钥
- 如果需要在 MCP Server 中使用密钥,通过 `env` 字段注入
- 密钥泄露后的处理流程:立即在对应平台 revoke → 更新 .env → 通知团队

1.3 MCP Server 配置安全示例

// .cursor/mcp.json — Claude Code / Hermes 通用
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "notion": {
      "command": "python",
      "args": ["-m", "notion_mcp_server"],
      "env": {
        "NOTION_API_KEY": "${NOTION_API_KEY}"
      }
    }
  }
}

关键的 ${GITHUB_TOKEN} 语法:MCP 客户端(Claude Code / Hermes Agent)在启动 Server 进程时会从当前 shell 环境中读取变量值。确保你在启动 AI 工具前执行了 source .env 或使用了 direnv。

方案2:Secret Manager 集成(团队级别)

当你的项目从一个人的 side project 变成团队协作时,.env 文件就不够了。你需要一个中心化的密钥管理。

2.1 使用 1Password CLI + MCP

Hermes Agent v0.19.0 原生支持 1Password 和 Bitwarden 作为密钥源。配置方式:

// ~/.hermes/config.json
{
  "credential_source": {
    "provider": "1password",
    "vault": "AI-Neican-Production",
    "item_mapping": {
      "openai": "OpenAI API Key",
      "anthropic": "Anthropic API Key",
      "github": "GitHub Token"
    }
  }
}

当 Hermes Agent 需要调用 OpenAI 时,它会通过 1Password CLI (op) 动态读取密钥,用完即丢弃。密钥永远不需要出现在环境变量中。

2.2 自己搭建一个简单的 Secret Server

如果你不想依赖第三方服务,可以用 Python 快速搭建一个本地 Secret Server。核心思路:密钥存在加密的 SQLite 数据库中,通过本地 HTTP API 按需读取。

# secret_server.py — 本地密钥管理服务
import sqlite3, os, secrets
from flask import Flask, request, jsonify

app = Flask(__name__)
DB_PATH = os.path.expanduser("~/.agent-secrets/secrets.db")
AUTH_TOKEN = os.environ.get("SECRET_SERVER_TOKEN", secrets.token_hex(32))

def init_db():
    os.makedirs(os.path.dirname(DB_PATH), exist_ok=True)
    conn = sqlite3.connect(DB_PATH)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS secrets (
            key TEXT PRIMARY KEY,
            value TEXT NOT NULL,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    """)
    conn.commit()
    return conn

@app.route("/secret/<key>", methods=["GET"])
def get_secret(key):
    token = request.headers.get("Authorization", "")
    if token != f"Bearer {AUTH_TOKEN}":
        return jsonify({"error": "unauthorized"}), 401

    conn = sqlite3.connect(DB_PATH)
    row = conn.execute("SELECT value FROM secrets WHERE key = ?", (key,)).fetchone()
    conn.close()

    if row:
        return jsonify({"key": key, "value": row[0]})
    return jsonify({"error": "not found"}), 404

@app.route("/secret/<key>", methods=["PUT"])
def set_secret(key):
    token = request.headers.get("Authorization", "")
    if token != f"Bearer {AUTH_TOKEN}":
        return jsonify({"error": "unauthorized"}), 401

    data = request.json
    conn = sqlite3.connect(DB_PATH)
    conn.execute(
        "INSERT OR REPLACE INTO secrets (key, value, updated_at) VALUES (?, ?, CURRENT_TIMESTAMP)",
        (key, data["value"])
    )
    conn.commit()
    conn.close()
    return jsonify({"status": "ok"})

if __name__ == "__main__":
    init_db()
    print(f"Auth token: {AUTH_TOKEN}")  # 记住这个 token
    app.run(host="127.0.0.1", port=9877)

在 MCP Server 中使用:

# 在你的 MCP Server 中读取密钥
import os, requests

SECRET_SERVER = "http://127.0.0.1:9877"
AUTH_TOKEN = os.environ["SECRET_SERVER_TOKEN"]

def get_api_key(service: str) -> str:
    """从本地 Secret Server 获取密钥"""
    resp = requests.get(
        f"{SECRET_SERVER}/secret/{service}",
        headers={"Authorization": f"Bearer {AUTH_TOKEN}"}
    )
    if resp.status_code == 200:
        return resp.json()["value"]
    raise RuntimeError(f"Secret not found: {service}")

# 使用示例
openai_key = get_api_key("openai")

方案3:OneCLI 凭证网关(企业级)

OneCLI 是 2026 年 7 月 23 日在 HN 上火起来的开源项目(103 pts),专门解决 AI Agent 的凭证管理问题。它的核心设计理念是:Agent 永远接触不到真实的密钥

3.1 OneCLI 工作原理

┌─────────────┐     请求服务      ┌──────────────┐
│  AI Agent   │ ────────────────→ │   OneCLI     │
│  (Claude/   │                   │  Gateway     │
│   Hermes)   │ ←──────────────── │              │
└─────────────┘   返回结果          └──────┬───────┘
                                           │ 持有真实密钥
                                           ▼
                                    ┌──────────────┐
                                    │  API 服务     │
                                    │ (OpenAI/GH等)│
                                    └──────────────┘

Agent 不直接调用 OpenAI API,而是通过 OneCLI Gateway 发起请求。Gateway 负责注入密钥、审计日志、速率限制。Agent 看到的是一个"不需要密钥"的 API 端点。

3.2 快速部署 OneCLI

# 安装
git clone https://github.com/onecli/onecli.git
cd onecli
npm install

# 配置 providers
cat > providers.yaml << 'EOF'
providers:
  openai:
    type: openai
    api_key: "${OPENAI_API_KEY}"
    base_url: https://api.openai.com/v1
  anthropic:
    type: anthropic
    api_key: "${ANTHROPIC_API_KEY}"
  github:
    type: github
    token: "${GITHUB_TOKEN}"

policies:
  - name: "agent-default"
    max_tokens_per_hour: 100000
    allowed_models: ["gpt-4o", "gpt-4o-mini", "claude-opus-5"]
EOF

# 启动 Gateway(监听 localhost:8787)
npm start

然后在 Claude Code / Hermes 中配置使用 OneCLI 作为代理:

// 将 API Base URL 指向 OneCLI Gateway
{
  "providers": {
    "openai": {
      "base_url": "http://127.0.0.1:8787/openai",
      "api_key": "onecli-agent-token-abc123"  // 这是 Gateway Token,不是真实密钥
    },
    "anthropic": {
      "base_url": "http://127.0.0.1:8787/anthropic",
      "api_key": "onecli-agent-token-abc123"
    }
  }
}

关键点:Agent 持有的只是 OneCLI 的 Gateway Token。即使这个 Token 泄露,也无法直接访问 API 服务——除非攻击者也控制了 OneCLI 所在的主机。

3.3 审计能力

OneCLI 的优势不仅是安全隔离,还有完整的调用审计:

# 查看最近 100 条 API 调用记录
curl -H "Authorization: Bearer admin-token" \
  http://127.0.0.1:8787/audit?limit=100

# 输出示例:
# [2026-07-25 14:32:01] Agent:hermes-v0.19 → OpenAI GPT-4o: 2,341 tokens ($0.012)
# [2026-07-25 14:32:15] Agent:claude-code  → Anthropic Opus 5: 15,832 tokens ($0.237)
# [2026-07-25 14:30:42] Agent:openclaw    → GitHub API: 3 requests

这对 AI 创业者意味着:你可以精确知道每个 Agent 花了多少钱,有没有异常调用。上个月就有创业者在审计日志里发现,某个测试 Agent 因为配置错误,一晚上调用了 47 万 token 的 Opus 5——按 Opus 5 的定价,那就是 $7.05 的浪费

实操:给 Hermes Agent 配置安全的 MCP Server

假设你正在用 Hermes Agent 运营一个 AI 内容创业项目,需要接入以下 MCP Server:

  • github-server:自动提交草稿到私有仓库
  • notion-server:将选题同步到 Notion 数据库
  • wechat-server:发布文章到微信公众号草稿箱

步骤一:创建加密密钥存储

# 创建密钥目录
mkdir -p ~/.hermes/secrets
chmod 700 ~/.hermes/secrets

# 生成加密密钥
python3 -c "import secrets; print(secrets.token_hex(32))" > ~/.hermes/secrets/master.key
chmod 600 ~/.hermes/secrets/master.key

步骤二:使用 Hermes 内置的 Bitwarden 集成

Hermes Agent v0.19.0 的 Bitwarden 集成可以通过 credential_source 配置:

// ~/.hermes/config.json — credential_source 配置
{
  "credential_source": {
    "provider": "bitwarden",
    "auto_lock_timeout": 300,
    "item_mapping": {
      "GITHUB_TOKEN": "GitHub - AI Neican Bot",
      "NOTION_API_KEY": "Notion - Content DB",
      "WECHAT_APPSECRET": "WeChat Official Account"
    }
  }
}

首次使用时会提示输入 Bitwarden 主密码,Hermes 会在会话期间缓存解锁状态,5 分钟无操作自动锁定。

步骤三:在 MCP 配置中使用 ${} 引用

// ~/.hermes/mcp.json
{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    },
    "notion": {
      "command": "python",
      "args": ["-m", "notion_mcp_server"],
      "env": {
        "NOTION_API_KEY": "${NOTION_API_KEY}"
      }
    },
    "wechat": {
      "command": "python",
      "args": ["/home/agent/.hermes/projects/ai-neican/mcp/wechat_server.py"],
      "env": {
        "WECHAT_APPID": "wxe3840e4d9c6e52ba",
        "WECHAT_APPSECRET": "${WECHAT_APPSECRET}"
      }
    }
  }
}

Hermes 在启动每个 MCP Server 进程时,会从 Bitwarden 获取 ${} 引用的密钥值并注入到子进程的环境变量中。密钥在整个过程中只在内存中存在,不会落盘。

步骤四:验证安全配置

# 检查 git 仓库中是否意外包含密钥
git log --all --full-history -- '*.env' '.env.*'

# 检查当前环境变量是否泄露密钥
env | grep -i 'key\|secret\|token' | grep -v '^_'

# 验证 MCP Server 无法在日志中输出密钥
hermes agent run --check-creds --dry-run

最佳实践 Checklist

每次启动新的 AI Agent 或 MCP Server 时,对照这个清单:

  • [ ] 密钥不在任何代码文件或公开配置中
  • [ ] .env 文件已在 .gitignore 中排除
  • [ ] .env.example 提供了模板但无真实密钥
  • [ ] MCP Server 通过环境变量 ${} 注入密钥
  • [ ] 使用最小权限原则(GitHub Token 只给 repo 而非 admin
  • [ ] 生产环境使用 Bitwarden / 1Password / OneCLI 等密钥管理
  • [ ] 密钥泄露应急方案已就位(各平台 revoke 链接已收藏)
  • [ ] API 调用有成本监控(至少每周检查一次账单)

总结

密钥管理是 AI Agent 基础设施中最容易被忽视的一环——因为它"看不见"。但正如 OneCLI 在 HN 上的讨论所示,随着 AI Agent 从个人实验走向生产环境,凭证管理正从"nice to have"变成"必须要有"

三个方案没有绝对的好坏:
- 如果只是个人项目,环境变量 + .gitignore已经够用
- 如果团队协作,Secret Manager(Bitwarden/1Password)是性价比最高的选择
- 如果 Agent 在生产环境处理敏感数据,OneCLI 凭证网关是安全性的终局方案

今天就可以开始:检查你的 MCP Server 配置,把所有硬编码密钥替换成环境变量引用。花 10 分钟,换一晚安睡。


AI创业 #Agent工坊 #MCP协议 #密钥管理 #安全实践 #一人公司