identity for every agent · redacted logs · a database that refuses

Every agent leaves a log line. This one can't lie.

a-guard gives an MCP resource server a real OpenID Connect authorization server, redacts PII out of every record at creation, and lets Postgres itself refuse the destructive call. Below is one real round trip, replayed.

agent session — journal --:--:--.---

Replayed sequence: an agent presents a token minted for the REST API; the MCP endpoint rejects it with 401 and reason mcp.auth.reject; the agent re-mints for the MCP audience; a log line containing an email address and a card number is redacted character by character before it can be stored; the agent's DELETE is refused by Postgres row-level security and column grants — rows=0, nothing changed — and the attempt is recorded in the audit log.

Three guarantees, three layers of truth

One identity surface for every agent. No SDK secrets. No audit trail you can't verify.

01 · AUTH

OpenID Connect, audience-bound

The resource server verifies every token against the AS's public JWKS — it holds no signing key. A token minted for /api is refused at /mcp. That's the mcp.auth.reject you watched above.

02 · REDACTION

PII never leaves the service

Every log record is redacted at creation — not at read time, not by a filter you can forget to enable. Raw identities, cards, and tokens stay inside; they never reach the agent's context window.

03 · DATABASE

The database says no

Row-level security, column grants, and a separate agent pool mean an agent's delete is refused by Postgres itself. Not middleware. rows=0 — nothing changed.

Try the redactor — it's live

This button calls POST /redact on this deployment: the same engine that redacts the service's own logs, with no OAuth needed to try it.

paste anything — an access log, a support ticket, a token

what the log keeps

— run it —

rate-limited per IP · counts only — the endpoint never echoes your input into its own logs, so the playground can't become the leak it exists to prevent.

See it in one command

Both services, a real MCP client, and the audit trail where rows=0 is the agent's refused delete.

bash scripts/demo.sh # paced for recording

Runs the AS and the resource server, registers a client, walks the full browser flow, and replays the refused delete. Leave the services up with DEMO_KEEP=1.

WHAT THE DEMO PROVES · AUDIT TRAIL

rows=0 is the refusal

The agent's delete is swallowed by Postgres. The audit log records the attempt — and nothing changed.

Star on GitHub —