MCP Guides

OAuth 2.1 for MCP servers explained (the 2026 spec walkthrough)

๐Ÿ”Œ Connect MCP๐Ÿ“ฆ npm package๐Ÿ“š Docs๐Ÿ’ฌ Playground๐Ÿงญ Full guide๐Ÿ” OAuth discovery

How Plugsky MCP works in practice

Everything in this guide runs on Plugskyโ€™s live MCP endpoint (https://plugsky.com/mcp) or the npm bridge (npx -y @plugsky/mcp). A client request flows: JSON-RPC over Streamable-HTTP → auth (API key or OAuth 2.1 + Dynamic Client Registration with fine-grained scopes) → tool router → the service you asked for. Model calls run behind a 7-tier provider failover chain; browsing renders with headless Chromium; transcripts come from real captions and Groq Whisper; images generate on FLUX; code runs in a sandbox with no network; memory persists in your account (Postgres-backed); and every tool call is metered per user on your dashboard.

Relevant live tools for this article: POST /oauth/register (DCR), GET /oauth/authorize (PKCE), POST /oauth/token โ€” scopes mcp.read/mcp.write/mcp.web/mcp.media/mcp.memory/mcp.compute.

OAuth 2.1 for MCP servers explained (the 2026 spec walkthrough)

Direct answer

OAuth 2.1 for MCP is the 2026 spec's mandated authorization pattern for remote (Streamable-HTTP) servers. It combines OAuth 2.1 + PKCE (RFC 6749/8252), Protected Resource Metadata (RFC 9728), Authorization Server Metadata (RFC 8414), and optional Dynamic Client Registration (RFC 7591). A well-implemented MCP server exposes three well-known endpoints, an authorization endpoint, a token endpoint, and (recommended) a registration endpoint โ€” the MCP client discovers everything automatically via a 401 challenge.

Key facts

Governing specMCP 2026-07-28 authorization section
Underlying RFCs6749 (OAuth 2.0), 8252 (Native Apps), 7636 (PKCE), 9728 (Protected Resource Metadata), 8414 (AS Metadata), 7591 (DCR), 7592 (DCR Management)
MandatoryOAuth 2.1 + PKCE for remote servers
Optional but recommendedDynamic Client Registration (DCR)
Discovery entry point401 with WWW-Authenticate: Bearer resource_metadata="..."
Metadata paths/.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server
Required forChatGPT Business/Enterprise App directory, Claude Enterprise Connectors, Cloudflare MCP Catalog
Common scopeschat.chat, chat.tools:run, chat.rag:read, chat.files:write, offline_access

TL;DR

  • MCP OAuth = OAuth 2.1 + PKCE with automatic discovery.
  • Return 401 with WWW-Authenticate on unauthed requests โ€” the client parses it to find the auth server.
  • Expose two well-known JSON files describing your resource and auth server.
  • Support PKCE on /authorize, standard exchange on /token, and (recommended) Dynamic Client Registration on /register.
  • Use scoped tokens per tool group; issue refresh tokens if you want long-lived agent access.
  • Getting OAuth right unblocks ChatGPT App directory, Claude Enterprise, Cloudflare Catalog โ€” without it, you're capped at hobbyists.

How it works

The two well-known files

/.well-known/oauth-protected-resource

{
  "resource": "https://plugsky.com/mcp",
  "authorization_servers": ["https://plugsky.com/oauth"],
  "scopes_supported": ["chat.chat","chat.tools:run","chat.rag:read","chat.files:write","offline_access"],
  "bearer_methods_supported": ["header"],
  "resource_documentation": "https://plugsky.com/mcp/docs"
}

/.well-known/oauth-authorization-server

{
  "issuer": "https://plugsky.com/oauth",
  "authorization_endpoint": "https://plugsky.com/oauth/authorize",
  "token_endpoint": "https://plugsky.com/oauth/token",
  "registration_endpoint": "https://plugsky.com/oauth/register",
  "revocation_endpoint": "https://plugsky.com/oauth/revoke",
  "scopes_supported": ["chat.chat","chat.tools:run","chat.rag:read","chat.files:write","offline_access"],
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code","refresh_token"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none","client_secret_basic","client_secret_post"]
}

PKCE โ€” non-negotiable

