Skip to content

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.

  • mcp-proxy installed

  • 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-server

    This puts a github-mcp-server binary on your $PATH. Verify with which github-mcp-server.

Terminal window
mcp-proxy init --name github-proxy
# creates ~/.agent-receipts/github-proxy.pem (0600) and ~/.agent-receipts/github-proxy.pem.pub

Re-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.

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.

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/token

Point 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:

Terminal window
# heredoc terminator (JSON) must be alone on its line; closing ) follows on the next
JSON_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:

Terminal window
set OP (which op)
set MCP_PROXY (which mcp-proxy)
set GITHUB_MCP (which github-mcp-server)
set KEY $HOME/.agent-receipts/github-proxy.pem
set 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:

Terminal window
# heredoc terminator (JSON) must be alone on its line; closing ) follows on the next
JSON_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):

Terminal window
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:

Terminal window
claude mcp list

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:

Terminal window
echo "command: $(which mcp-proxy)"
echo "key: $HOME/.agent-receipts/github-proxy.pem"
echo "server: $(which github-mcp-server)"

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"
]
}
}
}

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.

After making tool calls through Claude Code, inspect the receipt store from your terminal:

Terminal window
# List all receipts (uses the default ~/.agent-receipts/receipts.db)
mcp-proxy list
# Verify chain integrity
mcp-proxy verify \
-key ~/.agent-receipts/github-proxy.pem.pub \
<chain-id>
$ mcp-proxy list
ID SERVER TOOL ACTION RISK STATUS TIMESTAMP
---
urn:receipt:a72ee10b... github list_issues data.api.read low success 2026-04-24T01:45:07Z
urn:receipt:a125fd30... github list_pull_requests data.api.read low success 2026-04-24T01:44:20Z
urn:receipt:67fede57... github add_reply_to_pull_reques... data.api.write medium success 2026-04-24T00:51:57Z
urn:receipt:013bfc43... github request_copilot_review data.api.write medium success 2026-04-24T00:43:40Z
urn:receipt:7ae4f1b2... github issue_write data.api.write medium success 2026-04-24T00:19:35Z
5 receipts

Read 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.

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.