Learn how to set up MCP authentication using OAuth 2.1. This step-by-step guide walks you through the process to securely authorize remote MCP servers. We'll use the ScaleKit service to simplify the implementation, ensuring that your server complies with the OAuth 2.1 standard effectively.
Prerequisites
Before proceeding, ensure you have the following:
prerequisites
- An MCP server configured using FastAPI.
- Installed Python libraries, including the
scalekitpackage. - Access to a ScaleKit account for managing authentication workflows.
- Basic knowledge of OAuth 2.1 and its principles.
- Pre-configured environment variables:
SCALEKIT_CLIENT_IDSCALEKIT_CLIENT_SECRETSCALEKIT_ENVIRONMENT_URLRESOURCE_METADATA_URL(for your MCP server).
Setting Up ScaleKit Authentication
Configure your ScaleKit account to manage MCP authentication.
steps
- Create an account or sign in at ScaleKit.
- Activate full-stack authentication in the ScaleKit environment.
- Add necessary scopes, such as:
- Name:
search:read - Description: "Use Tavili to search the web."
- Name:
- Register your MCP server using its identifier URL.
- Make sure the URL includes a trailing slash, e.g.,
http://localhost:10000/mcp/.
- Make sure the URL includes a trailing slash, e.g.,
- Generate the client ID, client secret, and other credentials from ScaleKit and store them securely.
Creating the Well-Known Endpoint
Add a discovery endpoint to your MCP server for authentication workflows.
steps
- Add the following
@app.getroute to your FastAPI application for the well-known endpoint:pythonfrom fastapi import FastAPI import os import json app = FastAPI() @app.get("/.well-known/oauth-protected-resource/mcp") async def well_known_endpoint(): metadata = os.getenv("METADATA_JSON", '{"issuer":"https://example.com","authorization_endpoint":"/oauth/authorize","token_endpoint":"/oauth/token"}') return json.loads(metadata) - Ensure the endpoint is accessible publicly (without authentication).
- Test the endpoint manually using cURL:bash
curl http://localhost:10000/.well-known/oauth-protected-resource/mcp # Expected output (example): # { # "issuer": "https://example.com", # "authorization_endpoint": "/oauth/authorize", # "token_endpoint": "/oauth/token" # }
Adding Authentication Middleware
Add middleware to your MCP server to validate requests and enforce authorization.
steps
- Install the ScaleKit Python SDK:bash
pip install scalekit - Implement authentication middleware:python
from starlette.middleware.base import BaseHTTPMiddleware from starlette.exceptions import HTTPException from scalekit.client import ScaleKit from scalekit.models import TokenValidationOptions import os class AuthMiddleware(BaseHTTPMiddleware): def __init__(self, app): super().__init__(app) self.scalekit = ScaleKit( environment_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"), client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET") ) async def dispatch(self, request, call_next): # Skip validation for well-known endpoints if request.url.path.startswith("/.well-known"): return await call_next(request) # Check for Bearer token auth_header = request.headers.get("Authorization") if not auth_header or not auth_header.startswith("Bearer "): raise HTTPException(status_code=401, headers={ "WWW-Authenticate": f'Bearer realm="OAuth", resource="{os.getenv("RESOURCE_METADATA_URL")}"', }) token = auth_header.split(" ")[1] options = TokenValidationOptions( issuer=os.getenv("SCALEKIT_ENVIRONMENT_URL"), audience=os.getenv("RESOURCE_METADATA_NAME") ) try: self.scalekit.validate_token(token, options) except Exception as e: raise HTTPException(status_code=401, detail=str(e)) return await call_next(request) app.add_middleware(AuthMiddleware) - Restart your MCP server to apply changes.bash
uvicorn app:app --reload --host 0.0.0.0 --port 10000 - Test unauthorized requests to validate the 401 response:bash
curl -i http://localhost:10000/mcp # HTTP/1.1 401 Unauthorized # WWW-Authenticate: Bearer realm="OAuth", resource="http://localhost:10000/.well-known/oauth-protected-resource/mcp"
Testing the Authentication Workflow
Verify the full authentication and authorization flow to ensure proper functionality.
steps
- Restart your MCP server with updated configurations:bash
uvicorn app:app --reload - Perform an unauthorized request:bash
curl -i http://localhost:10000/mcp # Confirm a 401 error with proper headers (e.g., WWW-Authenticate). - Authenticate with ScaleKit and obtain a valid token.
- Retry the request with the token:bash
curl -i -H "Authorization: Bearer <valid-token>" http://localhost:10000/mcp/tools # Expected output: # List of tools with scopes and capabilities - Use an MCP client to interact with server tools after successful token authentication.
FAQ
What is MCP OAuth 2.1?
MCP OAuth 2.1 is the authorization standard required for remotely accessing and securing Modern Compute Protocol (MCP) servers. It uses the OAuth 2.1 framework to ensure secure client authentication and token-based authorization.
Do I need to write my own authorization server?
No, you can avoid maintaining a custom authorization server by using third-party services like ScaleKit, which handle the complex aspects of OAuth 2.1 and streamline the authentication setup.
Can I use this guide for non-FastAPI MCP servers?
Yes, the steps demonstrated here are generalizable to different server frameworks. However, the implementation details of middleware might differ depending on the framework used.
Official reference: Model Context Protocol documentation.