---
title: "MCP authentication"
description:
  "How to authenticate MCP servers: method guides with working agent code, what each identity provider supports, and fixes for the errors clients report."
canonicalUrl: "https://zuplo.com/learn/mcp/authentication"
sourceUrl: "https://zuplo.com/learn/mcp/authentication"
pageType: "other"
generatedAt: "2026-10-23"
---

# MCP authentication

> Every remote MCP server needs a way for callers to prove who they are, and the specification leaves most of that choice to you.

Current as of MCP 2026-07-28.

## Choosing a method

The specification makes authorization OPTIONAL, and says HTTP transports SHOULD rather than MUST use its OAuth flow. So decide by what your callers can present. A static key works with every agent SDK. Between workloads you own, platform identity removes the stored secret. Only the specification's OAuth flow gets a server into the ChatGPT and Claude connector directories.

## Authentication methods

| Method | Best for | Platform | Specification | Works with | Effort |
| --- | --- | --- | --- | --- | --- |
| [Anthropic-hosted agents](/learn/mcp/authentication/anthropic-managed-agents) | Reaching your MCP server from an agent that runs on Anthropic's infrastructure | Claude Managed Agents | Mixed — claude.ai and Claude Code run the specification's OAuth flow; a vault token or a static header sits outside it, not against it | Four surfaces, four credential fields; only Claude Code, which runs locally, sends a header name of your choosing | An afternoon per surface |
| [API key](/learn/mcp/authentication/api-key) | Service-to-service calls where you control both the agent and the MCP server | Any platform | Outside the specification's OAuth flow, which the specification makes OPTIONAL | Every agent SDK on this page; hosted connectors are more limited | An afternoon |
| [AWS IAM (SigV4)](/learn/mcp/authentication/aws-iam-sigv4) | Agents you write that run in AWS, calling a server behind Lambda, API Gateway, or AgentCore | AWS | Platform request signing rather than MCP authorization; the specification doesn't cover it | Your own agents. No MCP client signs SigV4; AWS ships a local proxy that does | An afternoon with AWS's transport, a day with the IAM policies |
| [Client credentials (M2M)](/learn/mcp/authentication/client-credentials) | Cron jobs, CI steps, and background workers, where no user is present to consent | Any platform | An official MCP extension, still Draft — shipped in the TypeScript and Python SDKs | Your own agents — the extension support matrix lists no client that implements it | An afternoon, if your identity provider already issues client-credentials tokens |
| [Google Cloud IAM](/learn/mcp/authentication/google-iam) | Agents that hold Google credentials, calling a server that can verify a Google token | Google Cloud | Platform identity rather than MCP authorization; the specification doesn't cover it | Your own workloads only; no MCP client can mint these tokens | A day, mostly IAM bindings |
| [Microsoft Entra ID](/learn/mcp/authentication/azure-managed-identity) | Agents and MCP servers that both run in Azure, in one Entra tenant | Azure | Outside the specification's OAuth flow, which the specification makes OPTIONAL | Your own workloads, plus Microsoft Foundry Agent Service; no chat or desktop client can mint one | A day, mostly the app registration and role assignments |
| [mTLS](/learn/mcp/authentication/mtls) | Workload-to-workload calls where both ends are yours and a CA already issues certificates | Any platform | Transport-layer authentication, outside the specification's OAuth profile — which the specification makes OPTIONAL | Your own agents only; no chat or desktop client config exposes a certificate field | An afternoon in code, longer if the PKI does not exist yet |
| [OAuth 2.1](/learn/mcp/authentication/oauth-2-1) | Servers that must be reachable by MCP clients you don't control, or listed in a connector directory | Any platform | The specification's own flow — though the specification still makes authorization OPTIONAL | Claude, ChatGPT, Cursor, and VS Code run it themselves; among agent SDKs, only those shipping an OAuth provider | Days — most of it is the authorization server, not MCP |

Guide titles:

- [How an Anthropic-managed agent authenticates to your MCP server](/learn/mcp/authentication/anthropic-managed-agents)
- [API key authentication for MCP servers](/learn/mcp/authentication/api-key)
- [Authenticate an MCP server with AWS IAM (SigV4)](/learn/mcp/authentication/aws-iam-sigv4)
- [Machine-to-machine (M2M) MCP authentication with the client credentials grant](/learn/mcp/authentication/client-credentials)
- [Authenticate an MCP server with Google Cloud IAM](/learn/mcp/authentication/google-iam)
- [Authenticate an MCP server with Microsoft Entra ID (Azure AD) managed identity](/learn/mcp/authentication/azure-managed-identity)
- [mTLS (mutual TLS) authentication for MCP servers](/learn/mcp/authentication/mtls)
- [OAuth 2.1 authentication for MCP servers](/learn/mcp/authentication/oauth-2-1)

## What your identity provider supports

The specification's OAuth flow needs dynamic client registration (RFC 7591) and resource indicators (RFC 8707). Support varies, so check yours before you commit to that flow.

