---
name: aironclaw
description: Operate AIronClaw — an AI firewall for MCP servers and LLM proxies — on the user's behalf via its REST API. Use when the user wants to programmatically manage MCP servers, LLM proxies, firewall rules, IP ACLs, rate limits, DLP redaction, prompt guards, MCP resources, API keys, audit logs, or budgets on AIronClaw. Authenticates with a personal access token issued from the dashboard's Profile → REST API Access section.
allowed-tools: Bash(curl:*), Bash(jq:*), Bash(scripts/aironclaw:*), Read
---

# AIronClaw API skill

AIronClaw is a gateway in front of MCP servers and LLM providers that adds authentication, per-tool/per-model permissions, IP ACLs, rate limits, DLP redaction, prompt-injection guards, response transforms, static caches, synthetic MCP resources, and per-proxy budgets.

The full surface the dashboard exposes is also reachable over REST. This skill teaches you how to drive every part of it on the user's behalf.

## When to use this skill

Use this skill whenever the user asks you to:

- list, create, modify, delete, or inspect **MCP servers**
- list, create, modify, delete, or inspect **LLM proxies** (OpenAI / Anthropic / Google / Mistral)
- configure **firewall rules**: IP ACLs, rate limits, response replace / DLP, prompt guards, lambda code, static caches, synthetic MCP resources
- mint, rotate, scope, or delete **API keys** for end clients
- read **audit logs** (events, blocks, errors, LLM calls)
- set or reset **LLM budgets** (per proxy or per key)
- inspect **usage** and spend
- discover or refresh remote **MCP tools**

If the user only wants to *call* an MCP tool or LLM provider through AIronClaw, that traffic flows through the gateway (`proxy.aironclaw.com` / `<uuid>.aifirewall.aironclaw.com`) and is **not** what this skill is for. This skill is for *managing the configuration*.

## Initial setup (must be done by the human user once)

The personal access token cannot be generated by an agent — it requires the dashboard UI because it is shown exactly once and only a SHA-256 hash is stored. If the user does not yet have one, walk them through this:

1. Open `https://dashboard.aironclaw.com/dashboard/profile`
2. Sign in (Google / GitHub / GitLab; complete 2FA if enabled)
3. Scroll to **REST API Access** → click **Generate token** (or **Rotate token** if one already exists — note that rotation invalidates the previous token immediately)
4. Copy the token displayed in the amber banner. It will not be shown again. Only a hash is stored on the server.
5. Export it in your shell, together with the base URL:

```bash
export AIRONCLAW_BASE_URL="https://dashboard.aironclaw.com"
export AIRONCLAW_TOKEN="<paste-token-here>"
```

If `AIRONCLAW_BASE_URL` is unset, default to `https://dashboard.aironclaw.com`. The base URL is configurable per deployment — self-hosted users may set it to e.g. `https://platform.example.com`.

**Never** ask the user to paste the token into the conversation. The shell environment is sufficient. If the env var is missing when you try to call the API, stop and instruct the user to export it first.

## Authentication

Every request carries the PAT as a bearer token:

```http
Authorization: Bearer <AIRONCLAW_TOKEN>
```

The PAT identifies the user. It bypasses 2FA (it was issued by an MFA-verified session) but **cannot** be used against:

- `/api/2fa/*` — TOTP enrolment / verify / disable / challenge → 403 (use the dashboard)
- `/api/profile/token` — viewing or rotating the PAT itself → 403 (a stolen PAT must not be able to perpetuate access)
- `/api/auth/*` — NextAuth internals

For everything else the same endpoint works whether called from the browser dashboard or from your script.

## Base URL & path layout

```
${AIRONCLAW_BASE_URL}/api/<resource>[/<id>][/<sub-resource>]
```

Resources:

| Path                              | Purpose |
|----------------------------------|---------|
| `/api/profile`                    | caller identity (email, consumer id, tags) |
| `/api/keys`, `/api/keys/:id`      | API keys for downstream clients (NOT the PAT) |
| `/api/mcp`, `/api/mcp/:id`        | MCP server CRUD |
| `/api/mcp/:id/tools`              | discover/refresh tools on the upstream MCP |
| `/api/mcp/:id/resources[/:rid]`   | synthetic MCP resources (text content served as MCP resources) |
| `/api/mcp/:id/rules`              | firewall rules (IP ACL, rate limit, response_replace, prompt_guard, lambda, static_cache, mcp_resource) |
| `/api/mcp/:id/cache`              | drain the response cache for a tool |
| `/api/mcp/:id/re-resolve`         | force DNS re-resolve for the upstream MCP host |
| `/api/mcp/jwks/test`              | validate a JWKS document before saving |
| `/api/llm`, `/api/llm/:id`        | LLM proxy CRUD |
| `/api/llm/:id/rules`              | firewall rules for the LLM proxy (subset: prompt_guard, prompt_replace, model_route, rate_limit, lambda) |
| `/api/llm/:id/usage[...]`         | monthly / daily usage series |
| `/api/llm/:id/budget[/reset]`     | budget configuration & manual reset |
| `/api/llm/:id/keys[...]`          | per-key budget & usage |
| `/api/llm/:id/logs[/:logId]`      | conversation logs (only when `logConversations: true`) |
| `/api/llm/:id/re-resolve`         | force DNS re-resolve for the upstream provider |
| `/api/logs`                       | global audit log feed |
| `/api/logs/chart`                 | log time-series for the dashboard chart |
| `/api/overview`, `/api/overview/feed` | dashboard summary + activity feed |
| `/api/resources`                  | flat list of all MCP resources across the user's MCPs |
| `/api/health`                     | infra probe (postgres / redis / gateway) |

