Skip to main contentArrow Right
MCP Server Security Best Practices Blog from Descope

Table of Contents

Summarize with AI

Don't have the time to read the entire post? Our human writers will be sad, but we understand. Summarize the post with your preferred LLM here instead.

The Model Context Protocol (MCP) has moved fast since Anthropic introduced it in November 2024. It is now a multi-company open standard under the Linux Foundation, and according to the maintainers, its Tier 1 SDKs are approaching half a billion downloads a month.

The auth spec has moved just as fast. Its July 2026 revision made the protocol stateless, formalized an extensions framework, and tightened authorization requirements. Security guidance written against earlier revisions now gets several details wrong, so this guide reflects the current spec.

At a glance

MCP server security best practices are the identity and access controls that keep a remote Model Context Protocol server from being reached, misused, or turned against its users: OAuth 2.1 authorization as the current spec defines it, tool-level scopes, governed client registration, and an audit trail of everything agents do.

  • This guide reflects the MCP specification's July 2026 revision (2026-07-28), which deprecated Dynamic Client Registration and added issuer validation and issuer-bound client credentials.

  • The baseline for a spec-compliant MCP server is OAuth 2.1 with PKCE (S256), resource indicators, token audience validation, and issuer validation.

  • Prefer Client ID Metadata Documents (CIMD) for client registration and keep Dynamic Client Registration (DCR) only for backward compatibility.

  • For enterprise customers, support Enterprise-Managed Authorization (EMA), and keep enforcing scopes per tool after the grant.

  • Never pass a client's token through to downstream services. Exchange it or use vaulted credentials.

  • These practices target remote (HTTP) servers. Local stdio servers retrieve credentials from the environment instead.

MCP security risks

Developers are still deploying MCP servers faster than security practices can keep up. A May 2026 measurement study from Fudan University researchers identified 7,973 live remote MCP servers and found that 40.55% exposed their tools with no authentication at all, while another 29% relied on static tokens or API keys. A separate dynamic security assessment of internet-facing MCP servers in July 2026 found that 91.8% of the audited servers lacked OAuth authentication completely, with 687 tool instances across these servers exposing shell execution capabilities without access controls.

Unfortunately, simply adding OAuth does not close the gap on its own, and the same OAuth misconfigurations and vulnerabilities other scenarios face are just as risky for MCP. The Fudan University team found at least one authentication flaw in each of the 119 OAuth-enabled servers they discovered. On 114 servers, the registration endpoint accepted any redirect URI from an anonymous registrant. On 81, a client could skip PKCE entirely or downgrade it to a weaker method.

Prompt injection is still a concerning problem in how it can relate to authorization. Security researcher and Databricks engineer Andre Landgraf demonstrated in a live session that injected instructions can get models to return sensitive admin API keys. As Landgraf put it, in-model defenses "cannot be the foundation on which you build your security architecture."

Enterprises are feeling the effects of MCP’s still-evolving security state. A Cloud Security Alliance survey commissioned by Token Security found that 65% of organizations had experienced an AI agent-related incident in the previous 12 months, and 82% had discovered AI agents they did not know were running. Descope’s survey of more than 400 identity decision-makers revealed a worrying gap between agent adoption and agentic identity readiness: An overwhelming majority, 94%, admit identity-related concerns about agents, led by the risk that agents will reach data beyond their scope and share data with people who shouldn't see it. Just under half, 46%, say their engineering teams lack the time or expertise to build agentic identity systems at all. Only 26% consider themselves knowledgeable about MCP.

The good news is that the MCP auth spec gets more prescriptive and easier to implement with every revision. The challenge is implementation: OAuth 2.1, PKCE, Protected Resource Metadata, client registration, and now enterprise-managed authorization all take real identity expertise to get right. Below are the eight MCP server security best practices we recommend for resilient, production-ready AI projects.

What changed in the July 2026 MCP spec

