Get started
Choose a compatible OAuth 2.1 or OpenID Connect provider
MCP specification has some specific requirements for authorization:
- OAuth 2.1 IETF DRAFT
- OAuth 2.0 Authorization Server Metadata (RFC 8414)
- OAuth 2.0 Dynamic Client Registration Protocol (RFC 7591)
While the last two are not mandatory, the first one is necessary to ensure a secure and compliant implementation.
In the new MCP draft, RFC 8414 will be mandated for authorization servers (providers). We'll update the documentation once the new draft is finalized.
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!
- Python
- Node.js
pip install mcpauth
Or any other package manager you prefer, such as pipenv or poetry.
npm install mcp-auth
Or any other package manager you prefer, such as pnpm or yarn.
Init MCP Auth
The first step is to initialize the MCP Auth instance with your provider's authorization server metadata. If your provider conforms one of:
You can use the built-in function to fetch the metadata and initialize the MCP Auth instance:
- Python
- Node.js
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
mcp_auth = MCPAuth(
server=fetch_server_config(
'<auth-server-url>',
type=AuthServerType.OIDC # or AuthServerType.OAUTH
)
)
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const mcpAuth = new MCPAuth({
server: await fetchServerConfig('<auth-server-issuer>', { type: 'oidc' }), // or 'oauth'
});
If you need to manually specify the metadata URL or endpoints, check Other ways to initialize MCP Auth.
Mount the metadata endpoint
To conform to the current MCP specification, MCP Auth mounts the OAuth 2.0 Authorization Server Metadata endpoint (/.well-known/oauth-authorization-server
) to your MCP server:
- Python
- Node.js
from starlette.applications import Starlette
app = Starlette(routes=[
mcp_auth.metadata_route(),
])
import express from 'express';
const app = express();
app.use(mcpAuth.delegatedRouter());
The URLs in the metadata are kept as-is, so the role of authorization server is fully delegated to the provider. You can test the metadata endpoint by visiting /.well-known/oauth-authorization-server
in your MCP server.
Why only the metadata endpoint?
You may see the official SDKs provide an auth router that mounts authorization endpoints like /authorize
, /token
, etc. Here is why we don't do that:
- Mounting only the metadata endpoint allows you to leverage the full capabilities of your provider without "reinventing the wheel" and injecting unnecessary complexity into your MCP server.
- There's also an ongoing effort to shift the MCP server's role to a resource server and requires OAuth 2.0 Protected Resource Metadata (RFC 9728). Which means that the MCP server will not handle any authorization logic anymore (including the metadata endpoint), but only serve as a resource server that relies on the provider for authentication and authorization.
We will update MCP Auth to support the new MCP specification when it is finalized. In the meantime, you can use the current version which is compatible with the current specification.
Use the Bearer auth middleware
Once the MCP Auth instance is initialized, you can apply the Bearer auth middleware to protect your MCP routes:
- Python
- Node.js
from starlette.applications import Starlette
from starlette.middleware import Middleware
from starlette.routing import Mount
from mcpauth import MCPAuth
from mcp.server.fastmcp import FastMCP
mcp = FastMCP()
mcp_auth = MCPAuth(
# Initialize with your auth server config
)
bearer_auth = mcp_auth.bearer_auth_middleware(
"jwt", required_scopes=["read", "write"]
)
app = Starlette(routes=[
mcp_auth.metadata_route(),
Mount(
"/",
app=mcp.sse_app(),
middleware=[Middleware(bearer_auth)],
),
])
import express from 'express';
import { MCPAuth } from 'mcp-auth';
const app = express();
const server = new McpServer(/* ... */);
const mcpAuth = new MCPAuth({
/* ... */
});
app.use(mcpAuth.bearerAuth('jwt', { requiredScopes: ['read', 'write'] }));
In the example above, we specified the jwt
token type and required the read
and write
scopes. It will automatically validate the JWT (JSON Web Token) and populate an object with the authenticated user's information.
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:
- Python
- Node.js
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()
mcp_auth = MCPAuth(
# Initialize with your auth server config
)
@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
The second argument of the tool handler will contain the authInfo
object, which includes the authenticated user's information:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const server = new McpServer(/* ... */);
server.tool('add', { a: z.number(), b: z.number() }, async ({ a, b }, { authInfo }) => {
// Now you can use the `authInfo` object to access the authenticated information
});
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.