Detailed request/response schemas for every endpoint are in [reference/api-reference.md](reference/api-reference.md).

## Quick start — list the user's MCPs

```bash
curl -fsS \
  -H "Authorization: Bearer ${AIRONCLAW_TOKEN}" \
  "${AIRONCLAW_BASE_URL}/api/mcp" | jq
```

Or via the bundled wrapper:

```bash
./scripts/aironclaw mcp list
```

The wrapper expects `AIRONCLAW_TOKEN` and `AIRONCLAW_BASE_URL` in the environment, sets the auth header, and pretty-prints JSON responses with `jq`. See [scripts/aironclaw](scripts/aironclaw).

## Conventions you must follow

1. **Always** check the HTTP status code before consuming the body. The API uses standard codes:
   - `200 / 201` success
   - `400` malformed request — the body's `error` field tells you what
   - `401` missing or invalid PAT
   - `403` forbidden (wrong endpoint for PAT, or quota exceeded)
   - `404` resource doesn't exist or doesn't belong to the caller
   - `409` conflict (e.g. enrolling 2FA twice, duplicate URI)
   - `429` rate-limited (only on `/api/2fa/challenge` today)
   - `500 / 502 / 503` server-side or upstream issue
2. **JSON only** for request bodies. Always send `Content-Type: application/json`.
3. **Never log the PAT.** When echoing a curl command for the user, mask it as `***`.
4. **Confirm destructive operations** with the user before executing them. `DELETE /api/mcp/:id` tears down the gateway service, route, and plugin instance and strips permission tags from every API key — it is not undoable. Same for `DELETE /api/llm/:id`.
5. **Respect quotas.** A user can have at most N MCPs and N API keys (defaults 10 / 40, overridable per-account). Failed creates with 403 will say so; don't retry blindly.
6. **Never invent UUIDs.** Always read them from a prior `GET /api/mcp` or `GET /api/llm` response.
7. **JWKS for inbound JWT auth on a proxy must be validated first** with `POST /api/mcp/jwks/test` before being passed in a create/update body — the upstream remote fetch was deliberately removed (DNS-rebinding hardening), so the JWKS JSON is pasted in as a string.
8. **Check for an existing resource before creating** when the user describes an action by name (e.g. "add the Stripe MCP" — list first, see if it's there, only then POST).

## Navigation

Pick the file that matches the user's task. Read only what you need:

- **MCP server lifecycle** (create, configure auth, discover tools, set permissions): [reference/mcp-lifecycle.md](reference/mcp-lifecycle.md)
- **LLM proxy lifecycle** (create, allowed models, budget, conversation logging): [reference/llm-lifecycle.md](reference/llm-lifecycle.md)
- **Firewall rules** (every rule type with body schema and worked examples): [reference/rules-and-dlp.md](reference/rules-and-dlp.md)
- **Lambda functions** (Lua extension point — read/modify request & response, custom guardrails, header injection): [reference/lambda-functions.md](reference/lambda-functions.md)
- **Permissions & API keys** (tag model, scoping a downstream client to specific MCPs/tools/LLMs/models): [reference/permissions-and-keys.md](reference/permissions-and-keys.md)
- **Full endpoint reference** (every method, path, body, response): [reference/api-reference.md](reference/api-reference.md)
- **Errors & remediation**: [reference/errors.md](reference/errors.md)

Worked end-to-end examples are in `scripts/examples/`:

- [scripts/examples/create-mcp.sh](scripts/examples/create-mcp.sh) — register an MCP, discover tools, mint a scoped API key
- [scripts/examples/configure-firewall-rule.sh](scripts/examples/configure-firewall-rule.sh) — IP ACL + rate limit + DLP redaction
- [scripts/examples/create-llm-proxy-with-budget.sh](scripts/examples/create-llm-proxy-with-budget.sh) — OpenAI proxy with allowed models and a monthly cap
- [scripts/examples/tail-logs.sh](scripts/examples/tail-logs.sh) — follow the audit log feed

## Versioning & stability

This skill targets the API as it stands at the date in the repository's HEAD commit. The `/api/*` paths are stable; new fields may be added to responses (your client should ignore unknown fields). Breaking changes will move under `/api/v2/`.