The 2026-07-28 release changed how MCP communicates far more than how it authorizes, but several authorization changes affect every remote server. These changes include:

  • Dynamic Client Registration (DCR) is formally deprecated in favor of Client ID Metadata Documents (CIMD). DCR still works for backward compatibility but will be removed in a future version.

  • Clients must validate the iss parameter (the issuer identifier) on authorization responses, per RFC 9207, before redeeming an authorization code. Authorization servers should send it today, and a future revision is expected to make that a requirement.

  • Client credentials are bound to the authorization server that issued them, and clients must re-register if that server changes.

  • Clients using DCR must declare an application_type (native or web), so authorization servers stop rejecting localhost redirects from desktop and CLI apps.

  • A formal extensions framework now hosts Enterprise-Managed Authorization (EMA), alongside MCP Apps and Tasks.

  • Protocol-level sessions and the initialization handshake are gone. Method and tool names now travel in the Mcp-Method and Mcp-Name HTTP headers.

For a full walkthrough, see What the July 2026 MCP Spec Revision Means for Identity and our MCP authorization specification deep dive.

MCP server security best practices at a glance

Best practice

Status in the current spec

What to do

Separate the authorization server from the resource server

Recommended; the spec permits co-hosting, but Protected Resource Metadata is required

Delegate token issuance to a dedicated authorization server and publish Protected Resource Metadata

Implement OAuth 2.1 as the current spec defines it

Required for HTTP-based MCP authorization

Enforce PKCE with S256, resource indicators, audience validation, issuer validation, and short-lived tokens

Authenticate users through SSO and support enterprise-managed authorization

SSO is best practice; EMA is a stable, optional extension

Authenticate users before agents act, and accept ID-JAG grants from enterprise customers' identity providers

Build consent management into the flow

Partly required; the redirect host must be shown during authorization

Show tools, data, duration, and redirect host, and confirm high-risk actions

Enforce scopes at the tool level

Recommended through scope challenges and step-up authorization

Keep default scopes minimal, challenge once per operation, and enforce per tool even after an EMA grant

Prefer CIMD for client registration

CIMD recommended; DCR deprecated

Use pre-registration or CIMD, and restrict DCR if you must keep it

Never pass tokens through

Required

Use token exchange or vaulted credentials for downstream calls

Audit everything and plan for revocation

Not addressed by the spec; recommended in OWASP's MCP guide

Log the full client lifecycle, revoke access on demand, and keep token lifetimes short

1. Separate your authorization server from your resource server

Earlier versions of the MCP auth specification treated MCP servers as both resource servers and authorization servers at once, which created significant complexity for implementers. The June 2025 revision classified MCP servers as OAuth resource servers, and the current spec keeps that role definition.

The current spec does not require a separate deployment, though. It states that the authorization server may be hosted with the resource server or as a separate entity. Separation is our recommendation rather than a mandate, and for most teams it is still the right call.

Diagram showing OAuth 2.0 roles in an MCP context: the MCP server as the resource server, the OAuth IdP as the authorization server, and the MCP client as the OAuth client
Fig: OAuth roles

The authorization server handles user authentication, token issuance, and client registration. The resource server (your MCP server) validates tokens and enforces access controls. Combining the two means maintaining OAuth infrastructure alongside your application logic. Auditing gets harder, scaling gets harder, and the implementation is more likely to drift out of compliance as the auth spec evolves.

The cleaner architecture delegates authorization to a dedicated identity provider (IdP) and lets your MCP server stick to what it is built to do. Two discovery requirements apply either way. MCP servers must publish OAuth 2.0 Protected Resource Metadata, and clients must use it to find the authorization server. Authorization servers must offer either OAuth 2.0 Authorization Server Metadata or OpenID Connect (OIDC) Discovery, and clients must support both. Clients handle discovery automatically, so nothing needs to be hardcoded.

See our MCP Authorization Specification deep dive to learn more.

2. Implement OAuth 2.1 the way the spec defines it