The Registration column records what each provider does, not what the specification recommends. As of the 2026-07-28 revision, dynamic client registration is deprecated in favour of client ID metadata documents, so read a Yes as "this provider will register a client for you" rather than as advice to use it. See [Specification: client registration](https://modelcontextprotocol.io/specification/2026-07-28/basic/authorization/client-registration).

| Provider | Registration | Resource indicators | Notes |
| --- | --- | --- | --- |
| Microsoft Entra ID ([source](https://learn.microsoft.com/en-us/entra/identity-platform/v2-protocols)) | No | No | No dynamic client registration, and no RFC 8414 metadata endpoint. Ask for an audience with `scope={resource}/.default` rather than the `resource` parameter. |
| Amazon Cognito ([source](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-app-idp-settings.html)) | No | No | Cognito's own docs state it does not support dynamic client registration. Pre-register the client. |
| Keycloak ([source](https://www.keycloak.org/securing-apps/mcp-authz-server)) | Yes | No | Keycloak documents that it "cannot recognize the `resource` parameter". Use the `scope` parameter plus an audience mapper on a client scope. |
| Auth0 ([source](https://auth0.com/ai/docs/mcp/guides/resource-param-compatibility-profile)) | Yes | Partial | Dynamic registration must be enabled per tenant. Auth0 accepts `resource` on the standard authorization flow, pushed and JWT-secured authorization requests, backchannel authentication, and the refresh grant — but when a request carries both `resource` and `audience`, the `audience` value is the one used. |
| Ory Hydra ([source](https://github.com/ory/hydra)) | Yes | No | Dynamic registration is off by default. Its registration response includes empty `client_uri` and `logo_uri` fields, which some clients reject during validation. |
| Zitadel ([source](https://github.com/zitadel/zitadel/issues/9810)) | No | No | Dynamic client registration is not implemented; the tracking issue has been open since April 2025. |
| authentik ([source](https://github.com/goauthentik/authentik/issues/8751)) | No | No | Not shipped. An implementation for the enterprise OAuth2 provider is in review. |

Provider support last verified July 24, 2026. For what each MCP client supports on the other side of the same flow, see the [MCP compatibility matrix](/learn/mcp/compatibility).

## When a connection fails

- [[mcp-sdk] excluding tool '<name>' from tools/list: invalid x-mcp-header declaration](/learn/mcp/errors/excluded-tool-invalid-x-mcp-header) — One parameter in that tool's `inputSchema` carries an `x-mcp-header` annotation that breaks a 2026-07-28 constraint, so a conforming Streamable HTTP client drops the whole tool from `tools/list` and logs a warning instead of raising an error.
- [Authorization with the MCP server failed](/learn/mcp/errors/oauth-completes-but-no-token-sent) — The client says it is connected, but no usable credential reaches your server: either it doesn't attach the token, or the token carries an audience your server is right to reject.
- [Couldn't reach the MCP server](/learn/mcp/errors/mcp-server-works-in-claude-code-but-not-claude-ai) — One toast covers four different failures: a claude.ai connector reaches your server from Anthropic's infrastructure over the public internet rather than from your machine, so the request dies at whichever hop exists only on that path — DNS, your edge, a redirect, or OAuth discovery.
- [Dynamic Client Registration not supported](/learn/mcp/errors/dynamic-client-registration-not-supported) — The MCP client reached your authorization server's metadata and found no way to obtain a client ID — no registration endpoint, no Client ID Metadata Document support, and none configured in the client — so it stopped before the OAuth flow began.
- [Failed to fetch authorization server metadata from all attempted URLs](/learn/mcp/errors/failed-to-fetch-authorization-server-metadata) — The client knows which authorization server to use, but none of the well-known URLs it probes returned a metadata document, so it never learns where `/authorize` and `/token` are and the flow stops short of a login.
- [MCP headers config ignored when server has OAuth discovery](/learn/mcp/errors/configured-headers-ignored-when-oauth-discovery-present) — Your credential never reaches the wire: the client found OAuth discovery metadata on the server first and started the OAuth flow instead of sending the header you configured.
- [mcp_authentication_failed_error](/learn/mcp/errors/mcp-authentication-failed-error-managed-agents) — A managed agent's connection to your MCP server failed on authentication: the server rejected the credential from the attached vault, required authentication when no matching credential was configured, or an `mcp_oauth` token refresh failed.
- [ModuleNotFoundError: No module named 'mcp.server.fastmcp'](/learn/mcp/errors/no-module-named-mcp-server-fastmcp) — Your server code imports `mcp.server.fastmcp`, but the installed `mcp` package is 2.x, where that module no longer exists — so the process dies at import, before it speaks any MCP.
- [resource indicator is missing, or unknown](/learn/mcp/errors/resource-indicator-missing-or-unknown) — Your authorization server refused to bind a token to your MCP server — the `resource` value it was handed names something it does not recognize, or the client sent none and this server requires one — so no token is minted and nothing ever reaches your MCP server.
- [Resource server does not implement OAuth 2.0 Protected Resource Metadata.](/learn/mcp/errors/401-without-www-authenticate) — Your server answers `401` correctly, but the response carries no pointer to protected resource metadata, so the client cannot discover the authorization server and the OAuth flow never starts.
- [The request signature we calculated does not match the signature you provided](/learn/mcp/errors/aws-signaturedoesnotmatch) — AWS recomputed the signature over the request it actually received, got a different value from the one you sent, and answered `403` before your MCP server ran — so nothing about your tools, your handler, or your IAM policy is implicated yet.
- [Token audience validation failed](/learn/mcp/errors/token-audience-validation-failed) — The token is real — right issuer, good signature, not expired — but the `aud` claim names something other than this MCP server, so the server is required to reject it.
- [Your MCP server returns a login page or 403 instead of 401](/learn/mcp/errors/302-redirect-instead-of-401) — A gate in front of your MCP server is enforcing login built for humans in browsers, so an unauthenticated client gets a login page, a redirect, or a bare `403` instead of the `401` that would tell it where to authenticate.

[Search the error reference](/learn/mcp/errors)

## Next steps

- [Back to Learn MCP](/learn/mcp)
- [Start for Free](https://portal.zuplo.com/signup) — put your MCP servers behind a gateway that handles the OAuth details providers leave out, filters tools per role, and logs every call.
- [Read the Docs](https://zuplo.com/docs/mcp-gateway/code-config/overview)
