Your MCP server is exposed.
AuthPlane locks it down.
The self-hosted authorization server purpose-built for MCP. Open source under AGPL-3.0. One Go binary. Implements the complete MCP authorization spec (2025-11-25) — including full OAuth 2.1 — so every agent call is authenticated, every credential is managed, and every action is auditable.
What happens when agents can't authenticate.
Static API keys from env files
Same key for every agent, every tool. Hardcoded in .env, never rotated, visible to anyone with repo access.
One leaked .env file exposes every integration. No rotation means compromised keys stay live indefinitely.
OAuth 2.1 with PKCE. Per-agent tokens, auto-rotated, never stored in env files. Revoke any token instantly.
Full access — can't scope per-agent
Agent-1 reads your issues AND deletes repos. Every agent gets the same all-or-nothing API key.
A compromised agent has god-mode access. No way to limit blast radius or enforce least-privilege.
Scoped tokens per agent, per tool. Agent-1 reads issues. Agent-2 creates PRs. Nothing more.
Silent failures on token expiry
No refresh flow. No graceful degradation. The agent stops working and nobody notices until a user reports it.
Production agents silently break. Workflows fail mid-execution. Hours of downtime before anyone catches it.
Built-in token refresh with RFC 6749 flows. Graceful re-auth, automatic retry, zero downtime.
No audit trail
All requests look the same. Can't tell which agent accessed what, when, or why. Every call is anonymous.
SOC 2, HIPAA, FedRAMP audits fail immediately. Incident response is blind — no forensics possible.
Every auth, credential vend, and tool call in one queryable audit log. Compliance-ready from day one.
One leak compromises everything
One shared API key across all agents. Can't revoke one agent without breaking every other agent that uses the same key.
Total exposure from a single leak. Lateral movement is trivial. Recovery means rotating every integration simultaneously.
DPoP-bound tokens can't be replayed. Per-agent identity means you revoke one agent instantly without touching others.
From request to audit in six steps.
Follow a single agent from registration to audit. Every feature in context.
From request to audit in six steps.
Follow a single agent from registration to audit. Every feature in context.
Agent presents its Client ID
The agent identifies itself using a Client ID Metadata Document (CIMD). It hosts a JSON document at a URL it controls — no registration endpoint needed.
PKCE challenge sent
The agent initiates OAuth 2.1 with a code_challenge. AuthPlane validates and issues a single-use authorization code. No client secrets cross the wire.
→ auth_code · expires: 600sDPoP binds token to key
The agent exchanges the code for an access token. DPoP binds it to the agent's ephemeral key pair — stolen tokens are useless.
htm: POST htu: /token jti: unique alg: ES256 ephemeral Vault returns scoped token
AuthPlane decrypts with per-owner HKDF derivation and returns a scoped token. The agent never sees raw credentials.
→ scope: repo:read · ttl: 3600sAgent calls MCP server
The agent sends its DPoP-bound JWT and scoped credential. The server validates via AuthPlane's JWKS endpoint. Zero trust, fully verified.
Every action logged
Authentication, credential vend, and tool call — all in one audit log. Queryable, exportable, and correlated with OpenTelemetry trace IDs.
Full visibility. Zero guesswork.
A built-in admin console to manage clients, users, tokens, signing keys, and audit every event — in real time.
Overview
Clients
Users
Tokens
Audit Log
System
Six capabilities. One server.
Every feature purpose-built for MCP. Click to explore the details.
Credentials in. Scoped tokens out.
- AES-256-GCM encryption with HKDF key derivation
- User-authorized PKCE flows per provider (GitHub, Slack, Linear, Jira)
- Vend scoped tokens at tool-call time — agents never see raw credentials
- HashiCorp Vault Transit backend for regulated environments
Tokens bound to their owner.
- ES256 ephemeral key pair per client — tokens can't be replayed
- Per-request proof with JTI nonce and server validation
- Automatic nonce rotation and replay detection
- Works seamlessly with Token Vault and Token Exchange
Delegate without oversharing.
- Orchestrator → worker delegation with automatic scope downscoping
- Chain depth tracked and enforced in token claims
- Every exchange audited with actor and target identifiers
- Supports both impersonation and delegation grant types
Every agent, fully identified.
- Unique agent identity with agent_name and sub claims
- Embedded user context via act (actor) claim chain
- Fine-grained scope breakdown per agent in the token
- Built on OpenID Connect ActorToken extension
Machine to machine. No user needed.
- Direct access tokens for service accounts — no user context
- Scope-based access control per service with CLI management
- Automatic rate limiting and quota enforcement
- Full audit trail for every machine token issued
Enterprise IdP in the loop.
- Enterprise IdP (Okta, Entra ID) mediates every agent-to-tool connection
- JWT Bearer grant (RFC 7523) — no user-facing consent screens needed
- Trusted IdP registry with JWKS discovery and audience binding
- Policy engine enforces scope, group membership, and step-up auth
Built to the letter of the spec.
Every RFC the MCP authorization specification requires. Verified with MCP Inspector.
| RFC | Specification | What it means for you | Status |
|---|---|---|---|
MCP 2025-11-25 | MCP Authorization | The complete MCP authorization spec, end to end. Tested with Claude Code, Claude Desktop, MCP Inspector. | Implemented |
RFC 8414 | AS Metadata | MCP clients auto-discover your authorization server config from a well-known endpoint. | Implemented |
RFC 9728 | Protected Resource Metadata | Your MCP server declares its AS. Clients find it automatically. Zero manual configuration. | Implemented |
RFC 7636 | PKCE (S256 only) | Proof Key for Code Exchange. Code interception prevented. plain method explicitly rejected. | Implemented |
CIMD + DCR | Client Identity | CIMD (URL-based) is the default. DCR (RFC 7591) supported as alternative for legacy clients. | Implemented |
RFC 8707 | Resource Indicators | Tokens are audience-bound to specific MCP servers. Cross-server token replay prevented. | Implemented |
RFC 7009 | Token Revocation | Immediate server-side revocation. Access and refresh tokens invalidated independently. | Implemented |
RFC 9068 | JWT Profile | Structured access tokens. jti, iss, sub, aud, scope, exp, iat in every issued token. | Implemented |
RFC 9449 | DPoP | Sender-constrained tokens bound to a client-held key. Server nonces and JTI replay prevention built in. | Implemented |
RFC 8693 | Token Exchange | Impersonation and delegation with nested act chains, scope narrowing, and configurable depth limits. | Implemented |
RFC 7662 | Token Introspection | Server-side token state checks for confidential clients. Pairs with RFC 7009 revocation. | Implemented |
RFC 7523 · ID-JAG | JWT Bearer / XAA | Enterprise IdP-mediated authorization: trusted IdP registry, JWKS discovery, subject mapping. | Implemented |
RFC 9700 | OAuth Security BCP | PKCE required, exact redirect matching, refresh rotation, no implicit grant, no ROPC. | Implemented |
RFC 9457 | Problem Details | Structured error responses with machine-readable type URIs and human-readable descriptions. | Implemented |
- Redirect URI Exact match required — no wildcards, no partial matches
- alg=none Unsigned tokens rejected at the verification layer
- Key rotation Automated JWKS rotation with zero-downtime key rollover
- Token binding Audience claim bound to resource at issuance, validated on receipt
- Scope enforcement Token scopes validated against registered server permissions
- Clock skew Configurable tolerance window for exp/nbf/iat validation
Protect your server in 5 minutes.
Two env vars. Point your SDK at AuthPlane. PKCE, CIMD, JWKS rotation — all handled automatically.
# server.py — FastMCP + authplane-fastmcp
from fastmcp import FastMCP
from authplane_fastmcp import authplane_auth
auth = await authplane_auth(
issuer=os.environ["AUTHPLANE_ISSUER"],
base_url=os.environ["AUTHPLANE_BASE_URL"],
scopes=["mcp:echo"],
)
mcp = FastMCP("my-server", **auth)
@mcp.tool()
def echo(text: str) -> str:
return text // server.ts — @authplane/mcp
import { authplaneMcpAuth } from "@authplane/mcp";
const auth = await authplaneMcpAuth({
issuer: process.env.AUTHPLANE_ISSUER!,
resource: process.env.AUTHPLANE_RESOURCE!,
scopes: ["mcp:echo"],
});
app.get(
auth.protectedResourceMetadataPath,
auth.protectedResourceMetadataHandler,
);
app.use("/mcp", auth.bearerAuth); // main.go — authplane/go-sdk
import "github.com/authplane/go-sdk/mcp/pkg/authplanemcp"
adapter, err := authplanemcp.NewAdapter(ctx, authplanemcp.Options{
Issuer: os.Getenv("AUTHPLANE_ISSUER"),
Resource: os.Getenv("AUTHPLANE_RESOURCE"),
Scopes: []string{"mcp:echo"},
})
http.Handle(adapter.WellKnownPRMPath(),
adapter.ProtectedResourceMetadataHandler())
http.Handle("/mcp", adapter.AuthMiddleware(handler)) Three paths. One server.
Same server, different configurations. Pick the path that matches your environment.
Local Development
SQLite · Zero config
docker run -p 9000:9000 -p 9001:9001 \
-e AUTHPLANE_ADMIN_API_KEY \
authplane/authserver:latest serve Production
PostgreSQL · HA ready
helm install authplane \
oci://ghcr.io/authplane/charts/authplane \
--values prod.yaml Regulated Enterprise
Vault Transit · Air-gapped
authserver serve \
--config /etc/authplane/config.yaml Start building with AuthPlane.
Open source. Self-hosted or cloud-hosted. No credit card required.