For HTTP-based MCP servers that implement authorization, OAuth 2.1 is the foundation, and its details matter. OAuth 2.1 is still an IETF draft that deprecates several older methods and adds new requirements. The current MCP spec layers its own requirements on top:

  • PKCE for every client, with S256. MCP clients must implement PKCE (Proof Key for Code Exchange) and must use the S256 challenge method when technically capable. If the authorization server's metadata omits code_challenge_methods_supported (the field that advertises PKCE support), the client must refuse to proceed. On the server side, reject authorization requests without a code challenge.

  • Resource indicators and audience binding. Clients must send the resource parameter (RFC 8707) in both authorization and token requests, identifying the MCP server by its canonical URI. MCP servers must validate that each token was issued specifically for them as the audience and reject anything else.

  • Issuer validation. Clients must record the expected issuer before redirecting the user and compare it to the iss value in the authorization response (RFC 9207) before redeeming the code. This closes the authorization server mix-up attack. If you run the authorization server, start emitting iss now.

  • Short-lived tokens and refresh rotation. Authorization servers should issue short-lived access tokens and must rotate refresh tokens for public clients.

  • Tokens in headers only. Access tokens go in the Authorization header on every request and never in a URL query string.

Most MCP clients, including CLI tools, IDE extensions, and desktop applications, cannot securely store a client secret. This is why PKCE is a core requirement, and why the Fudan study discussed above is so significant. If a threat actor can downgrade from PKCE to the weaker plain method and your server still accepts it, you lose all the defenses PKCE affords.

Sequence diagram depicting interactions between User, Client, AuthZ Server (Descope), and Resource Server. The User clicks a login link, prompting the Client to generate a code verifier and code challenge. The Client sends the code challenge with an authorization code request to the AuthZ Server, which prompts the User for authentication and consent. After the User consents, the AuthZ Server returns an authorization code. The Client exchanges this code along with the original code verifier; the AuthZ Server validates the pair, then issues ID and access tokens. The Client uses the access token to request and receive user data from the Resource Server.
Fig: Authorization Code Flow With PKCE

Learn more about OAuth 2.1 vs. OAuth 2.0 and how PKCE works.

If your team is not deeply familiar with OAuth and its in-draft revision, either take the time to learn the spec or use a solution that follows it to the letter. The OWASP GenAI Security Project's guide for secure MCP server development reaches the same conclusion, listing OAuth 2.1 and OpenID Connect for all remote MCP servers as the first item in its minimum security bar.

3. Support user SSO and enterprise-managed authorization (EMA)

For enterprise-facing MCP servers, connecting to your existing identity infrastructure is essential for getting production-ready. Users should authenticate through your SSO layer before any agent takes action on their behalf, whether that means reaching a shared Google Drive or your GitHub organization. Your MCP server must confirm that each token corresponds to a real authenticated user with the right permissions for the request.

Relying on the underlying language model to police access may be tempting, but it is dangerous. Prompt injection, context poisoning, and instruction drift are architectural problems, and the reliable fix is proper authentication, authorization, and scoping at the infrastructure level.

Screenshot of Andre Landgraf demonstrating a prompt injection attack that bypasses model-level defenses to extract sensitive admin API keys
Fig: Landgraf demonstrates a simple prompt injection scenario

The OWASP guide makes the same recommendation: centralize policy enforcement in a dedicated layer rather than relying on a model to tell legitimate instructions from malicious ones. Learn more in Why Model-Level Defenses Are Not Enough for MCP and the Top 6 MCP Vulnerabilities.

Enterprise-managed authorization: XAA, ID-JAG, and EMA

Enterprise customers increasingly want to govern agent access to your MCP server through the identity provider they already run, rather than having every employee click through a consent screen for every server. Three related terms describe how that works, each at a different layer:

  • Cross-App Access (XAA) is the pattern: an identity provider brokers one application's access to another application's API on a user's behalf. The IETF draft that defines the mechanism notes that its pattern is informally referred to as Cross-App Access.

  • The Identity Assertion JWT Authorization Grant (ID-JAG) is that IETF draft (at version 04 as of May 2026) and the name of the signed assertion it defines.

  • Enterprise-Managed Authorization (EMA) is the MCP extension that applies the grant to MCP clients and servers. The maintainers declared it stable in June 2026.

