All posts
COMPARISON
Open source MCP auth: what your options actually are — cover art

Open source MCP auth: what your options actually are

Four ways to put OAuth 2.1 in front of an MCP server, and the point where each one runs out of road.

TL;DR

  • Four real options: Keycloak, a cloud identity provider, build it yourself, or a server built for MCP. They all work.
  • Keycloak covers the OAuth core but does not read the resource parameter, so you bind token audiences by hand, one mapper per server.
  • Two questions usually settle it: can your tokens leave your network, and do your agents act on each other's behalf?

You built an MCP server. It runs. Now you want agents other than your own to reach it, and the auth you put off is the thing between you and production. Once the server is remote, the MCP spec expects OAuth 2.1, so that static key in your .env is not a long-term answer.

If it is any comfort, you are in a crowd. Astrix Security analyzed more than 5,200 open-source MCP servers for its State of MCP Server Security 2025 report, published that October. 88% require some credential, 53% run on a long-lived static key or personal access token, and 8.5% use OAuth. The study read repository READMEs rather than code, so treat the split as directional. The direction is unambiguous, and nothing since suggests it has reversed.

There are four realistic ways to get a spec-compliant OAuth 2.1 layer in front of your server. Here is each one, and where it falls short.

What the MCP spec requires of an authorization server

"Does it do OAuth" is not a useful question. The spec is specific about which requirements land on the authorization server, which land on the client, and which land on your MCP server. Getting those confused is where most of the confusion starts. These levels are from the authorization section of the spec.

RequirementWho / levelWhat it does
OAuth 2.1AS: MUSTAuthorization code flow with mandatory PKCE for public clients.
A discovery mechanismAS: MUST provide oneEither RFC 8414 metadata or OpenID Connect Discovery, so clients can find its endpoints.
Client ID Metadata Documents (CIMD)AS and client: SHOULDA newer registration approach used by clients like VS Code and Claude Code.
Dynamic Client Registration (RFC 7591)AS and client: MAYRegistration with no prior relationship. Now deprecated in favor of CIMD (see below).
Resource Indicators (RFC 8707)Client MUST send; server MUST validateBinds a token to one MCP server. The client sends resource; your server rejects tokens not issued for it.
Issuer identification (RFC 9207)AS: SHOULD send; client MUST validateThe AS returns iss in the authorization response; the client checks it before redeeming the code. Closes the authorization-server mix-up attack. New in 2026-07-28, and the spec signals it will become a MUST for the AS.

Three things to pull out of that. The spec does not require the authorization server to support RFC 8707. It requires the client to send the resource parameter and your MCP server to validate the audience, so an authorization server that ignores resource is still usable, you just have to arrange the binding another way. Protected Resource Metadata (RFC 9728) is a MUST, but it belongs to your MCP server, not the authorization server. And RFC 9207 is the newest arrival: no authorization server in this comparison has published a compliance position on it yet, which makes it the thing to ask any vendor about.

One update: the current spec is 2026-07-28, and it deprecates Dynamic Client Registration (DCR) in favor of Client ID Metadata Documents (CIMD). DCR still works for now. Most authorization servers, Keycloak included, have not fully caught up to that revision yet, which is worth keeping in mind as you read the rest. We go through the revision in detail in MCP 2026-07-28: what changes for authorization.

Option 1: Keycloak for MCP auth

Keycloak is the first name most people reach for, and that is a fair instinct. It is a CNCF project, it has been in production for a decade, and if you already run it for employee SSO, adding a realm for MCP is a Tuesday.

The OAuth core is solid. Per Keycloak's own MCP guide, it supports OAuth 2.1, RFC 8414 metadata, and Dynamic Client Registration, and it can do Client ID Metadata Documents behind an experimental flag (kc.sh start --features=cimd).

The snag is Resource Indicators. Keycloak's compliance table lists RFC 8707 as "Not supported," and the guide puts it bluntly: Keycloak cannot recognize the resource parameter. Keycloak is hard on itself about this, grading its own MCP conformance "Partially Supported without Resource Indicators." Read strictly, the spec is more forgiving: it puts the resource-parameter MUSTs on the client and on your MCP server, and tells clients to send the parameter "regardless of whether authorization servers support it." Either way the practical consequence is the same. Your MCP server still has to reject tokens that were not minted for it, and reading resource is the clean way an authorization server sets that audience. Without it, you set the audience yourself.

Here is what "yourself" looks like, straight from Keycloak's instructions. Say your server is https://example.com/mcp with three scopes. You create a client scope for each one, then add an Audience mapper to each with the server URL typed into the Included Custom Audience field. Three scopes, three mappers, one server. The result is a token with the right aud:

{
  "aud": "https://example.com/mcp",
  "scope": "mcp:tools mcp:prompts mcp:resources"
}

It works, and the docs walk you through every click. It is also configuration you own and repeat for every server you protect, and native resource support is on the Keycloak community's roadmap rather than in a release. If you already live in Keycloak and do not mind the mapping, this is a real path. If you are standing auth up for agents specifically, that per-server step is the thing to weigh.

Option 2: a cloud identity provider (Auth0, WorkOS, Descope)

Auth0, WorkOS, Descope, Stytch, Scalekit. Managed OAuth you point at, where someone else absorbs the spec churn every time MCP revises. WorkOS pitches exactly that: paste a URL, skip the authorization-server plumbing.

