Cursor
~/.cursor/mcp.json(用户级)或 <project>/.cursor/mcp.json(项目级)。JSON 结构与 Claude Code 同构,改法完全相同。
Deployment
这一页是整个站点最具体的一页。它回答的不是「原理是什么」,而是你要改哪一行、改完怎么自己验证。
配置路径证据
本页所有配置文件路径均为 2026-07 在一台 macOS 机器上实测(已安装 Claude Code 与 Codex CLI)。托管策略文件的路径已确认存在性,schema 未逐厂商验证 —— 见页尾待验证清单。
The mechanism
我们不改 agent,不写插件,不装内核扩展。 我们改 MCP server 的启动命令,让 agent 去启动我们的二进制,由我们再去启动真正的 MCP server。
BEFORE agent ──fork──> MCP server process holds GITHUB_PAT AFTER agent ──fork──> agentpam ──fork──> MCP server env has no secrets │ └──> control plane attest / authorize / mint short-lived cred / audit
tsh mcp connect 和 Keycard 的 keycard run 用的是同一个机制 —— 它是 stdio 场景下唯一不需要客户改代码的插入点。
Integration forms
| 形态 | 何时用 | 你要改什么 | 我们看得到什么 |
|---|---|---|---|
| A. 命令包装(本地 stdio) | agent 在笔记本上直连本地 MCP server —— 约 85% 的真实情况 | MCP 配置里的 command 一行 | 每次 tools/call + 出站凭据 |
| B. 我们当 AS(远程 HTTP + 已有网关) | 你已经有 MCP Gateway | 网关配置一行(指向我们的 AS) | 每次调用的授权决策 |
| C. 本地 loopback 代理 | 远程 MCP server,但你没有网关 | MCP 配置里的 url 指向 127.0.0.1 | 全量流量 |
A 和 B 是主力,通常同时存在 —— 因为真实企业里两种 MCP server 都有。
Per-agent config
| 文件 | 作用域 | agent 能改吗 |
|---|---|---|
~/.claude.json | 用户全局(顶层 mcpServers) | ⚠️ 可以 |
<project>/.mcp.json | 项目级 | ⚠️ 可以 |
~/.claude/settings.json | 用户设置 | ⚠️ 可以 |
/Library/Application Support/ClaudeCode/managed-settings.json(macOS)/etc/claude-code/managed-settings.json(Linux) | 企业托管策略 | ✅ root 拥有,agent 改不了 |
{ "mcpServers": { "github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxx" } } } }
{ "mcpServers": { "github": { "command": "/usr/local/bin/agentpam", "args": ["run", "github", "--", "npx", "-y", "@modelcontextprotocol/server-github"] } } }
env 块消失了。 凭据不再存在于任何配置文件、任何进程环境变量、任何磁盘位置。这一行差异就是 Tier 0 的全部内容。
配置在 ~/.codex/config.toml(TOML 格式,与 Claude Code 的 JSON 不同),MCP server 在 [mcp_servers.<name>] 段下。
[mcp_servers.github] command = "npx" args = ["-y", "@modelcontextprotocol/server-github"] env = { GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_xxxxxxxxxxxx" }
[mcp_servers.github] command = "/usr/local/bin/agentpam" args = ["run", "github", "--", "npx", "-y", "@modelcontextprotocol/server-github"]
~/.cursor/mcp.json(用户级)或 <project>/.cursor/mcp.json(项目级)。JSON 结构与 Claude Code 同构,改法完全相同。
<project>/.vscode/mcp.json 或用户 settings,同构。⚠️ 注意:VS Code 在设计上把密钥放进 inputs 而非配置文件明文 —— 它是少数几个默认姿态较好的 —— 但仍然把凭据交给 MCP server 进程。
均为 JSON/YAML 的 command + args + env 三元组。同一套包装逻辑通吃,只是文件路径与语法不同。
command + args + env 三元组去 fork 子进程。所以一个包装器覆盖所有 agent,我们不需要为每个 agent 写适配层。
What it does
agentpam run 在做什么1. read own config: control-plane address, machine identity, this server's blueprint 2. ask the Local Attestor for device/process attestation (Secure Enclave signature) 3. exchange human SSO assertion + agent instance assertion for Ts session token, DPoP-bound, 5-15 min 4. fork the real MCP server as a child process * scrub the environment explicitly: strip *_TOKEN / *_KEY / *_SECRET / AWS_* ... * the child receives no long-lived credential at all 5. relay JSON-RPC on stdin/stdout: · tools/list ──> record tool descriptions, TOFU-pin them (rug-pull detection) · tools/call ──> send to the PDP for a decision ├ deny ──> return an error; the request never reaches the server └ allow ──> mint Tup (60-300s) and inject it outbound 6. write an audit event per call (including traceparent), push to the control plane 7. task termination / CAEP revocation event ──> invalidate the session immediately
Form B
你已经有 MCP Gateway 时,客户端一行都不用改。全部改动在网关侧。
// 1) the gateway publishes protected resource metadata (RFC 9728, mandatory) // GET /.well-known/oauth-protected-resource { "resource": "https://mcp.customer.internal", "authorization_servers": ["https://agentpam.customer.internal"] } // 2) on 401 the gateway returns // WWW-Authenticate: Bearer resource_metadata= // "https://mcp.customer.internal/.well-known/oauth-protected-resource" // 3) the gateway exchanges for the upstream credential (agentgateway shown) { "backendAuth": { "oauthTokenExchange": { "tokenEndpoint": "https://agentpam.customer.internal/token", "grantType": "urn:ietf:params:oauth:grant-type:token-exchange" } } }
authorization_servers 必须至少含一个 AS。但规范明确允许那个 AS 就是网关自己(It may be hosted with the resource server or a separate entity.),所以「任何合规网关都能指向我们」是错的 —— 实测 12 家中 4 家干净支持。⚠️ 第 2 步的 WWW-Authenticate 自 2025-11-25 规范(SEP-985)起已变为可选。
Enterprise rollout
单机改配置是 POC。企业部署靠这三步。
| 步骤 | 机制 | 工具 |
|---|---|---|
| ① 分发二进制 | 签名的 pkg / deb / rpm,或容器 | Jamf · Intune · Ansible · Munki |
| ② 下发托管策略 | root 拥有的 managed settings,定义所有 MCP server 指向包装器 | 同上(MDM 推文件) |
| ③ 锁定 | 开启「仅允许托管 MCP 配置」,禁止用户级覆盖 | 各 agent 的企业策略开关 |
docker load 导入。POC acceptance
这七项不需要我们在场。你自己跑,当场看结果 —— 这是我们希望被检验的方式。
| # | 检查 | 期望结果 |
|---|---|---|
| 1 | grep -rE "ghp_|sk-|AKIA" ~/.claude.json ~/.cursor ~/.codex | 无命中(凭据已从配置移除) |
| 2 | ps eww <mcp-server-pid> 看子进程环境变量 | 无任何 *_TOKEN / *_KEY |
| 3 | 让 agent 调用一个被策略拒绝的工具 | 请求不抵达上游,审计有拒绝记录 |
| 4 | 让 agent 调用超参数上限的操作(如 refund $2500 > 上限 $500) | 参数级拒绝 |
| 5 | 在上游 API 日志里看一次调用 | 携带短时凭据,可关联到具体的人 + agent + 任务 |
| 6 | 抓 agent 进程内存 / transcript 搜上游凭据 | 找不到 |
| 7 | 标记任务完成,再让 agent 调用 | 立即拒绝(即使 token 未到期) |
Known limitations
诚实列出。这些不是待办事项,是这个方案的边界。
| 限制 | 说明 | 缓解 |
|---|---|---|
| 用户可以绕过 | 开发者可以自己在 shell 里 export GITHUB_TOKEN=… && curl | Tier 2 出站兜底 / Tier 3 OS 级执行(V2);但根本上这是内部人风险,不是本产品的威胁模型 |
| 配置可被改回 | 若未下发 root 托管策略,用户或 agent 可以改回原配置 | 企业部署必须用 MDM + 托管策略。这是硬要求,不是选项 |
| 首次注册需联网到控制平面 | 气隙内网可达即可,但不能完全离线 | 内网控制平面 |
| 增加一跳延迟 | 每次 tools/call 多一次决策往返 | 目标 P99 < 200ms —— ⚠️ 尚未实测(Gap G-05) |
| 不覆盖非 MCP 路径 | agent 直接调 SDK / psql / kubectl 不经过我们 | Tier 0 已在原理上覆盖大部分(凭据本来就不在 agent 手里);残留凭据靠 Tier 2 / 3 |
| ID | 项目 | 状态 |
|---|---|---|
| G-04 | 各网关对形态 B 的支持度矩阵 | 仅 agentgateway 验证过 |
| G-05 | 端到端延迟 P99 | 未实测 |
| G-15 | 各 agent 托管策略文件的确切路径与 schema | 路径存在性已验证;schema 未验证 —— 需逐个查官方文档 |
| G-16 | 环境变量清洗的完备性 | 需建立黑名单 + 白名单双策略并测试逃逸 |