Documentation

Everything you need to install the proxy, configure guardrails, and connect to estoppl cloud.

On this page

Getting Started

Install

# npm (recommended)
npm install -g estoppl

# Homebrew (macOS / Linux)
brew tap estoppl/tap && brew install estoppl

# Cargo (Rust)
cargo install estoppl

# Or try without installing
npx estoppl

Quick Start

# Initialize config and signing keys
estoppl init --agent-id my-agent

# Auto-wrap Claude Desktop or Cursor
estoppl wrap

# Restart your MCP client, then live-stream tool calls
estoppl tail

estoppl wrap discovers your MCP client configs and rewrites them to route tool calls through the proxy. The proxy runs as a subprocess — your MCP client starts it automatically. Restart your client after wrapping for changes to take effect.

Connect to estoppl Cloud

Sign up at app.estoppl.ai and grab your API key during onboarding. Then uncomment the [ledger] section in estoppl.toml:

[ledger]
cloud_api_key = "sk_your_key"
org_id = "your_org_id"

Cloud sync starts automatically. Events appear in your dashboard within seconds. The remote kill switch and human review also activate when org_id is set.

CLI Reference

CommandDescription
estoppl initInitialize config, keypair, and database
estoppl startStart stdio proxy (wraps a local MCP server)
estoppl start-httpStart HTTP proxy (reverse proxy for remote MCP)
estoppl wrapAuto-wrap MCP client configs (Claude Desktop, Cursor). Use --client claude or --client cursor to wrap a specific client.
estoppl unwrapRestore original MCP client configs
estoppl auditView audit log with filters (--tool, --decision, --since)
estoppl audit --verifyVerify hash chain integrity
estoppl tailLive-stream tool calls as they happen
estoppl statsTool call volume, latency, per-tool breakdown
estoppl dashboardLocal web dashboard at http://127.0.0.1:4200
estoppl benchMeasure proxy overhead (p50/p95/p99 latency)
estoppl reportGenerate HTML activity report

Configuration

estoppl init generates estoppl.toml in the current directory:

[agent]
id = "my-agent"
version = "0.1.0"

[rules]
block_tools = ["delete_*", "drop_*"]
# human_review_tools = ["wire_transfer"]
# max_amount_usd = 50000.0
# rate_limit_per_minute = 30

# Connect to estoppl cloud (https://app.estoppl.ai)
[ledger]
# cloud_api_key = "sk_your_key"
# org_id = "your_org_id"

Guardrails

RuleWhat it doesExample
Allow listOnly listed tools are permittedallow_tools = ["read.*"]
Block listAlways rejected (overrides allow list)block_tools = ["rm_rf.*"]
Human reviewPauses until a human approveshuman_review_tools = ["wire_transfer"]
Amount thresholdBlocks calls exceeding a USD limitmax_amount_usd = 50000.0
Rate limitingBlocks after N calls per minuterate_limit_per_minute = 30

Cloud Sync

When cloud_api_key is set in estoppl.toml, the proxy automatically syncs events to the cloud. The endpoint defaults to https://api.estoppl.ai/v1/events.

Events always persist locally first. Cloud sync is best-effort with exponential backoff, gap detection, and automatic reconciliation.

When org_id is also set, two additional features activate:

Cloud API

Base URL: https://api.estoppl.ai. All requests require Authorization: Bearer <token>.

GET/healthNo auth

Returns {"status": "ok"} if the server and database are reachable.

POST/v1/eventsAPI key (scope: sync)

Ingest a batch of signed events from a proxy. Verifies chain integrity (sequence gaps, batch hash, prev_hash continuity).

Returns {"accepted": N} on success, or 409 with {"gap_from_sequence": N} if a gap is detected.

GET/v1/policy/{orgID}API key

Returns the current policy for the org. Proxies poll this every 5 seconds and hot-reload rules when the version changes.

GET/v1/verify/{attestationID}API key (scope: verify)

Verify that a tool call was governance-checked by estoppl. Returns agent ID, org, tool name, decision, and chain integrity status. Used by upstream MCP servers to verify the X-Estoppl-Attestation header.

