A tiny MCP server whose auth is browserid natively: no API keys — every tool call carries a warrant naming who granted it, and revocation is re-checked on every single call. Three minutes, from claude.ai or any MCP host.
claude.ai: Settings → Connectors → Add custom connector. Claude Code: claude mcp add --transport http mcp-demo <url>. Any MCP host works — it runs its ordinary OAuth flow, which lands you on the browserid consent card: sign in with your email, approve demo:write once.
https://mcp-demo.browserid.me/mcp
The server's tools now appear like any connector's. Every call carries your warrant; the reply shows the attribution — this agent, on your behalf.
Log a fun action at the browserid mcp-demo, then read the log back and show me how it was attributed.
Open browserid.me/account → Authorized sites → revoke the mcp-demo grant. Then ask the agent to log one more action: the very next call is refused, fail-closed — the server re-checks the warrant's status on every call. Nothing else you've granted is touched.
Log another action at the browserid mcp-demo.
The server is the reference for building your own: mcp-demo (JS, on @browserid-ng/mcp-auth). It mounts both auth lanes: the connector flow above (authorization code), and an assertion grant for headless agents and tests — code that already holds a browserid warrant exchanges it at /token directly, no browser anywhere. A Python twin on browserid-mcp-auth (source) implements the assertion lane, showing both SDKs enforce identically.