The catch is location. Your tokens, and the identity behind them, pass through a third party. Plenty of teams are fine with that. Some vendors offer dedicated or private-cloud deployments that answer a geographic residency requirement, though the service is still operated by the vendor on their schedule. If your constraint is an on-prem mandate, or a rule that identity data cannot leave your perimeter at all, no managed option clears it, and this branch closes before the feature comparison starts.

Option 3: build your own MCP authorization server

The spec is public and for one server it looks like a weekend. The first version usually is. Nobody quotes you for the maintenance.

A real authorization server means a dozen or more OAuth RFCs, plus key rotation, JWKS, refresh rotation with replay detection, and an audit trail you can hand to a reviewer. Then the spec moves. It has revised four times since launching in November 2024, 2025-03-26, 2025-06-18, 2025-11-25, and now 2026-07-28, and the latest revision deprecates DCR for CIMD. Building it yourself means signing up to chase that indefinitely. Most teams did not set out to run an identity team.

Option 4: a purpose-built MCP authorization server

This is where AuthPlane sits, so read it as one of the four rather than a sales turn. It is an open-source OAuth 2.1 authorization server for MCP. The server is AGPL-3.0, the SDKs are Apache-2.0. That licensing line tends to be the first thing an engineering manager forwards to legal, so it is worth saying up front.

It is a single Go binary with an admin UI built in, and it runs next to your MCP server instead of in front of it. Your server validates tokens locally against the JWKS, so only the OAuth flows touch AuthPlane and nothing sits in your request path. That distinction is the subject of its own piece, authorization server or gateway, if the difference is not obvious. Tokens are short-lived and audience-bound, and scopes go down to the tool level. When the calling client is registered as an agent, the token also carries its identity and the delegation chain: a record of which agent made the call and on whose behalf. Non-agent traffic, like service-to-service calls and admin operations, is issued without those claims, so your MCP server can tell agent-mediated requests from the rest. Chains nest up to five hops by default, and the flattened chain claim holds eight entries.

On agent identity across the field: Keycloak has no native concept of it. Among the cloud providers it varies. Auth0 shipped Agents as Principal, currently in Early Access, which gives an agent its own stable identifier and audit trail. The rest treat an agent as just another OAuth client.

On the audience question that trips up Keycloak: AuthPlane reads the resource parameter and stamps the audience into the token automatically, on every grant. You register a server once, and there is no per-server mapper to maintain. Matching is exact: the resource identifier has to match what you registered, with no prefix or wildcard matching.

Open source MCP auth options compared

Rows are the requirements from the top. Every cell about a third party is sourced.

CapabilityKeycloakCloud IdPBuild your ownAuthPlane
OAuth 2.1 + PKCEYesYesYou build itYes
Discovery (8414 / OIDC)YesYesYou build itYes
Audience binding (resource)Manual, per serverVaries by vendorYou build itYes, automatic
Agent identity + delegationNo native conceptVaries: Auth0 ships Agents as Principal (EA); others noneYou build itNative
Self-hostedYesNoYesYes
Data-residency optionsYesDedicated / private cloud from some vendorsYesYes
Who tracks spec revisionsCommunity-pacedVendorYouMaintainers, shipped as releases

One note on that last row. As of publication, no authorization server in this table has published a 2026-07-28 compliance statement, AuthPlane included; its docs currently document 2025-11-25. The row describes who owns the upgrade work, not who has finished it.

When Keycloak (or no authorization server) is the right call

A comparison that only points one direction is not worth your time, so here is where AuthPlane is not the answer. If you already run Keycloak for human SSO, have no residency constraint, and your agents do not delegate to each other, extending what you already operate beats adding a component. And if you are one person running a single local server with no delegation and nothing regulated, you may not need an authorization server at all. A static key on localhost is fine.

Which MCP auth option should you pick?

The destination is not in question. The spec already picked it: OAuth 2.1, audience-bound tokens, real scopes, a discovery endpoint. You are choosing the road. Keycloak if you already run it and can live with the manual mapping. A cloud IdP if your tokens are allowed to leave. Roll your own if you want to own the treadmill. And if you would rather have the agent-specific pieces handled and keep your infrastructure yours, that is the fourth option.

AuthPlane is open source and self-hosted. Point it at your own server and see where it holds up: github.com/AuthPlane.

Sources

  1. MCP Authorization specification, 2026-07-28 (current). https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization
  2. Keycloak, Integrating with Model Context Protocol (MCP). https://www.keycloak.org/securing-apps/mcp-authz-server
  3. Astrix Security, State of MCP Server Security 2025. https://astrix.security/learn/blog/state-of-mcp-server-security-2025/
  4. Auth0 Docs, Agents as Principal. https://auth0.com/docs/ai-agents-mcp/agents-as-principal
  5. RFC 8414, OAuth 2.0 Authorization Server Metadata. https://datatracker.ietf.org/doc/html/rfc8414
  6. RFC 7591, OAuth 2.0 Dynamic Client Registration Protocol. https://datatracker.ietf.org/doc/html/rfc7591
  7. RFC 8707, Resource Indicators for OAuth 2.0. https://datatracker.ietf.org/doc/html/rfc8707
  8. RFC 9207, OAuth 2.0 Authorization Server Issuer Identification. https://datatracker.ietf.org/doc/html/rfc9207
  9. RFC 9728, OAuth 2.0 Protected Resource Metadata. https://datatracker.ietf.org/doc/html/rfc9728