Skip to main content
Version: 0.2.0-beta.1

Get started

MCP authorization specification support

Choose a compatible OAuth 2.1 or OpenID Connect provider

MCP specification has specific requirements for authorization. The authorization mechanism is based on established specifications, implementing a selected subset of their features to ensure security and interoperability while maintaining simplicity:

These specifications work together to provide a secure and standardized authorization framework for MCP implementations.

You can check the MCP-compatible provider list to see if your provider is supported.

Install MCP Auth SDK

MCP Auth is available for both Python and TypeScript. Let us know if you need support for another language or framework!

pip install mcpauth

Or any other package manager you prefer, such as pipenv or poetry.

Init MCP Auth

The first step is to define your resource identifier and configure the authorization server that will be trusted for authentication. MCP Auth now operates in resource server mode, conforming to the updated MCP specification that requires OAuth 2.0 Protected Resource Metadata (RFC 9728).

If your provider conforms to:

You can use the built-in function to fetch the metadata and initialize the MCP Auth instance:

from mcpauth import MCPAuth
from mcpauth.config import AuthServerType, ResourceServerConfig, ResourceServerMetadata
from mcpauth.utils import fetch_server_config

# 1. Define your resource identifier and fetch the config for its trusted authorization server.
resource_id = "https://api.example.com/notes"
auth_server_config = fetch_server_config("https://auth.logto.io/oidc", AuthServerType.OIDC)

# 2. Initialize MCPAuth in resource server mode.
# `protected_resources` can be a single object or a list for multiple resources.
mcp_auth = MCPAuth(
    protected_resources=ResourceServerConfig(
        metadata=ResourceServerMetadata(
            resource=resource_id,
            authorization_servers=[auth_server_config],
            scopes_supported=[
                "read:notes",
                "write:notes",
            ],
        )
    )
)

For other ways to configure authorization server metadata including custom metadata URLs, data transpilation, or manual metadata specification, check Other ways to configure MCP Auth.

Mount the protected resource metadata endpoint

To conform to the updated MCP specification, MCP Auth mounts the OAuth 2.0 Protected Resource Metadata endpoint (RFC 9728) to your MCP server. This endpoint allows clients to discover:

  • Which authorization servers can issue valid tokens for your protected resources
  • What scopes are supported for each resource
  • Other metadata required for proper token validation

The endpoint path is automatically determined by the path component of your resource identifier:

  • No path: https://api.example.com/.well-known/oauth-protected-resource
  • With path: https://api.example.com/notes/.well-known/oauth-protected-resource/notes

The MCP server now serves as a resource server that validates tokens and provides metadata about its protected resources, while relying entirely on external authorization servers for authentication and authorization.

You can use the SDK provided method to mount this endpoint:

from starlette.applications import Starlette

# Mount the router to serve the Protected Resource Metadata.
# For resource "https://api.example.com" → endpoint: /.well-known/oauth-protected-resource
# For resource "https://api.example.com/notes" → endpoint: /.well-known/oauth-protected-resource/notes
app = Starlette(routes=[
    *mcp_auth.resource_metadata_router().routes,
])

Use the Bearer auth middleware

Once the MCP Auth instance is initialized, you can apply the Bearer auth middleware to protect your MCP routes. The middleware now requires specifying which resource the endpoint belongs to, enabling proper token validation:

Audience Validation

The audience parameter is required by the OAuth 2.0 specification for secure token validation. However, it is currently optional to maintain compatibility with authorization servers that do not yet support resource identifiers. For security reasons, please always include the audience parameter when possible. Future versions will enforce audience validation as mandatory to fully comply with the specification.

from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.routing import Mount

# Create the middleware to protect your MCP server with the resource-specific policy.
bearer_auth = Middleware(mcp_auth.bearer_auth_middleware('jwt', 
    resource=resource_id,
    audience=resource_id,  # Enable audience validation for security
    required_scopes=['read:notes']
))

# Mount the router to serve the Protected Resource Metadata and protect the MCP server.
app = Starlette(
    routes=[
        *mcp_auth.resource_metadata_router().routes,
        # Protect the MCP server with the Bearer auth middleware.
        Mount("/", app=mcp.sse_app(), middleware=[bearer_auth]),
    ],
)

In the examples above, we specify the jwt token type and the resource identifier. The middleware will automatically validate the JWT token against the trusted authorization servers configured for that specific resource and populate the authenticated user's information.

info

Didn't hear about JWT (JSON Web Token) before? Don't worry, you can keep reading the documentation and we'll explain it when needed. You can also check Auth Wiki for a quick introduction.

For more information on the Bearer auth configuration, check the Configure Bearer auth.

Retrieve the auth info in your MCP implementation

Once the Bearer auth middleware is applied, you can access the authenticated user's (or identity's) information in your MCP implementation:

MCP Auth will store the authenticated user's information in a context variable after successful authentication once the Bearer auth middleware is applied. You can access it in your MCP tool handlers like this:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP()

# Initialize with MCP Auth as shown in previous examples
# ...

@mcp.tool()
def add(a: int, b: int):
    """
    A tool that adds two numbers.
    The authenticated user's information will be available in the context.
    """
    auth_info = mcp_auth.auth_info # Access the auth info in the current context
    if auth_info:
        print(f"Authenticated user: {auth_info.claims}")
    return a + b

Next steps

Continue reading to learn an end-to-end example of how to integrate MCP Auth with your MCP server, and how to handle the auth flow in MCP clients.