A quality engineer at a mid-size biopharma was testing a new MCP-connected AI assistant against their QMS. The assistant could read deviations, search CAPAs, and pull batch records — all through natural language. During a routine audit, the compliance team asked a simple question: “When the AI calls our QMS, whose credentials does it use?”

Nobody had an answer. The MCP server had been deployed with a shared service account and static API key. Every tool call — whether it was Jane from QA querying a deviation or the CI/CD pipeline running a validation — looked identical in the logs. Attributability was zero. The system was pulled from production the same afternoon.

This is not a hypothetical. Forty-one percent of production MCP servers currently have zero authentication. The protocol is powerful; the security story is implementation-dependent. And if you are deploying MCP in anything beyond a local prototype, the details of how authentication and authorization actually work at the protocol level are the difference between a compliant system and an audit finding.

The Core Design: Two Transports, Two Security Models

MCP supports two transport mechanisms, and the authentication strategy is completely different for each.

stdio (Local Transport)

When an MCP client spawns a local server via stdio, there is no network authentication. The server runs as a child process under the host user’s OS privileges. Communication happens over stdin/stdout pipes — no network exposure, no bearer tokens, no OAuth flow. Secrets for downstream services (database passwords, API keys) are injected via environment variables at startup.

This model works for desktop tools and local development. It does not work for remote servers, multi-tenant deployments, or any environment where attributability matters.

Streamable HTTP (Remote Transport)

This is where all authentication complexity lives. The legacy SSE transport was deprecated in June 2025 and officially removed in the July 2026 spec revision. Streamable HTTP is now the only standard remote transport, and it carries a mandatory OAuth 2.1 authorization framework.

The critical architectural decision: the MCP server is only an OAuth 2.1 Resource Server. It validates tokens. It does not issue tokens, manage user logins, or act as an Authorization Server. That responsibility belongs entirely to an external identity provider.

The Four Roles

The MCP auth model maps cleanly onto standard OAuth 2.1 roles:

OAuth Role MCP Equivalent Responsibility
Resource Owner End User Owns the data/actions the server exposes
Client MCP Client (Claude, VS Code, custom agent) Requests access on behalf of the user
Resource Server MCP Server Hosts tools/resources; validates tokens
Authorization Server External IdP (Keycloak, Okta, Entra ID) Authenticates users; issues tokens

This separation is not optional. If your MCP server was also its own authorization server, that pattern was explicitly deprecated by the June 2025 spec revision. The MCP server validates. The IdP issues.

The Discovery Flow

Before any token is exchanged, the MCP client needs to discover where to authenticate. The spec mandates a two-step discovery process.

Step 1: Protected Resource Metadata (RFC 9728)

When an unauthenticated client hits the MCP server, the server responds with a 401 and points to its metadata document:

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

The metadata document tells the client which authorization servers the MCP server trusts:

{
  "resource": "https://mcp.example.com",
  "authorization_servers": ["https://idp.example.com"],
  "scopes_supported": ["mcp:read", "mcp:write"],
  "bearer_methods_supported": ["header"]
}

This is mandatory. MCP servers must implement it. MCP clients must use it. The old fallback of default endpoints at /authorize and /token was removed.

Step 2: Authorization Server Metadata (RFC 8414)

The client picks an authorization server and fetches its configuration:

GET /.well-known/oauth-authorization-server

This returns the actual OAuth endpoints: authorization endpoint, token endpoint, registration endpoint, JWKS URI, supported scopes, and PKCE methods.

The Authorization Flow

Once the client has the endpoints, it runs the standard OAuth 2.1 Authorization Code flow with several MCP-specific requirements:

PKCE is mandatory for all clients. Since most MCP clients are public applications (desktop apps, CLI tools) that cannot securely store client secrets, PKCE with S256 is required — not optional.

Resource Indicators (RFC 8707) are required. The resource parameter in the authorization request must be the MCP server URL. The authorization server must bind the token to that audience. The MCP server must reject tokens that lack the correct audience binding.

This is the control that prevents token replay across multiple MCP servers. If you have five subagents each talking to different MCP server surfaces, Resource Indicators ensures a token minted for the QMS server cannot be replayed against the LIMS server.

Issuer validation (RFC 9207) is now required. The authorization server returns an iss parameter in the authorization response, and the client must validate it before exchanging the code. This prevents mix-up attacks when a client interacts with multiple authorization servers.

The complete flow:

Client → MCP Server: POST /mcp (no token)
MCP Server → Client: 401 + WWW-Authenticate (metadata URL)
Client → Auth Server: Discovery + Registration
Client → Auth Server: /authorize + PKCE + resource indicator
User → Auth Server: Login + consent
Auth Server → Client: Authorization code
Client → Auth Server: /token (code + code_verifier)
Auth Server → Client: Access token + refresh token
Client → MCP Server: POST /mcp + Authorization: Bearer <token>
MCP Server: Validate signature, issuer, audience, expiry, scopes
MCP Server → Client: 200 + response

