Quickstart
One docker run. A working OAuth 2.1 + MCP authorization server in under a minute. All you need installed is Docker.
-
Generate the two secrets
Terminal window export AUTHPLANE_ADMIN_API_KEY="$(openssl rand -hex 32)"export AUTHPLANE_SESSION_SECRET="$(openssl rand -hex 32)"echo "Save this — it's your Admin UI login: $AUTHPLANE_ADMIN_API_KEY"AUTHPLANE_ADMIN_API_KEYis your login for the Admin UI and the admin REST API.AUTHPLANE_SESSION_SECRETsecures user login sessions. -
Start AuthPlane
Terminal window docker run --name authserver -p 9000:9000 -p 9001:9001 \-e AUTHPLANE_ADMIN_API_KEY \-e AUTHPLANE_SESSION_SECRET \-e AUTHPLANE_CLIENT_CREDENTIALS_ENABLED=true \-e AUTHPLANE_DPOP_ENABLED=true \-e AUTHPLANE_TOKEN_EXCHANGE_ENABLED=true \-v authserver-data:/data \authplane/authserver:latest serveThe public OAuth endpoints are on http://localhost:9000; the admin API and Admin UI are on http://localhost:9001. State — the default SQLite database and the auto-generated signing keys — persists in the
authserver-datavolume.The authorization-code + refresh-token flow is always on. The other grants are off by default; the three flags enable them:
AUTHPLANE_CLIENT_CREDENTIALS_ENABLED— machine-to-machine tokens, the simplest MCP-server path.AUTHPLANE_DPOP_ENABLED— DPoP sender-constrained tokens (RFC 9449).AUTHPLANE_TOKEN_EXCHANGE_ENABLED— RFC 8693, needed for agent-to-agent delegation and Broker upstreams.
-
Log in to the Admin UI
Open http://localhost:9001/admin/ui/ and paste the API key you printed in step 1. The dashboard shows server stats, registered clients, users, and scopes — every administrative operation is available from the web UI, and each one is also exposed via the admin REST API.
-
Register your first MCP server
AuthPlane calls each protected MCP server a resource. Scopes are declared on the resource they belong to. Register one with backend kind
mint(AuthPlane signs the tokens your server validates):In the Admin UI at http://localhost:9001/admin/ui/, open the Resources section and create a resource with the same fields as the API call: slug
my-mcp-server, backend kindmint, URIhttp://localhost:8080/mcp, and its scopes (mcp:echo,mcp:add).Terminal window curl -X POST http://localhost:9001/admin/resources \-H "Authorization: Bearer $AUTHPLANE_ADMIN_API_KEY" \-H "Content-Type: application/json" \-d '{"slug": "my-mcp-server","display_name": "My MCP server","uri": "http://localhost:8080/mcp","backend_kind": "mint","scopes": [{"name": "mcp:echo", "description": "Echo a message"},{"name": "mcp:add", "description": "Add two numbers"}]}'If you run
authserverwith a mounted config file — the setup used in the full Docker quickstart — you can register the same resource from inside the container:Terminal window docker exec authserver /authserver --config /config.yaml admin resource create \--slug my-mcp-server \--backend-kind mint \--uri "http://localhost:8080/mcp" \--scopes 'mcp:echo||Echo a message' \--scopes 'mcp:add||Add two numbers'--scopesis repeatable. Each value is aname|upstream|descriptiontuple — for Mint resources the middle (upstream) part is empty, so the form isname||description(double pipe). -
Verify discovery
Terminal window curl -s http://localhost:9000/.well-known/oauth-authorization-server \| jq '{issuer, grant_types_supported, scopes_supported}'The response is the OAuth 2.0 Authorization Server Metadata (RFC 8414). Spot-check three things:
issuermatcheshttp://localhost:9000.grant_types_supportedcontainsclient_credentialsandurn:ietf:params:oauth:grant-type:token-exchange. If you only see["authorization_code", "refresh_token"], the flags didn’t apply — re-check theAUTHPLANE_*_ENABLEDvariables and restart the container.scopes_supportedcontains the scopes you declared on the resource (mcp:echo,mcp:add).
-
Connect your MCP server
Drop the AuthPlane SDK adapter into your MCP server — about 5 lines of integration code. It validates JWTs against the JWKS (signature, audience, scope), serves the RFC 9728 discovery document, and returns the
401+WWW-Authenticateresponse that tells agents where to authenticate.- Python —
authplane-fastmcp(FastMCP, Python 3.12+) orauthplane-mcp(official MCP Python SDK). Runnable example: examples/python/01-mcp-server-basic. - TypeScript —
@authplane/mcp(official MCP TypeScript SDK) or@authplane/fastmcp(FastMCP). Runnable example: examples/typescript/01-mcp-server-basic. - Go — the
go-sdk/mcpadapter for the official MCP Go SDK. Runnable example: examples/go/01-mcp-server-basic.
Each example ships
make runand amake verifythat mints a token and calls the protected tool end to end. Adding auth to an MCP server you already have? Use the before/after retrofit examples — Python · TypeScript · Go.Then point an MCP client at your server — AuthPlane is tested against Claude Code, Claude Desktop, and MCP Inspector.
- Python —
Before production
Section titled “Before production”The setup above is for local development. Before deploying:
- Set the issuer to your public HTTPS URL (
server.issuer: https://auth.example.com). - Set a session secret (
session.secretorAUTHPLANE_SESSION_SECRET). - Set an admin API key (
admin.api_keyorAUTHPLANE_ADMIN_API_KEY). - Enable secure cookies (
session.secure: true— enforced automatically for non-localhost issuers). - Consider PostgreSQL for multi-instance deployments (
storage.driver: postgres).
See the configuration guide and the field-by-field schema reference.
Next steps
Section titled “Next steps”Going deeper, in the upstream docs: Connect an MCP server · Admin CLI & API · OIDC federation · Upstream provider connections · Drive the whole flow by hand with curl