POST/v1/reviewAPI key

Submit a tool call for human review. The proxy calls this when a HUMAN_REQUIRED decision is made. Returns review ID and expiry.

GET/v1/review/{eventID}API key

Poll the status of a pending review. Status: pending, approved, denied, expired.

GET/v1/review-action?token=...&action=approveSigned token (no login)

One-click approve or deny a review via a signed link. Sent in Slack and webhook notifications. Single-use.

Dashboard API

These endpoints power the web dashboard at app.estoppl.ai. Auth: Clerk JWT or API key.

GET/v1/dashboard/eventsClerk JWT or API key

List events with optional filters: limit, tool, decision, agent, since.

GET/v1/dashboard/statsClerk JWT or API key

Summary stats: total events, allowed/blocked/human review counts, unique tools, unique agents, time range, and top_tools — top 10 tools by call count with per-tool decision breakdown.

GET/v1/dashboard/policyClerk JWT or API key

Get the current policy with version number.

POST/v1/dashboard/policyClerk JWT or API key

Update policy rules. Accepts any combination of block_tools, allow_tools, human_review_tools, max_amount_usd, custom_rules, agent_rules. Proxies pick up changes within 5 seconds.

GET/v1/dashboard/exportClerk JWT or API key

Download a signed compliance evidence pack. Optional from and to date filters. Verify offline with estoppl audit --verify-export.

GET/v1/dashboard/receipt/{eventID}Clerk JWT or API key

Download a cryptographic receipt for a single event. Verify offline with estoppl audit --verify-receipt.

GET/v1/dashboard/reviewsClerk JWT or API key

List reviews. Optional status=pending filter.

POST/v1/dashboard/review/{eventID}Clerk JWT or API key

Approve or deny a review. Body: {"action": "approved", "reason": "Client confirmed details"} or {"action": "denied", "reason": "Suspicious amount"}. The reason field is recommended for compliance audit trails.

GET/v1/dashboard/api-keysClerk JWT or API key

List API keys for the org.

POST/v1/dashboard/api-keysClerk JWT or API key

Create an API key. Scopes: sync, verify, admin.

DELETE/v1/dashboard/api-keys/{keyID}Clerk JWT or API key

Revoke an API key.

GET/v1/dashboard/notificationsClerk JWT or API key

Get notification settings (email, Slack webhook URL, custom webhook).

POST/v1/dashboard/notificationsClerk JWT or API key

Update notification settings. Email, Slack, and webhook are fully supported.

Policy Rules Reference

Custom Rules

Define arbitrary conditions on tool arguments:

{
  "custom_rules": [
    {
      "name": "Large transfers need approval",
      "tool": "wire_transfer",
      "condition": {"field": "amount", "operator": "gt", "value": 10000},
      "action": "human_review"
    }
  ]
}

Tool patterns: wire_transfer (exact), wire_* (prefix), * (all tools)

Operators: gt, lt, gte, lte, eq, neq, contains, not_contains

Actions: block, human_review, allow

Nested fields: Use dot notation — payment.total extracts from {"payment": {"total": 5000}}

Per-Agent Rules

Override org-wide rules for specific agents. Fields not specified fall back to org-wide defaults:

{
  "agent_rules": {
    "analytics-bot": {
      "allow_tools": ["read_*", "get_*"],
      "block_tools": ["wire_transfer"]
    }
  }
}

Field Redaction

Configure in estoppl.toml (proxy-side):

[rules]
redact_fields = ["ssn", "credit_card", "password"]

Redacted fields are replaced with [REDACTED] before syncing to the cloud.

Notifications

When a tool call requires human review, estoppl sends notifications to all configured channels with one-click approve/deny links:

Configure via Settings in the dashboard or the notifications API endpoint.

Error Responses

All API errors return JSON: {"error": "description"}

StatusMeaning
400Bad request (invalid JSON, missing fields)
401Unauthorized (missing or invalid token)
403Forbidden (wrong org)
404Not found
409Conflict (chain gap detected)
500Internal server error

Questions? Email tina@estoppl.ai or book a call.