Under the EMA specification, the user signs in to the MCP client through the enterprise IdP. The client then uses OAuth token exchange to trade its ID token for an ID-JAG, and the IdP evaluates administrator policy before issuing it. The client presents the ID-JAG to your MCP server's authorization server, which validates it and issues its own access token, audience-restricted to your MCP server.

If you validate ID-JAGs, the draft's processing rules are the checklist. Confirm the token type is oauth-id-jag+jwt. Confirm that the aud claim (the audience) is your authorization server's issuer identifier, and that the client_id claim matches the client that authenticated the request. Register a trusted issuer per tenant, so an assertion minted for one customer cannot be used against another.

The ID-JAG draft says the grant should only be supported for confidential clients, with public clients using the standard authorization code flow and interactive consent. So EMA adds to the standard OAuth flow rather than replacing it. EMA also governs the connection, not each call inside it, which is why practice 5 still applies after the grant.

For a deeper look at how each layer is defined, see XAA vs. ID-JAG vs. EMA: What's the Difference?, or read about the underlying mechanics in What Is Cross-App Access (XAA) and How It Works.

Consent is closely related to user authentication, but it is harder for two reasons. First, most applications assume that users interact with the system directly, though that is slowly changing with efforts like the Agent Payments Protocol.

MCP breaks that expectation. When a user connects a semi-autonomous AI agent to your MCP server, the agent acts on the user's behalf, but it is the one making requests. That brings the second challenge: the user may have limited visibility into what the agent is doing, what data it is accessing, or what actions it is taking.

Consent management restores that visibility and control. Before an MCP client can act, users should see a clear consent screen describing what is being requested: which tools are accessible, what data may be read or written, and for how long.

The spec also requires that clearly display the redirect URI hostname during authorization,, and it recommends extra warnings when a client's only redirect URIs point to localhost, because localhost callbacks are easy to impersonate.

A screenshot of a software consent interface on a white background. At the top, a red rectangular border encloses a Custom Warning Message that reads: Descope has marked this agent as "unverified!" You can configure the agents you trust using Agent Registration Flows. Below the warning, two icons—a red sunburst and a small photo of a cat—are separated by a double-sided arrow. The main heading below reads Connect MCP Server Demo with Claude, followed by the text: Claude will be able to:. This is followed by a list with three checked boxes: Schedule Meetings*, Read Contacts from HubSpot*, and Sends email*. At the bottom of the interface are two large buttons: a blue Authorize button and a white Cancel button with a blue border.
Fig: Consent screen for an unverified AI agent

Time-bound consent is particularly important here, which means short-lived, ephemeral tokens. A user who authorizes an agent to draft a proposal in Google Docs does not necessarily want to grant that agent indefinite access to email, calendar, and the rest of their Google apps. Consent should be scoped to the task and expire when the task is done. For high-risk actions such as deleting data, sending money, or changing system settings, the OWASP guide recommends pausing for explicit human confirmation. Under the July 2026 spec, a server can request that confirmation mid-call through Multi Round-Trip Requests: it returns an input-required result, and the client retries the original call with the user's answer attached. Enterprise-managed authorization changes who consents. Under EMA, administrator policy at the IdP replaces the per-user consent screen, so the scopes and audit practices below carry more of the load.

5. Enforce scope-based access control at the tool level

Least privilege is well-established in traditional identity. Applying it with MCP fundamentally means scoping access only to what a task requires. The problem is that users and even organizations themselves tend to offer agents dangerously broad scopes.

Consider an enterprise agent that helps employees across a calendar, an email system, a CRM, and an internal API. Each environment carries different risks and different permissions for different actions. An agent that can read calendar events should not automatically be able to write CRM records.

The OWASP guide flags this as a top vulnerability, noting that over-privileged tools or broad access scopes amplify the impact of any single breach. It recommends centralized policy enforcement so access decisions stay consistent across every agent, server, and tool.

Screenshot of Descope showing MCP server scopes that control what an AI agent can access on a user's behalf
Fig: Scope-based access control for MCP servers