Client Registration: The DCR Problem

Before the OAuth flow begins, the client needs a client_id. The MCP spec defines a preference hierarchy:

Client ID Metadata Documents (CIMD) — the recommended approach as of July 2026. The client hosts a metadata document at a URL it controls. The authorization server fetches this to learn about the client. No pre-registration needed, but with verifiable identity.

Dynamic Client Registration (DCR, RFC 7591) — now formally deprecated. The client POSTs to a registration endpoint at runtime. This was the primary mechanism in early spec versions but has been deprecated because of a serious security problem: a May 2026 study of 119 testable OAuth-enabled MCP servers found DCR flaws in 96.6% of them. Every tested server had at least one vulnerability.

Pre-registered static client IDs — the simplest approach for controlled environments. You control both the client and the auth server, so you register ahead of time.

Manual entry — the user inputs a client_id via a UI. Works for edge cases.

The critical rule: multiple MCP clients must not share the same OAuth client_id. If they do, the authorization server cannot distinguish between them, and scope caching can leak data across clients.

Token Validation

Once the MCP server receives a request with a Bearer token, it must validate at minimum:

Check What It Verifies
Signature Token was actually issued by the trusted issuer
Issuer (iss) Matches the expected IdP
Audience (aud / resource) Token was minted for THIS MCP server
Expiration (exp) Token has not expired
Not-before (nbf) Token is already valid
Scopes Token contains required permissions

The preferred approach is stateless JWT validation: the MCP server downloads the IdP’s JWKS (public keys) and validates the signature locally. No per-request call to the authorization server. No introspection latency. Fully scalable.

For opaque tokens or environments requiring active revocation, token introspection against the authorization server is the alternative — higher latency but enables immediate credential revocation.

What Changed in July 2026

The 2026-07-28 specification revision was the most significant tightening of MCP authorization requirements to date. Six changes:

  1. Issuer validation (RFC 9207) — prevents authorization server mix-up attacks in multi-server deployments.

  2. Application type declaration — clients must declare whether they are web or native during registration, fixing the long-standing problem where authorization servers rejected localhost redirects for desktop apps.

  3. Credential binding to issuer — client credentials cannot be reused across different authorization servers, preventing cross-AS token replay.

  4. Offline access scope — standardizes refresh token requests via the offline_access scope.

  5. Scope step-up — formalizes how clients handle escalating permission needs. When a tool requires additional scopes, the server signals what it needs and the client requests the union of existing plus new scopes.

  6. Stateless transport — protocol sessions were removed from the transport layer. The old initialize/Mcp-Session-Id model is gone. Requests are independently routable. HTTP headers Mcp-Method and Mcp-Name can be used by gateways for routing and authorization decisions.

Additionally, Dynamic Client Registration was formally deprecated in favor of CIMD, and Enterprise-Managed Authorization was promoted to an official extension.

Enterprise-Managed Authorization

For enterprise deployments where per-server consent screens are impractical, the MCP specification now supports the EMA extension. This is the most important enterprise feature added in 2026.

The problem: Without EMA, every MCP server requires its own OAuth consent flow. An enterprise with dozens of MCP servers — QMS, LIMS, ELN, ERP, document management — faces consent-screen fatigue and cannot centrally control which servers users access.

How EMA works:

  1. An enterprise identity provider governs policy: which MCP clients can reach which MCP servers, on behalf of which users.
  2. The IdP issues a signed Identity Assertion JWT Authorization Grant (ID-JAG) under administrative policy.
  3. The MCP server’s authorization server validates the assertion and mints scoped access tokens.
  4. No per-user consent screen is shown. Access is governed by enterprise policy.

ID-JAG claims include:

  • iss — identity provider issuer URL
  • sub — user principal identifier
  • aud — target MCP server identifier
  • groups — security group memberships
  • roles — assigned roles
  • exp — expiration time

As of mid-2026, EMA is supported by Anthropic (Claude, Claude Code, Cowork), Microsoft (VS Code), Okta, and major server publishers including Asana, Atlassian, Figma, Slack, and Supabase.

For a regulated life-sciences environment, EMA means an administrator can provision “QA team members can access MCP-QMS, MCP-LIMS, and MCP-ELN” as a single IdP policy — without every user clicking “Allow” on each server individually.

Identity Propagation: The Hardest Part

Authentication tells the MCP server who is calling. But in a real deployment, the MCP server must translate that identity into its own internal user context — and do so without escalating privileges.

