AgentStack
MCP verified MIT Self-run

MCPAuthKit

mcp-opzero-sh-mcpauthkit · by OpZero-sh

OAuth 2.1 for MCP servers in one Cloudflare Worker. RFC 9728 + 8414 + 7591, PKCE, dynamic client registration, consent UI, multi-tenant. Deploy in 5 minutes.

No reviews yet
0 installs
3 views
0.0% view→install

Install

$ agentstack add mcp-opzero-sh-mcpauthkit

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of MCPAuthKit? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

MCP AuthKit

OAuth 2.1 for MCP servers. One Worker. Five minutes.

Every MCP server builder hits the same wall: the OAuth spec is brutal.AuthKit is the other side of that wall.

A single Cloudflare Worker + D1 database that handles the entire MCP OAuth specification -- discovery, registration, consent, tokens -- so your MCP server doesn't have to.

[](LICENSE) [](https://workers.cloudflare.com) [](https://oauth.net/2.1/) [](https://modelcontextprotocol.io) [](https://www.rfc-editor.org/rfc/rfc9728)

Running in production at auth.opzero.sh, powering OAuth for OpZero.sh.

[Get Started](#quick-start) · [How It Works](#how-it-works) · [API Reference](#api-reference) · [The War Story](#the-war-story)


The Problem

You want to build an MCP server. Claude, ChatGPT, and other clients need to authenticate users with your server. The spec says: implement OAuth 2.1.

That means RFC 9728 (Protected Resource Metadata), RFC 8414 (Authorization Server Metadata), RFC 7591 (Dynamic Client Registration), PKCE with S256, consent screens, token refresh, token revocation, and multi-tenant support. All before your first tool call works.

We spent weeks fighting this. Then we ripped it out into its own service.

The Solution

AuthKit is a standalone OAuth authorization server (~600 lines) purpose-built for MCP. Your MCP server points its authorization_servers to AuthKit, and the entire OAuth dance -- registration, consent, tokens -- happens here.

Your MCP server's only job: validate the Bearer token.

// Your MCP server's /.well-known/oauth-protected-resource
{
  "resource": "https://your-mcp-server.com/mcp",
  "authorization_servers": ["https://your-authkit-instance.com"],
  "bearer_methods_supported": ["header"]
}

That's the entire integration.

What It Implements

| Spec | What | Status | |------|------|--------| | RFC 9728 | Protected Resource Metadata | Auto-generated per server | | RFC 8414 | Authorization Server Metadata | Complete | | RFC 7591 | Dynamic Client Registration | Complete | | OAuth 2.1 | Authorization code + PKCE (S256) | Complete | | -- | Token refresh (30-day TTL) | Complete | | -- | Token revocation | Complete | | -- | Consent screen with login/signup | Complete | | -- | Multi-tenant (multiple MCP servers) | Complete |

How It Works

Claude / ChatGPT         AuthKit (CF Worker + D1)       Your MCP Server
     |                           |                           |
     |  POST /mcp (no token)     |                           |
     |------------------------------------------------------------>|
     |  401 + WWW-Authenticate   |                           |
     ||
     |  { authorization_servers: ["https://authkit..."] }    |
     ||                           |
     |  { endpoints... }        |                           |
     ||                           |
     |  { client_id }           |                           |
     ||                           |
     |  [consent screen]        |                           |
     ||                           |
     |  302 -> callback?code=xxx|                           |
     ||                           |
     |  { access_token, ... }   |                           |
     ||
     |                           |  GET /oauth/userinfo      |
     |                           ||
     |  [tools response]         |                           |
     | enter a strong random string

# Deploy
wrangler deploy

Live at https://mcp-authkit..workers.dev.

Register Your MCP Server

curl -X POST https://your-authkit.workers.dev/api/servers \
  -H "Authorization: Bearer YOUR_ADMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My MCP Server",
    "resource_url": "https://my-mcp.com/mcp",
    "scopes": ["mcp:tools"]
  }'

Response:

{
  "server_id": "srv_abc123...",
  "api_key": "sak_xyz789...",
  "prm_url": "https://your-authkit.workers.dev/prm/srv_abc123...",
  "message": "Set authorization_servers in your PRM to point to this gateway."
}

Wire Up Your MCP Server

Point your server's Protected Resource Metadata at your AuthKit instance and validate tokens via the /oauth/userinfo endpoint. That's it.

See [Integration Guide](docs/integration.md) for the full walkthrough.

API Reference

| Method | Endpoint | Description | |--------|----------|-------------| | GET | /.well-known/oauth-authorization-server | Authorization server metadata (RFC 8414) | | POST | /oauth/register | Dynamic client registration (RFC 7591) | | GET | /oauth/authorize | Authorization + consent UI | | POST | /oauth/token | Code -> token exchange with PKCE | | POST | /oauth/revoke | Token revocation | | GET | /oauth/userinfo | User info from access token | | GET | /prm/:server_id | Auto-generated Protected Resource Metadata (RFC 9728) | | POST | /api/servers | Register an MCP server (admin) | | GET | /health | Health check |

See [API Reference](docs/api.md) for request/response details.

Token Format

| Type | Prefix | Lifetime | Example | |------|--------|----------|---------| | Access token | mat_ | 1 hour | mat_dhcbqsgb... | | Refresh token | mrt_ | 30 days | mrt_ydqd0ug1... | | Auth code | code_ | 10 minutes | code_zkm6ukm... | | Server API key | sak_ | Permanent | sak_6rvstdl7... |

All tokens are hashed (SHA-256) before storage. The plaintext is only returned once at creation.

Project Structure

mcp-authkit/
  src/
    worker.js              The entire OAuth gateway (~600 lines)
  docs/
    integration.md         How to wire up your MCP server
    api.md                 Full API reference
    how-it-works.md        Deep dive on the OAuth flow
    decisions.md           Why we built it this way
    war-story.md           10 attempts, every bug, the full timeline
  scripts/
    test-flow.sh           End-to-end OAuth flow test
  schema.sql               D1 database schema (7 tables)
  wrangler.toml            Cloudflare Worker config
  package.json

The War Story

This project exists because we spent 10 attempts across 5 days trying to get MCP OAuth working in a Next.js app with Better Auth. Trailing newlines in env vars, boolean-vs-string consent redirects, hashed tokens compared as raw strings, missing OPTIONS handlers, undocumented config flags -- every bug manifested as "nothing happens."

The turning point was realizing OAuth is infrastructure, not product. Rip it out.

  • [The War Story](docs/war-story.md) -- All 10 attempts, every bug, the full timeline
  • [Architecture Decisions](docs/decisions.md) -- Why Cloudflare Workers, why standalone

Caveats

This is a reference implementation that powers a real product. It is not:

  • A maintained library with SLAs
  • A drop-in replacement for Auth0/Stytch/Clerk
  • Battle-tested at massive scale (it works for our traffic)

Use it to learn from, fork it, steal the patterns. If you need production auth with support, use a dedicated auth provider.

Built by OpZero

OpZero is an AI-native deployment platform. Ship websites to Cloudflare, Netlify, and Vercel from any MCP client -- Claude, Cursor, or your own agents.

AuthKit is the OAuth layer that powers it. We open-sourced it because every MCP builder shouldn't have to fight the same spec.

Contributing

Contributions welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

License

[MIT](LICENSE)


Built by @jcameronjeff for OpZero.sh

If this saves you the OAuth headache it saved us, give OpZero a look --it's the deployment platform we built this for.

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.