Progressive scoping takes this further, and the current spec now describes the pattern directly. Servers should advertise required scopes in the WWW-Authenticate header, and scopes_supported (the scopes listed in Protected Resource Metadata) is meant to be the minimal set for basic functionality, with more requested through step-up authorization. 

When a token lacks a needed scope, the server should return a 403 with an insufficient_scope error and include every scope the operation needs in a single challenge, rather than forcing several authorization round trips. Clients then request the union of previously granted scopes and the new ones. 

Take a deeper dive into how progressive scoping works in Securing Your APIs With Progressive Scoping. 

6. Support all three MCP client registration methods

The current spec defines three ways for a client to obtain a client ID, with a clear order of preference. Clients supporting all three should use pre-registered information first, then Client ID Metadata Documents (CIMD) if the authorization server supports them, then Dynamic Client Registration (DCR) as a fallback.

DCR is now formally deprecated. It remains available only for backward compatibility with authorization servers that do not support CIMD, and the maintainers say it will be removed in a future version of the spec.

DCR was the early default because MCP needed a way for unknown clients to register at runtime without manual pre-registration. It solved that by letting clients register through an open endpoint, but it created standing risks. Anyone can post to a registration endpoint, client identities can be spoofed, and authorization server databases fill with stale entries. 

CIMD takes a different approach. The client_id is a stable HTTPS URL pointing to a JSON metadata document the client hosts. The authorization server fetches that document, confirms that its client_id matches the URL exactly, validates redirect URIs against it, and caches it according to HTTP cache headers. There is no registration endpoint to abuse, client identity is tied to domain ownership, and one URL can represent a single application across thousands of installs. Authorization servers should guard the fetch against server-side request forgery, and they may apply domain-based trust policies.

CIMD client IDs are also portable. The July 2026 revision requires clients to bind pre-registered and DCR credentials to the issuing authorization server and re-register if it changes, while CIMD-based client IDs need no re-registration.

Pre-registration remains the right choice for curated setups where you control both sides of the connection. If you must keep DCR for existing clients, restrict which redirect URIs it accepts, apply the hardening practices in our DCR hardening guide, and expect clients to declare an application_type.

Screenshot of the Descope Agentic Identity Hub showing CIMD and DCR both enabled simultaneously for MCP client registration.
Fig. Enabling CIMD and DCR support in the Agentic Identity Hub.

Descope lets you enable CIMD and DCR side by side and apply risk assessment flows at registration time, so you can move clients to CIMD without cutting off existing ones. 

For an in-depth discussion of which legacy scenarios are still viable for DCR, see DCR vs. CIMD. 

7. Never pass tokens through

MCP servers frequently call third-party services on behalf of users: APIs, databases, SaaS tools, and even other MCP servers or agents. In the Fudan study, 81 of the 119 OAuth-enabled servers tested also acted as OAuth clients to an upstream service. An MCP server must not pass through the token it received from the MCP client. The token used at an upstream API is a separate token issued by that upstream authorization server. Passthrough breaks audience binding, bypasses the upstream service's own policy, and creates a confused deputy risk.

The secure pattern is a fresh, narrowly scoped token for each downstream hop. Where the upstream service supports it, use OAuth 2.0 Token Exchange (RFC 8693) to obtain a token that carries the user's context while keeping the MCP server's own identity distinct. The OWASP guide recommends this delegation pattern explicitly. Apply the same standard to every hop. The Fudan team found servers that enforced PKCE on the first hop but dropped it on the upstream request.

Where the upstream service only offers API keys or personal access tokens, do not leave them in environment variables. Static secrets are long-lived, hard to rotate, and a single point of failure if the server is compromised. Use a credential vault built for agent connections, with short-lived tokens scoped to specific services, automatic rotation, and per-service access controls. OWASP recommends storing secrets in vaults, never in environment variables or logs, and never giving the LLM access to them.

The Descope Agentic Identity Hub showing AI agent connection templates for credential management and storage.
Fig: AI agent connection templates for credential management and storage

