> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentsentinel.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Claude Code setup

> Give Claude Code governed tools through the agentsentinel-mcp stdio proxy, with no credential in the model's context.

## How it works

`agentsentinel-mcp` is a stdio MCP server shipped in the Python SDK. Claude Code launches it like any other MCP server. The proxy answers `initialize` itself and forwards `tools/list` and `tools/call` to the platform's [`/mcp` endpoint](https://docs.agentsentinel.dev/platform/mcp), authenticating with an **agent-bound API key** read from its environment.

The key travels only in the upstream `Authorization` header. It never appears in a tool list, a tool result, an error message or the proxy's output, so the model never sees it. Upstream credentials for the tools themselves stay in [AgentVault](https://docs.agentsentinel.dev/platform/agentvault.md) and are injected by the platform only after the gateway allows a call.

## Install

The proxy needs Python 3.10 or later:

```bash theme={null}
pip install "agentsentinel-sdk[mcp]"
```

This installs the `agentsentinel-mcp` command. Make sure it is on the `PATH` Claude Code uses, or put its absolute path in `command`.

## Register the server

Add this to `.mcp.json` at your project root (or your user-level Claude Code configuration):

```json theme={null}
{
  "mcpServers": {
    "agentsentinel": {
      "command": "agentsentinel-mcp",
      "env": {
        "AGENT_SENTINEL_API_KEY": "${AGENT_SENTINEL_API_KEY}",
        "AGENT_SENTINEL_HARNESS": "claude-code"
      }
    }
  }
}
```

Claude Code expands `${AGENT_SENTINEL_API_KEY}` from the environment it was started in, so the key never has to be committed. Export it before launching Claude Code. Alternatively, register the server from the CLI:

```bash theme={null}
claude mcp add agentsentinel \
  -e AGENT_SENTINEL_API_KEY="$AGENT_SENTINEL_API_KEY" \
  -e AGENT_SENTINEL_HARNESS=claude-code \
  -- agentsentinel-mcp
```

| Variable | Required | Meaning |
| - | - | - |
| `AGENT_SENTINEL_API_KEY` | yes | An [agent-bound API key](https://docs.agentsentinel.dev/platform/auth.md#agent-bound-keys). `/mcp` refuses user sessions and unbound keys with `403 agent_bound_key_required`. |
| `AGENT_SENTINEL_URL` | no | Overrides the platform base URL, for a self-hosted or staging platform. Defaults to the hosted platform. The proxy targets `<url>/mcp`. `https` is required unless the host is `localhost` or `127.0.0.1`. |
| `AGENT_SENTINEL_HARNESS` | no | Sent as `X-Sentinel-Harness`, so decisions and ledger rows record which harness made the call. |

If the key is missing or the URL is not allowed, `agentsentinel-mcp` exits non-zero with a one-line message on stderr (Claude Code shows it as a failed server). The message never contains the key.

## Walkthrough: a governed call, end to end

The operator steps (1–3, 5 and 6) use a **user session**: the registry, AgentVault and policy routes refuse API keys. In the commands below, `$API` is your platform API base URL and `$SESSION_TOKEN` is your console session token.

```bash theme={null}
export API="<your platform API base URL>"
```

### 1. Create an agent-bound key

```bash theme={null}
curl -X POST "$API/api/v1/api-keys/" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "claude-code-agent", "agent_id": "claude-code-agent"}'
```

Copy the returned `key` (shown once) into `AGENT_SENTINEL_API_KEY` in the shell you launch Claude Code from.

### 2. Register a governed tool

```bash theme={null}
curl -X POST "$API/api/v1/governed-tools" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "send",
    "description": "Send a message",
    "input_schema": {
      "type": "object",
      "properties": {"to": {"type": "string"}},
      "required": ["to"]
    },
    "impact": "low",
    "estimated_cost_usd": 0.25,
    "target_url": "https://tools.example.com/send",
    "target_method": "POST",
    "enabled": true
  }'
```

Use an HTTPS endpoint you operate as `target_url`. Note the returned tool `id`. See [Registering governed tools](https://docs.agentsentinel.dev/platform/mcp.md#registering-governed-tools) for the rules.

### 3. Bind a credential

Store the target's credential in AgentVault and bind it to the tool, as described in [AgentVault Credentials](https://docs.agentsentinel.dev/platform/agentvault.md):

```bash theme={null}
curl -X POST "$API/api/v1/agentvault/credentials" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "send-target", "secret": "<target API token>", "scopes": []}'

curl -X PUT "$API/api/v1/agentvault/credentials/<credential id>/bindings/<tool id>" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"credential_injection": {"type": "header", "header": "Authorization", "prefix": "Bearer "}}'
```

The secret is write-only. The platform injects it into the outbound request only after the gateway allows the call; neither Claude Code nor the proxy ever holds it.

### 4. Call it from Claude Code

Restart Claude Code (or run `/mcp`) and check that the `agentsentinel` server lists `send`. Then ask:

> Use the send tool to send a message to [a@example.com](mailto:a@example.com).

Claude Code calls `tools/call`. The proxy forwards it unchanged, the gateway decides, the platform injects the credential and runs the target, and the result comes back as an ordinary tool result. The model's context holds the tool's name, schema and result, never a key or token.

### 5. See a budget cap block a call

Cap the tool below its estimated cost with a policy for this agent:

```bash theme={null}
curl -X POST "$API/api/v1/policies/" \
  -H "Authorization: Bearer $SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "cap send",
    "enabled": true,
    "scope": "agent",
    "target_id": "claude-code-agent",
    "action_budgets": {"send": 0.10}
  }'
```

Ask Claude Code to send again. The target is not contacted. The tool result has `isError: true` and the refusal's reason code in `structuredContent`, which the proxy passes through unchanged:

```json theme={null}
{
  "content": [{"type": "text", "text": "..."}],
  "structuredContent": {"decision": "deny", "reason_code": "action_budget_exceeded"},
  "isError": true
}
```

See [Error reason codes](https://docs.agentsentinel.dev/platform/mcp.md#error-reason-codes) for the other codes, such as `monthly_budget_exceeded` and `kill_switch_active`.

### 6. Verify the ledger

Both calls, the allowed one and the refused one, are recorded in the signed, hash-chained ledger. Verify the whole chain:

```bash theme={null}
curl "$API/api/v1/ledger/verify" \
  -H "Authorization: Bearer $SESSION_TOKEN"
```

A response with `"valid": true` and `"head_matches": true` shows that no row was altered, removed or reordered. See [`GET /api/v1/ledger/verify`](https://docs.agentsentinel.dev/platform/ledger#get-api-v1-ledger-verify).

## Troubleshooting

| Symptom | Cause |
| - | - |
| The server fails to start: `AGENT_SENTINEL_API_KEY is not set` | The key is not in the server's `env`, or `${AGENT_SENTINEL_API_KEY}` was not exported when Claude Code started. |
| The server fails to start: `AGENT_SENTINEL_URL must use https` | Plain `http` is only allowed for `localhost` and `127.0.0.1`. |
| `tools/list` fails, or tool calls return `AgentSentinel rejected the API key (HTTP 403, agent_bound_key_required)` | The key is unbound, or is a user session token. Create an agent-bound key (step 1). |
| Tool calls return `AgentSentinel is unreachable` | The platform URL cannot be reached from your machine. |

Resources, prompts and the [`/mcp/admin`](https://docs.agentsentinel.dev/platform/mcp#admin-mount) mount are not proxied.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.