MCP clients are considered public clients. PKCE (RFC 7636) is mandatory to defend against interception attacks.

  1. Client generates a random code_verifier (43โ€“128 chars).
  2. Computes code_challenge = BASE64URL(SHA256(code_verifier)).
  3. Sends code_challenge + code_challenge_method=S256 on /authorize.
  4. Sends code_verifier on /token.
  5. Server checks the SHA256 matches.

Dynamic Client Registration (DCR, RFC 7591)

DCR lets an MCP client bootstrap without a human first creating an OAuth app. The client POSTs client metadata to /register, the server returns client_id/client_secret. This is why a user can "add MCP URL to Claude" without touching a developer portal.

DCR is strongly recommended by the 2026 spec. Without it, every developer has to manually register your MCP as an OAuth app in their team โ€” killing adoption.

Scopes โ€” keep them fine-grained

Bad: one scope plugsky that grants everything.

Good: chat.chat, chat.models:read, chat.rag:read, chat.rag:write, chat.files:write, chat.tools:run, chat.web:read, chat.code:exec, chat.memory:read, chat.memory:write, offline_access.

With fine-grained scopes:

  • ChatGPT users can grant read-only.
  • Enterprise admins can restrict which teams get chat.code:exec.
  • Audits show precisely what an agent was authorized to do.

Refresh tokens vs long-lived access tokens

  • Refresh tokens โ€” required for long-running agents. Include offline_access scope. Rotate on every use (best practice).
  • Long-lived access tokens โ€” tempting but avoid; a leaked token is a full breach.

The 401 challenge โ€” the whole protocol hinges on this

When an unauthed request hits your MCP endpoint, return:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://plugsky.com/.well-known/oauth-protected-resource"

That single header tells the MCP client where to find your metadata. Miss it and clients can't self-configure.

Common OAuth implementation mistakes

Forgetting WWW-Authenticate on 401Add the header โ€” clients can't discover you without it
Not supporting PKCEAdd S256 support
No DCRAdd /register โ€” huge friction reducer
Scopes too broadSplit into read/write/exec per tool group
Access tokens without expirySet 1h TTL, issue refresh tokens
Skipping redirect_uri validationRequire exact match; reject wildcards
Storing refresh tokens in plaintextEncrypt at rest
No revocation endpointAdd /revoke per RFC 7009

Comparison โ€” Bearer vs OAuth 2.1 for MCP

Setup for userPaste keyClick login
RevocationManual regenerateOne-click on dashboard
Per-user scopingโŒโœ…
Leak blast radiusFull accountSingle client, single scope
Screenshots safeโŒโœ…
ChatGPT App directoryโŒโœ…
Claude Enterpriseโš ๏ธโœ…
Cloudflare CatalogโŒโœ…
Enterprise procurementโŒโœ…

FAQ

Q: Do I have to support OAuth 2.1 to publish an MCP server?

A: For local stdio, no. For remote (Streamable-HTTP), yes if you want listing in ChatGPT App directory, Claude Enterprise, or Cloudflare Catalog. Bearer works for hobbyists but blocks enterprise.

Q: What's Dynamic Client Registration and why do I need it?

A: DCR (RFC 7591) lets MCP clients auto-register themselves as OAuth apps, no manual dev-portal step. Without it, adoption dies at the friction of manual registration.

Q: How do refresh tokens interact with long-running agents?

A: Include the offline_access scope on your /authorize request; server issues a refresh token; agent silently exchanges it for a new access token when needed. Rotate on every use.

Q: What ports/URLs do I need to expose?

A: Just HTTPS on your usual domain. Add the two /.well-known/* files, /oauth/authorize, /oauth/token, optionally /oauth/register, /oauth/revoke. All standard REST.

Q: Can I use my existing OAuth server (Okta, Auth0, Entra) as the AS for MCP?

A: Yes โ€” as long as it advertises AS Metadata (RFC 8414) and supports PKCE. Most modern IdPs do.

Q: What about API keys for programmatic (headless) agents?

A: The client credentials grant is allowed. Issue service-account tokens with narrow scopes for headless use.

Trust & sources

Cite this page

Plugsky (2026). “OAuth 2.1 for MCP servers explained (the 2026 spec walkthrough)”. Plugsky. Available at: https://plugsky.com/articles/oauth-2-1-mcp-servers-explained-2026 (last updated 2026-09-30).