背景:MCP 的认证现状
MCP(Model Context Protocol)连接 AI 工具和外部服务时,HTTP 传输层需要认证。目前绝大多数客户端(Claude Code、OpenClaw 等)的做法是静态 headers:
json
{
"mcpServers": {
"jina": {
"type": "http",
"url": "https://mcp.jina.ai/v1",
"headers": {
"Authorization": "Bearer jina_6b..."
}
}
}
}
简单直接,但有三个企业场景下的硬伤:
| 问题 | 说明 |
|---|---|
| Token 明文暴露 | 配置文件里躺着长期有效的密钥,泄露即全损 |
| 无法自动轮换 | 短期 Token(OAuth、SSO)过期后必须手动更新 |
| 多服务器管理成本 | 10 个 MCP 服务器 = 10 份独立的认证配置 |
Claude Code 的解法:headersHelper
Claude Code 在 v2.1.85 引入了 headersHelper 机制------用外部脚本动态生成认证头。
工作原理
ini
Claude Code 启动
→ 发现 MCP 服务器配置了 headersHelper
→ 注入环境变量:
CLAUDE_CODE_MCP_SERVER_NAME=gitlab
CLAUDE_CODE_MCP_SERVER_URL=https://gitlab.example.com/mcp
→ 执行指定脚本(10 秒超时)
→ 脚本输出 JSON 到 stdout
→ 将输出合并为 HTTP 请求头
→ 连接 MCP 服务器
配置方式
json
{
"mcpServers": {
"gitlab": {
"type": "http",
"url": "https://gitlab.example.com/mcp",
"headersHelper": "/opt/bin/mcp-auth.sh"
}
}
}
脚本规范
输入:通过环境变量传入
| 环境变量 | 值 |
|---|---|
CLAUDE_CODE_MCP_SERVER_NAME |
配置中的服务器名(如 gitlab) |
CLAUDE_CODE_MCP_SERVER_URL |
服务器 URL |
输出:stdout 输出一个 JSON 对象(string key-value)
json
{"Authorization": "Bearer eyJhbGciOi..."}
约束:
- 在 shell 中执行,超时 10 秒
- 每次连接(启动和重连)都会重新执行,无缓存
- 动态 headers 覆盖同名静态 headers
实际示例:一个脚本管所有服务器
bash
#!/bin/bash
# /opt/bin/mcp-auth.sh
case "$CLAUDE_CODE_MCP_SERVER_NAME" in
gitlab)
# 从 macOS Keychain 取 token
TOKEN=$(security find-generic-password -s "mcp-gitlab" -w)
;;
jira)
# 从 HashiCorp Vault 取 token
TOKEN=$(vault kv get -field=token secret/mcp/jira)
;;
internal-api)
# 调 SSO 接口获取短期 token
TOKEN=$(curl -s https://sso.corp.com/oauth/token \
--data "grant_type=client_credentials&client_id=mcp" \
-u "$USER:$(cat ~/.sso-secret)" | jq -r '.access_token')
;;
*)
echo '{}' && exit 0
;;
esac
echo "{\"Authorization\": \"Bearer $TOKEN\"}"
所有服务器指向同一个脚本:
json
{
"mcpServers": {
"gitlab": { "url": "...", "headersHelper": "/opt/bin/mcp-auth.sh" },
"jira": { "url": "...", "headersHelper": "/opt/bin/mcp-auth.sh" },
"internal-api": { "url": "...", "headersHelper": "/opt/bin/mcp-auth.sh" }
}
}
更多玩法
从 AWS Secrets Manager 取 token:
bash
#!/bin/bash
SECRET_NAME="mcp/$CLAUDE_CODE_MCP_SERVER_NAME"
TOKEN=$(aws secretsmanager get-secret-value \
--secret-id "$SECRET_NAME" \
--query SecretString --output text | jq -r '.token')
echo "{\"Authorization\": \"Bearer $TOKEN\"}"
从 1Password CLI 取 token:
bash
#!/bin/bash
TOKEN=$(op read "op://MCP/$CLAUDE_CODE_MCP_SERVER_NAME/token")
echo "{\"Authorization\": \"Bearer $TOKEN\"}"
内联写法(简单场景):
json
{
"headersHelper": "echo '{\"Authorization\": \"Bearer '\"$(op read op://MCP/jina/token)\"'\"}'"
}
这不是 MCP 官方标准
需要明确:headersHelper 是 Claude Code 的私有扩展,不是 MCP 协议标准的一部分。
MCP 标准只定义了:
headers:静态 key-value 头- OAuth 2.1 流程(RFC 8414 发现 + PKCE)
但 headersHelper 这种"委托外部脚本生成认证头"的模式,有可能成为事实标准------因为它解决了 OAuth 覆盖不到的场景(Kerberos、mTLS token、企业 SSO、Vault 集成等)。
OpenClaw 的现状与改造思路
OpenClaw 目前 只支持静态 headers,不支持动态生成。相关 Issue(#61611)已提出需求,但尚未实现。
要实现类似 headersHelper 的能力,需要改造的核心路径:
1. 配置层:扩展 MCP server schema
在 mcp.servers 的配置结构中增加 headersHelper 字段:
typescript
// 当前
interface McpServerConfig {
url: string;
headers?: Record<string, string>;
transport?: 'sse' | 'streamable-http';
}
// 改造后
interface McpServerConfig {
url: string;
headers?: Record<string, string>;
headersHelper?: string; // 新增:外部脚本路径或内联命令
transport?: 'sse' | 'streamable-http';
}
2. 运行时:MCP 客户端连接前执行脚本
在 MCP 客户端建立 HTTP 连接之前,检查是否配置了 headersHelper,如果有:
c
读取 headersHelper 配置
→ spawn 子进程执行脚本
→ 注入环境变量(服务器名、URL)
→ 捕获 stdout,解析 JSON
→ 与静态 headers 合并(动态优先)
→ 传递给 HTTP 客户端
核心伪代码:
typescript
async function resolveHeaders(serverName: string, config: McpServerConfig) {
const staticHeaders = config.headers ?? {};
if (!config.headersHelper) return staticHeaders;
const { stdout } = await execWithTimeout(config.headersHelper, {
env: {
...process.env,
MCP_SERVER_NAME: serverName, // OpenClaw 可以用自己的变量名
MCP_SERVER_URL: config.url,
},
timeout: 10_000,
});
const dynamicHeaders = JSON.parse(stdout);
return { ...staticHeaders, ...dynamicHeaders }; // 动态覆盖静态
}
3. 重连时刷新
MCP 连接断开重连时,需要重新执行 headersHelper(而不是复用上次的结果),确保短期 token 被刷新。
改造总结
| 模块 | 改什么 | 工作量 |
|---|---|---|
| 配置 schema | 增加 headersHelper 字段 |
小 |
| MCP 客户端 | 连接前执行脚本、解析输出、合并 headers | 中 |
| 重连逻辑 | 重连时重新执行脚本 | 小 |
| CLI 命令 | openclaw mcp set 支持设置 headersHelper |
小 |
| 文档 | 配置说明 + 脚本示例 | 小 |
核心改动集中在 MCP 客户端的 HTTP 传输层,是一个边界清晰、风险可控的改造。