Cursor
~/.cursor/mcp.json (user level) or <project>/.cursor/mcp.json (project level). Structurally identical JSON to Claude Code — the change is exactly the same.
Deployment
This is the most concrete page on the site. It does not answer “how does it work” — it answers which line you change, and how you verify it yourself afterwards.
Evidence for these config paths
Every config path on this page was verified on a real macOS machine in 2026-07 (with Claude Code and Codex CLI installed). Managed-policy file paths were confirmed to exist as concepts; the schema was not verified per vendor — see the open items at the foot of this page.
The mechanism
We do not modify the agent, write a plugin, or install a kernel extension. We change the MCP server's launch command, so the agent starts our binary, and we start the real 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 and Keycard's keycard run use the same mechanism — it is the only insertion point for stdio that requires no code change from the customer.
Integration forms
| Form | When to use it | What you change | What we see |
|---|---|---|---|
| A. Command wrapping (local stdio) | The agent talks directly to a local MCP server on a laptop — roughly 85% of real cases | One command line in the MCP config | Every tools/call + the outbound credential |
| B. We are the AS (remote HTTP + existing gateway) | You already run an MCP Gateway | One line of gateway config (pointing at our AS) | The authorization decision on every call |
| C. Local loopback proxy | Remote MCP server, but you have no gateway | Point the url in the MCP config at 127.0.0.1 | All traffic |
A and B are the main paths and usually coexist — because real enterprises run both kinds of MCP server.
Per-agent config
| File | Scope | Can the agent edit it? |
|---|---|---|
~/.claude.json | User global (top-level mcpServers) | ⚠️ Yes |
<project>/.mcp.json | Project level | ⚠️ Yes |
~/.claude/settings.json | User settings | ⚠️ Yes |
/Library/Application Support/ClaudeCode/managed-settings.json (macOS)/etc/claude-code/managed-settings.json (Linux) | Enterprise managed policy | ✅ root-owned; the agent cannot |
{ "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 block disappears. The credential no longer exists in any config file, any process environment variable, or any location on disk. That single difference is the whole of Tier 0.
Config lives at ~/.codex/config.toml (TOML, unlike Claude Code's JSON), with MCP servers under [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 (user level) or <project>/.cursor/mcp.json (project level). Structurally identical JSON to Claude Code — the change is exactly the same.
<project>/.vscode/mcp.json or user settings; same shape. ⚠️ Note: VS Code deliberately puts secrets in inputs rather than plaintext in the config file — one of the few with a good default posture — but it still hands the credential to the MCP server process.
All are a command + args + env triple in JSON or YAML. The same wrapping logic covers all of them; only the file path and syntax differ.
command + args + env triple. So one wrapper covers every agent, and we do not need a per-agent adapter layer.
What it does
agentpam run actually does1. 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
If you already run an MCP Gateway, not a single line changes on the client. Everything happens on the gateway side.
// 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 must name at least one AS. But the spec explicitly permits that AS to be the gateway itself (It may be hosted with the resource server or a separate entity.), so “any conformant gateway can point at us” is false — 4 of 12 tested support it cleanly. ⚠️ Step 2's WWW-Authenticate became optional in the 2025-11-25 spec (SEP-985).
Enterprise rollout
Editing config on one machine is a POC. Enterprise deployment rests on three steps.
| Step | Mechanism | Tooling |
|---|---|---|
| ① Distribute the binary | Signed pkg / deb / rpm, or a container | Jamf · Intune · Ansible · Munki |
| ② Push managed policy | root-owned managed settings that point every MCP server at the wrapper | Same (MDM file push) |
| ③ Lock it | Enable “managed MCP config only”, forbid user-level overrides | Each agent's enterprise policy switch |
docker load.POC acceptance
None of these seven needs us in the room. Run them, watch the result — this is how we want to be tested.
| # | Check | Expected result |
|---|---|---|
| 1 | grep -rE "ghp_|sk-|AKIA" ~/.claude.json ~/.cursor ~/.codex | No hits (credentials removed from config) |
| 2 | ps eww <mcp-server-pid> to inspect the child's environment | No *_TOKEN / *_KEY at all |
| 3 | Have the agent call a tool the policy denies | The request never reaches upstream; the denial is in the audit log |
| 4 | Have the agent exceed a parameter limit (e.g. refund $2500 against a $500 cap) | Parameter-level denial |
| 5 | Inspect one call in the upstream API's logs | Carries a short-lived credential, attributable to a specific human + agent + task |
| 6 | Dump the agent's process memory / transcript and search for the upstream credential | Not found |
| 7 | Mark the task complete, then have the agent call again | Immediately denied — even though the token has not expired |
Authorization header the upstream actually received.
Known limitations
Listed honestly. These are not a backlog — they are the boundary of this approach.
| Limitation | Detail | Mitigation |
|---|---|---|
| A user can bypass it | A developer can just run export GITHUB_TOKEN=… && curl in their own shell | Tier 2 egress backstop / Tier 3 OS-level enforcement (V2); but fundamentally this is insider risk, and outside this product's threat model |
| The config can be reverted | Without a root-owned managed policy, a user or the agent can put the old config back | Enterprise deployment must use MDM + managed policy. That is a hard requirement, not an option |
| First registration needs to reach the control plane | Reachable on an internal network is enough, but it cannot be fully offline | Internal control plane |
| It adds a hop of latency | Every tools/call costs one extra decision round trip | Target P99 < 200ms — ⚠️ not yet measured (Gap G-05) |
| It does not cover non-MCP paths | An agent calling an SDK, psql, or kubectl directly does not pass through us | Tier 0 covers most of this in principle (the credential was never in the agent's hands); residual credentials fall to Tier 2 / 3 |
| ID | Item | Status |
|---|---|---|
| G-04 | Per-gateway support matrix for Form B | Only agentgateway verified |
| G-05 | End-to-end P99 latency | Not measured |
| G-15 | Exact managed-policy path and schema per agent | Path existence verified; schema not verified — needs per-vendor documentation review |
| G-16 | Completeness of environment-variable scrubbing | Needs a blacklist + whitelist dual strategy and escape testing |