The principle: The MCP server must never operate as an elevated service account. It must extract the sub claim from the token, look up the internal user, and execute business logic with that user’s permissions.

In co-located mode, this is a direct call: OrderService.create_order(userContext). In microservice mode, the user ID or token is passed downstream, and each downstream service enforces the same permission checks as if the call came from a human clicking buttons in a UI.

The confused deputy problem: When the MCP server needs to call an upstream service (a CRM, a database, an external API), it must not forward the token it received from the MCP client. That token was minted for the MCP server’s audience, not for the upstream service. Forwarding it creates a confused deputy vulnerability where the upstream service may trust a token not intended for it.

The correct pattern: the MCP server uses Token Exchange (RFC 8693) to obtain its own token scoped for the downstream resource, or uses its own service credentials with explicit user-context propagation.

Machine-to-Machine Authentication

Not every MCP client is a human. Scheduled agents, CI/CD pipelines, background validation jobs, and monitoring agents all need to call MCP servers without interactive user login.

The MCP specification supports OAuth Client Credentials flow for these scenarios. The principal is the service identity, not a human. Keycloak has introduced token exchange delegation as an experimental feature, allowing a subagent to act under a delegated user identity rather than a shared service account — which is significantly better for audit attributability.

The fundamental question in M2M scenarios: who is the principal? With human OAuth, you can trace Jane → Agent → MCP Server. With M2M, the principal is the service identity. That distinction matters enormously for audit trails in regulated environments.

Tool-Level Authorization: What the Spec Does Not Cover

Here is the most important limitation: the MCP specification does not define tool-level access control. If a user is authenticated and authorized to connect to an MCP server, they can invoke all tools that server exposes.

There is no protocol-level mechanism for:

  • Role-based tool permissions
  • Resource-level ACLs
  • Per-tool scope requirements
  • Parameter-level authorization

This is not a gap in understanding — it is a gap in the specification. Implementers must build tool-level authorization into their server application code, using JWT claims (roles, groups, scopes) to gate access before executing each tool.

The recommended pattern for regulated environments: define a policy hierarchy that considers more than just the user.

Subject:       Who is the user?
Agent:         Which AI agent is making the request?
Tool:          What operation is being requested?
Resource:      Which specific record (CAPA, batch, deviation)?
Action:        Read, create, modify, approve, release?
Context:       Production? GxP? Business hours? Human approval required?

A simple ALLOW/DENY is insufficient for GxP. The decision space should include REQUIRE_HUMAN, REQUIRE_SECOND_APPROVER, and REQUIRE_ELECTRONIC_SIGNATURE.

The Seven-Layer Defense Model

For regulated deployments, MCP authentication should be one layer in a defense-in-depth architecture:

┌──────────────────────────────────────┐
│ Layer 1: Network                     │
│ TLS, mTLS, private networking, WAF   │
├──────────────────────────────────────┤
│ Layer 2: MCP Authentication          │
│ OAuth 2.1, OIDC, JWT validation      │
├──────────────────────────────────────┤
│ Layer 3: Identity                    │
│ Human, agent, service, tenant        │
├──────────────────────────────────────┤
│ Layer 4: RBAC                        │
│ Role-to-tool mapping                 │
├──────────────────────────────────────┤
│ Layer 5: ABAC                        │
│ Department, environment, risk level  │
├──────────────────────────────────────┤
│ Layer 6: Tool Authorization          │
│ READ=auto, APPROVE=HITL, RELEASE=HITL│
├──────────────────────────────────────┤
│ Layer 7: Audit                       │
│ Who, what, when, agent, tool, params,│
│ policy decision, result              │
└──────────────────────────────────────┘

Every layer should be capable of independently saying no.

Authorization should happen at least twice. The agent harness enforces agent-specific policy (which tools this agent is allowed to call), while the MCP server enforces resource-level security (which user has access to which data). Defense in depth means a prompt injection that tricks the agent cannot bypass both layers.

The Bottom Line

MCP authentication is OAuth 2.1 with mandatory PKCE, resource indicators for audience binding, and a clean separation between Resource Server and Authorization Server. The July 2026 revision hardened the spec significantly — issuer validation, credential binding, scope step-up, and the deprecation of Dynamic Client Registration in favor of CIMD.

But authentication is only half the problem. Authorization — controlling which users can invoke which tools with which parameters — remains outside the protocol. For regulated environments, that gap must be filled with a policy engine that considers subject, agent, tool, resource, action, and context.

The protocol gives you a standardized transport for identity. Everything else — tool-level RBAC, segregation of duties, electronic signatures, immutable audit trails — is your architecture to build. MCP is the foundation, not the building.


Research notes: [[MCP Authentication and Authorization - Comprehensive Report]]