The better and more secure approach is a dedicated credential vault, purpose-built for agent connections: short-lived tokens scoped to specific services, automatic rotation, and per-service access controls. This limits the impact of any single credential being compromised and keeps the token lifecycle manageable as the number of downstream connections grows. The OWASP best practices are clear on this point: store secrets in credential vaults, never in environment variables or logs, and the LLM should never have access to them at all. 

Learn why OAuth is the preferred approach for agentic scenarios in OAuth vs. API Keys for Agentic AI. 

8. Audit everything and plan for revocation

An MCP server that cannot tell you who connected, what they did, and why they had access to do it is not production ready. 

Each MCP client should carry a dedicated identity tied to the user it is acting on behalf of, with observable attributes including registration method, IP address, client type, and the scopes that were granted. Every significant event in the client lifecycle should generate an auditable log entry: consent granted and for how long, tokens issued and when they expired, scope changes, anomalous activity, and revocations. 

The Descope console's Agentic Activity dashboard, offering visibility into agentic identity trends and misconfigurations.
Fig: Get visibility into agentic identity trends and misconfigurations

For example, Descope allows devs and organizations to audit agentic identities, monitoring their behavior through four key stages:

  • Registration: the agent is created, identifies itself, and requests permissions.

  • Consent: a user or admin grants scopes that define what the agent may do on their behalf.

  • Connectivity: the agent carries out its tasks by connecting to external systems.

  • Termination: the agent's credentials are revoked and its access retired when its task is complete.

Organizations rarely formalize termination. In the Cloud Security Alliance survey from Token Security, only 21% of respondents had formal processes for decommissioning AI agents. And even if an agent is shut down, if its credentials persist, that’s a stale risk surface waiting to be exploited. 

Revocation has a vital timing consideration as well, as per the ID-JAG draft. Under EMA, the resource authorization server should not issue refresh tokens. Instead, the client can resubmit its ID-JAG for a new access token until the ID-JAG expires, then return to the IdP for a new one. Revoking access at the IdP stops new ID-JAGs, but an unexpired ID-JAG can still be redeemed for fresh access tokens, and access tokens already issued stay valid until they expire. Keep both lifetimes short, and record each ID-JAG's jti (its unique identifier) so a replayed assertion is rejected.

OWASP frames this under non-human identity (NHI) governance, treating every automated agent and MCP server system as a first-class identity with unique credentials and tightly scoped permissions. The headline is simple here: if you cannot audit what an NHI did and revoke its access on demand, you do not actually control it.

Simplifying MCP server security

For teams that do not want to build OAuth infrastructure from scratch, the Descope Agentic Identity Hub provides the auth and access control layer for internal and external-facing MCP servers. It covers OAuth 2.1 and PKCE, CIMD and DCR with risk assessment at registration, consent management, per-agent and per-tool scopes, Connections that store and refresh downstream credentials, and audit logging.

Descope also supports Cross-App Access on both sides of the exchange. As a validator, it lets each enterprise customer register their identity provider (Okta, Ping, or another standards-compliant IdP) as a trusted issuer for their tenant. Descope validates the ID-JAG and issues a standard access token, so your MCP server needs no ID-JAG handling of its own. Per-organization scope policies let you grant different customers different levels of agent access on the same server, based on roles, tenant membership, and claims from the customer's IdP. 

As an issuer, Descope gives your own agents short-lived, scoped access to other MCP servers and APIs under policies evaluated on every request. Tenant admins can configure XAA themselves in the SSO Setup Suite, alongside SSO, SCIM, and JIT provisioning. See the Enterprise-Managed Authorization documentation for configuration details.

WisdomAI used Descope to take MCP auth from concept to production in roughly a day and a half, freeing its engineering team to focus on core capabilities. Daylight Security uses Descope as the OAuth provider for both its enterprise SSO integration and its MCP server.

If you're building or securing an MCP server, start with a free Descope account or book time with our team. To see MCP and agentic identity capabilities in action, visit descope.ai, or join AuthTown, our developer community, to connect with Descopers and other builders.

Frequently asked questions