MCP Authentication Methods: Complete Comparison
OAuth 2.1 with PKCE, API keys, and JWTs solve different MCP authentication problems. Here's what each actually protects against, and where real production MCP servers (Zerodha, Swiggy, Razorpay) land on this spectrum.
The MCP specification itself doesn't mandate one authentication scheme — it defines how a client and server exchange messages, not how they establish trust. In practice, three patterns cover almost every real MCP server in production, and they solve genuinely different problems.
OAuth 2.1 with PKCE — For User-Delegated Access
This is the pattern behind most consumer-facing official MCP servers covered on this site: Swiggy's three MCP servers use OAuth 2.1 with PKCE explicitly, and Zomato's uses OAuth for its Claude/ChatGPT connections. The core value: the AI client never sees or stores the user's actual credentials — the user authenticates directly with the service (Swiggy, Zomato, Zerodha) through that service's own login flow, and the MCP client only ever holds a scoped, revocable token. PKCE specifically matters because MCP clients are frequently native apps or CLIs without a securely-hidden client secret — the same reasoning that made PKCE the standard for public OAuth clients well before MCP existed.
API Keys — For Simple, Internal, or Read-Only Tools
A static API key is the simplest possible auth model, and it's a legitimate choice for internal tooling or servers with genuinely low blast radius. It becomes a real liability specifically when keys are long-lived, unscoped (one key that can do everything rather than several narrowly-scoped ones), or shared across environments (the same key used in dev and production). If you're building an internal MCP server for your own team, API keys with rotation and per-key scoping are a reasonable, proportionate choice — reach for OAuth when you're building something a third party's end users will authenticate through.
JWT — For Stateless, Distributed Verification
JSON Web Tokens carry their own claims (user ID, scopes, expiry) in a cryptographically signed payload, so any server instance can verify a token without a round-trip to a central session store. This matters specifically when an MCP server runs across multiple stateless instances behind a load balancer — every instance can independently validate the same token. The tradeoff: a JWT is valid until it expires or its signing key is rotated, so short expiry windows and a real refresh-token flow matter more here than with a server-side session you can revoke instantly.
Which One Should You Actually Use
- Building for real, external end users (like Zomato, Swiggy, Razorpay did) → OAuth 2.1 with PKCE.
- Internal tooling, single team, low-risk actions → scoped API keys with rotation.
- Multiple stateless server instances that need independent verification → JWT, layered on top of whichever initial auth (OAuth or API key) issued it.
These aren't mutually exclusive in practice — a real production system often uses OAuth to initially authenticate the user, then issues short-lived JWTs for the actual per-request MCP calls, combining the delegation model of OAuth with the stateless verification of JWT.