Skip to content

Instantly share code, notes, and snippets.

@rajrao
Last active February 13, 2026 15:48
Show Gist options
  • Select an option

  • Save rajrao/e243a28f1dc64fb7e1e77d8eac616dc5 to your computer and use it in GitHub Desktop.

Select an option

Save rajrao/e243a28f1dc64fb7e1e77d8eac616dc5 to your computer and use it in GitHub Desktop.
Key based auth for FastMCP 3.0
import logging
import os
from fastmcp.server.middleware import Middleware, MiddlewareContext
from fastmcp.server.dependencies import get_http_headers
from starlette.responses import JSONResponse
_logger = logging.getLogger(__name__)
class AuthKeyMiddleware(Middleware):
"""
Provides a simple key based auth. Key is defined in environment as "MCP_API_KEY"
Send it as either Bearer KEY or as header X-API-KEY
"""
async def on_message(self, context: MiddlewareContext, call_next):
# Skip authentication for OPTIONS requests (CORS preflight)
if context.method == "OPTIONS":
return await call_next(request)
# Get API key from environment
expected_api_key = os.getenv("MCP_API_KEY")
# If no API key is configured, allow all requests (optional: you can make this stricter)
if not expected_api_key:
_logger.warning("MCP_API_KEY not configured - authentication disabled")
return await call_next(context)
headers = get_http_headers()
# Check for API key in headers (fastmcp makes them lower case)
api_key = headers.get("x-api-key") or headers.get("authorization")
# Handle Bearer token format
if api_key and api_key.startswith("Bearer "):
api_key = api_key[7:]
# Validate API key
if api_key != expected_api_key:
return JSONResponse(
status_code=401,
content={"error": "Invalid or missing API key"}
)
return await call_next(context)
###usage:
from fastmcp import FastMCP
mcp = FastMCP("My MCP Server",
instructions="""
Shows how to implement key based authentication
""")
http_app = mcp.http_app(path="/mcp", transport="http")
mcp.add_middleware(AuthKeyMiddleware())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment