Claude Code Integration
Claude Code is a CLI-based agent that connects to MCP servers for tools like GitHub, databases, and file systems. The Agent Receipts proxy wraps any MCP server transparently — Claude Code doesn’t know or care that the proxy is there.
Prerequisites
Section titled “Prerequisites”-
A signing key pair generated (see below)
-
Claude Code installed (
npm install -g @anthropic-ai/claude-code) -
The MCP server you want to audit. The examples below wrap GitHub’s official MCP server:
Terminal window brew install github-mcp-serverThis puts a
github-mcp-serverbinary on your$PATH. Verify withwhich github-mcp-server.
Generate a signing key
Section titled “Generate a signing key”mcp-proxy init --name github-proxy# creates ~/.agent-receipts/github-proxy.pem (0600) and ~/.agent-receipts/github-proxy.pem.pubRe-running init is safe — it warns and skips if the key already exists. Use absolute paths everywhere — Claude Code launches MCP servers with a clean environment where ~ expansion and $PATH may not behave as expected.
Register the proxy with Claude Code
Section titled “Register the proxy with Claude Code”Use claude mcp add-json to register a proxied server. The example below wraps github-mcp-server. Your shell resolves the proxy, key, and server paths at paste time.
The token needs to reach mcp-proxy’s environment without being written into the stored config. Pick whichever pattern matches your secrets setup.
Recommended: secret manager (op run, aws-vault exec, …)
Section titled “Recommended: secret manager (op run, aws-vault exec, …)”Install the 1Password CLI (brew install 1password-cli), sign in (op signin), and create a referenced env file:
# ~/.agent-receipts/mcp.env (chmod 600)GITHUB_PERSONAL_ACCESS_TOKEN=op://Personal/GitHub/tokenPoint Claude Code at op run — it resolves the op:// reference at exec time and injects the value into mcp-proxy’s env. No env block is needed in the config. Find your op path with which op.
bash / zsh:
# heredoc terminator (JSON) must be alone on its line; closing ) follows on the nextJSON_BODY=$(cat <<JSON{ "command": "$(which op)", "args": [ "run", "--env-file=$HOME/.agent-receipts/mcp.env", "--", "$(which mcp-proxy)", "-name", "github", "-key", "$HOME/.agent-receipts/github-proxy.pem", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "$(which github-mcp-server)", "stdio" ]}JSON)
claude mcp add-json github-audited --scope user "$JSON_BODY"fish:
set OP (which op)set MCP_PROXY (which mcp-proxy)set GITHUB_MCP (which github-mcp-server)set KEY $HOME/.agent-receipts/github-proxy.pemset ENV_FILE $HOME/.agent-receipts/mcp.env
set json (printf '{ "command": "%s", "args": [ "run", "--env-file=%s", "--", "%s", "-name", "github", "-key", "%s", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "%s", "stdio" ]}' $OP $ENV_FILE $MCP_PROXY $KEY $GITHUB_MCP | string collect)
claude mcp add-json github-audited --scope user "$json"aws-vault exec, chamber exec (AWS Parameter Store), and similar tools follow the same wrapping pattern — substitute whichever your team already deploys.
Alternative: shell environment (Claude Code only)
Section titled “Alternative: shell environment (Claude Code only)”Unlike Claude Desktop, Claude Code expands ${VAR} placeholders in env blocks at server-launch time. This means you can keep the credential in your shell environment and reference it by name in the config.
bash / zsh — \$ escapes the placeholder so bash leaves it intact at paste time:
# heredoc terminator (JSON) must be alone on its line; closing ) follows on the nextJSON_BODY=$(cat <<JSON{ "command": "$(which mcp-proxy)", "args": [ "-name", "github", "-key", "$HOME/.agent-receipts/github-proxy.pem", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "$(which github-mcp-server)", "stdio" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_PERSONAL_ACCESS_TOKEN}" }}JSON)
claude mcp add-json github-audited --scope user "$JSON_BODY"fish (no heredoc support — build JSON via printf instead; the single-quoted format string passes the placeholder through literally):
set MCP_PROXY (which mcp-proxy)set GITHUB_MCP (which github-mcp-server)set KEY $HOME/.agent-receipts/github-proxy.pem
set json (printf '{ "command": "%s", "args": [ "-name", "github", "-key", "%s", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "%s", "stdio" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}" }}' $MCP_PROXY $KEY $GITHUB_MCP | string collect)
claude mcp add-json github-audited --scope user "$json"Set GITHUB_PERSONAL_ACCESS_TOKEN in your shell rc (~/.zshrc, ~/.config/fish/config.fish, etc.) before launching Claude Code. Verify the placeholder reached the stored config (and was not expanded at paste time) with claude mcp get github-audited.
--scope user makes the server available across all projects. Omit it for project-local scope only.
-issuer-name, -operator-id, and -operator-name stamp the signed receipt with the agent and the organisation running it. Setting -issuer-name to Claude Code here (and to Codex in the Codex integration) is what lets you tell at receipt-inspection time which client made a given call — without it, every receipt just shows the default did:agent:mcp-proxy issuer. See the configuration reference for the full set of identity flags.
Verify the server is registered:
claude mcp listProject-scoped setup via .mcp.json
Section titled “Project-scoped setup via .mcp.json”For a shared team configuration, add a .mcp.json file at the project root. This is committed to version control — do not put tokens directly in it.
Since .mcp.json is a static JSON file, print the absolute paths you need first and paste them into the template below:
echo "command: $(which mcp-proxy)"echo "key: $HOME/.agent-receipts/github-proxy.pem"echo "server: $(which github-mcp-server)"Recommended: secret manager
Section titled “Recommended: secret manager”Point Claude Code at op run, same as the claude mcp add-json pattern above. Each developer needs ~/.agent-receipts/mcp.env on their machine with their own op:// reference (or whichever secret manager the team uses).
{ "mcpServers": { "github-audited": { "command": "/opt/homebrew/bin/op", "args": [ "run", "--env-file=/Users/YOU/.agent-receipts/mcp.env", "--", "/Users/YOU/go/bin/mcp-proxy", "-name", "github", "-key", "/Users/YOU/.agent-receipts/github-proxy.pem", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "/opt/homebrew/bin/github-mcp-server", "stdio" ] } }}Alternative: shell environment
Section titled “Alternative: shell environment”Claude Code expands ${VAR} placeholders at server-launch time, so each developer can set GITHUB_PERSONAL_ACCESS_TOKEN in their shell environment and have it picked up automatically.
{ "mcpServers": { "github-audited": { "command": "/Users/YOU/go/bin/mcp-proxy", "args": [ "-name", "github", "-key", "/Users/YOU/.agent-receipts/github-proxy.pem", "-issuer-name", "Claude Code", "-operator-id", "did:web:anthropic.com", "-operator-name", "Anthropic", "/opt/homebrew/bin/github-mcp-server", "stdio" ], "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}" } } }}The proxy path and key path will need to be consistent across the team, or handled via a wrapper script.
Verifying receipts
Section titled “Verifying receipts”After making tool calls through Claude Code, inspect the receipt store from your terminal:
# List all receipts (uses the default ~/.agent-receipts/receipts.db)mcp-proxy list
# Verify chain integritymcp-proxy verify \ -key ~/.agent-receipts/github-proxy.pem.pub \ <chain-id>$ mcp-proxy listID SERVER TOOL ACTION RISK STATUS TIMESTAMP---urn:receipt:a72ee10b... github list_issues data.api.read low success 2026-04-24T01:45:07Zurn:receipt:a125fd30... github list_pull_requests data.api.read low success 2026-04-24T01:44:20Zurn:receipt:67fede57... github add_reply_to_pull_reques... data.api.write medium success 2026-04-24T00:51:57Zurn:receipt:013bfc43... github request_copilot_review data.api.write medium success 2026-04-24T00:43:40Zurn:receipt:7ae4f1b2... github issue_write data.api.write medium success 2026-04-24T00:19:35Z
5 receiptsRead tools like list_issues and list_pull_requests show data.api.read / low; write tools like issue_write show data.api.write / medium. The SERVER column reflects the -name github flag you passed to mcp-proxy.
Gotchas
Section titled “Gotchas”Absolute paths required. Claude Code launches MCP servers with a clean PATH. Use the full path to mcp-proxy (find it with which mcp-proxy) and the full path to the wrapped server binary.
fish shell. Fish does not support heredocs — pasting the bash/zsh snippet as-is fails with Expected a string, but found a redirection. Use the fish alternative above, which builds the JSON via printf and stores it in a variable.
Want human-in-the-loop approvals? Opt in with -http. The approval listener is off by default. If your server exposes tools that cross the risk-score threshold (e.g. create_token = 50, update_auth_config = 70), pass -http 127.0.0.1:<port> and run an approver — see Approval Server. Without it, a paused call fails immediately with JSON-RPC code -32003 (no approver configured). To prevent pausing entirely, drop pause/block rules from a custom -rules YAML.
Classic PATs for org-owned repos. GitHub’s fine-grained PATs can fail for org-level write operations even when permissions appear correct. Use a classic PAT with repo scope for org-owned repositories.
Per-session chain IDs. By default the proxy generates a new chain ID each session. Pass -chain <id> to persist a chain across sessions.
Old receipts show unknown. If you upgraded from a version before v0.2.0, existing receipts in the DB will always show Action: unknown — the tool name was never stored. Clear the DB and start fresh after upgrading.