MCP Directory

MCP OAuth: how remote-server auth works

Local servers skip auth entirely. The moment you go remote, OAuth 2.1 shows up — here's exactly what it's doing and why the flow looks the way it does.

Hua·June 30, 2026·6 min read
Dynamic urban scene showcasing interconnected light trails representing digital communication networks.
Photo by Pixabay on Pexels

MCP OAuth is how a remote MCP server proves you authorized the agent to act on your behalf — using OAuth 2.1, a redirect to the service's login page, and a scoped access token the client attaches to every request. If you only run local servers, you have never seen it: about 90% of MCP servers run locally over stdio and need no auth at all. OAuth is the price of going remote.

This matters because the ecosystem is drifting toward hosted servers, and the auth story is genuinely different from a static API key. Below is what the flow actually does, what the 2.1 spec makes mandatory, and where clients still trip.

When you actually hit OAuth (and when you don't)

You hit OAuth only with remote MCP servers that choose it. Local stdio servers borrow your machine's existing trust and skip auth entirely.

Three servers from our catalogue show the whole spectrum. The Filesystem reference server is stdio with authType: none — it's confined to directories you pass as arguments, so there's nothing to log into. Context7 has a hosted endpoint at https://mcp.context7.com/mcp but uses an optional API key, not OAuth — a static-key remote. The GitHub MCP Server is the OAuth case: run it locally via Docker with a personal access token, or connect to GitHub's hosted server at https://api.githubcopilot.com/mcp/ over OAuth.

That GitHub split is the whole argument for OAuth in one server. A PAT is a long-lived credential sitting in your config; the hosted variant hands you a short-lived, scoped token and never stores a standing secret on disk.

What the OAuth 2.1 flow does, step by step

The flow is authorization-code-with-PKCE — the same pattern a well-built mobile app uses, adapted so the client is your MCP host (Claude, Cursor, VS Code) rather than a browser SPA. Here's the sequence:

  1. Discovery. The client hits the server, gets a 401 with a WWW-Authenticate header pointing at the authorization server, then reads its metadata (/.well-known/oauth-authorization-server) to learn the authorize and token endpoints.
  2. Registration. If the client isn't pre-registered, it can register itself via Dynamic Client Registration — no manual client-ID copy-paste.
  3. Authorize. The client opens the service's login page in your browser. You approve the requested scopes. This is the only human step.
  4. Callback + token exchange. The service redirects back with an authorization code; the client exchanges it (plus its PKCE verifier) for an access token and usually a refresh token.
  5. Call. Every MCP request now carries Authorization: Bearer <token>. When it expires, the client silently refreshes.

The part people miss: the MCP server is the resource server, and it may not be the authorization server. GitHub's login is separate from the MCP endpoint you're calling. That separation is exactly what the 2.1 spec formalizes.

What the spec makes mandatory

MCP's auth spec is built on OAuth 2.1, and 2.1 removes the footguns that made classic OAuth 2.0 easy to get wrong. Three requirements matter to anyone shipping or debugging a server:

RequirementWhat it meansWhy it's mandatory
PKCE on every flowClient sends a hashed code_challenge, proves it later with the code_verifierStops a stolen authorization code from being redeemed by anyone else
Exact redirect-URI matchNo wildcard or prefix matching on the callback URLCloses open-redirect token theft
Resource indicators (RFC 8707)Client names the target MCP server as the resource when asking for a tokenThe token is bound to that server, so a malicious server can't replay it elsewhere

The resource-indicator rule is the one most specific to MCP. Because a host may talk to many servers, a token minted for server A must not be usable against server B. RFC 8707 audience-binding is how the spec prevents a confused-deputy attack between servers. If you're evaluating a remote server, this is the box to check.

Implied-grant and password-grant flows are gone in 2.1. If a server asks for your username and password directly instead of redirecting you to the real login page, that's not MCP OAuth — treat it as a red flag.

What clients handle for you — and where they don't

Good news: for the whole flow above, the client does the work. You click "connect," a browser tab opens, you approve, and the token lifecycle (storage, refresh, attaching the header) is invisible. Adding a remote server is usually a URL plus a one-time login — see how to add an MCP server for the mechanics per client.

Where it still breaks in mid-2026:

  • Uneven client support. Not every host implements Dynamic Client Registration or metadata discovery. A server that assumes them will fail in a client that doesn't, with an opaque 401.
  • Localhost callbacks. Desktop clients listen on a loopback port for the redirect; a firewall or a hijacked port produces a hang, not an error.
  • Scope surprises. You approve broad scopes at login and forget. OAuth's advantage over a PAT is scoping, but only if you read the consent screen.

OAuth also doesn't make a server trustworthy — it only proves who's calling. What the server does with your authorized access is a separate question, and MCP security is where the real risk lives. A scoped token in front of a tool that will read arbitrary URLs is still a prompt-injection surface.

Should you prefer OAuth servers?

For anything that acts on your behalf against a real account — GitHub, a calendar, a CRM — yes, prefer the OAuth remote over pasting a long-lived token. You get short-lived credentials, real scopes, and revocation from the provider's dashboard, and nothing sensitive sits in a config file. That's why OAuth is disproportionately the auth model on official vendor servers: the vendor is the one who can host the authorization server correctly.

But don't go remote just to get OAuth. If a local stdio server already does the job with your existing CLI credentials, that's the more private default — no third party sees your traffic. Reserve remote-plus-OAuth for the cases where a hosted server earns it: team sharing, no local runtime, or a token you'd rather not store. Weigh it the same way you'd weigh any local vs remote MCP decision, and browse the best MCP servers for OAuth-capable options before you commit.

FAQ

Is MCP OAuth safe to use?

Yes, and it's usually safer than the alternative. OAuth 2.1 gives you short-lived, scoped tokens instead of a long-lived API key sitting in a config file, requires PKCE on every flow, and lets you revoke access from the provider's dashboard. The catch is that OAuth only proves who's calling — it doesn't vet what the server does with that access, so tool-level security still matters.

Do I need to configure OAuth myself?

No. The MCP client (Claude, Cursor, VS Code) handles discovery, PKCE, the browser login, and token refresh for you. For a remote server you typically just add its URL and approve a one-time login screen; the token is stored and refreshed behind the scenes.

Which MCP servers use OAuth?

Remote, hosted servers — most often official vendor ones. GitHub's hosted server at api.githubcopilot.com/mcp uses OAuth, while its local Docker variant uses a personal access token. Local stdio servers like the filesystem reference server use no auth at all, and some remote servers such as Context7 use an optional API key instead of OAuth.

What's the difference between MCP OAuth and an API key?

An API key is one long-lived static secret you paste into your config; anyone who reads it has full access until you rotate it. MCP OAuth issues short-lived, scoped tokens bound to a specific server via resource indicators, refreshes them automatically, and is revocable per-connection. OAuth is more moving parts but far less standing risk.

Why does OAuth 2.1 require PKCE and resource indicators?

PKCE stops a stolen authorization code from being redeemed by an attacker, closing the biggest classic-OAuth theft path. Resource indicators (RFC 8707) bind each token to the exact MCP server it was issued for, so a malicious server can't replay your token against a different one — a real concern when one client talks to many servers.

Put this into practice

Browse MCP servers by capability, or check your own setup's tool budget and security.

More essays