Skip to main content

Get started

MCP authorization specification support
Python SDK available

MCP Auth is also available for Python! Check out the Python SDK repository for installation and usage.

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

pnpm add mcp-auth

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:

import { MCPAuth, fetchServerConfig } from 'mcp-auth';

// 1. Define your resource identifier and fetch the config for its trusted authorization server.
const resourceIdentifier = 'https://api.example.com/notes';
const authServerConfig = await fetchServerConfig('https://auth.logto.io/oidc', { type: 'oidc' });

// 2. Initialize MCPAuth in resource server mode.
// `protectedResources` can be a single object or an array for multiple resources.
const mcpAuth = new MCPAuth({
  protectedResources: {
    metadata: {
      resource: resourceIdentifier,
      authorizationServers: [authServerConfig],
      scopesSupported: ['read:notes', 'write:notes'],
    },
  },
});

If you're using edge runtimes like Cloudflare Workers where top-level async fetch is not allowed, use on demand discovery instead:

const authServerConfig = { issuer: 'https://auth.logto.io/oidc', type: 'oidc' };

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:

import express from 'express';

const app = express();

// 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.use(mcpAuth.protectedResourceMetadataRouter());

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.

Always Validate Scopes

In OAuth 2.0, scopes are the primary mechanism for permission control. A valid token with the correct audience does NOT guarantee the user has permission to perform an action — authorization servers may issue tokens with an empty or limited scope.

Always use requiredScopes to enforce that the token contains the necessary permissions for each operation. Never assume a valid token implies full access.

import express from 'express';

const app = express();

// Mount the router to serve the Protected Resource Metadata.
app.use(mcpAuth.protectedResourceMetadataRouter());

// Protect an API endpoint using the resource-specific policy.
app.get(
  '/notes',
  mcpAuth.bearerAuth('jwt', {
    resource: resourceIdentifier,
    audience: resourceIdentifier, // Enable audience validation for security
    requiredScopes: ['read:notes'],
  }),
  (req, res) => {
    // If the token is valid, `req.auth` is populated with its claims.
    console.log('Auth info:', req.auth);
    res.json({ notes: [] });
  }
);

app.listen(3000);

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:

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(/* ... */);

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

server.registerTool(
  'add',
  {
    description: 'Add two numbers',
    inputSchema: { 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.