Guides users through adding OAuth 2.1 authorization to Model Context Protocol servers using Scalekit. Use when the user mentions MCP security, OAuth, protected-resource metadata, MCP hosts like Claude Desktop or Cursor, or a need to secure tools exposed over HTTP.
Use this skill when an MCP server needs standards-based authorization for AI hosts.
OAuth-capable MCP auth requires HTTP-based transport. A stdio-only MCP server cannot complete the browser and callback flows needed for OAuth 2.1.
StreamableHTTPServerTransportSCALEKIT_ENVIRONMENT_URLSCALEKIT_CLIENT_IDSCALEKIT_CLIENT_SECRETGet these from the Scalekit dashboard after registering the MCP server.
MCP OAuth Setup:
- [ ] Install Scalekit SDK
- [ ] Register the MCP server in Scalekit
- [ ] Publish /.well-known/oauth-protected-resource
- [ ] Add token validation middleware
- [ ] Test from an MCP host
/.well-known/oauth-protected-resource with the authorization server metadata from Scalekit.401 with a WWW-Authenticate header that points to the protected-resource metadata whenever auth is missing or invalid.import { Scalekit } from '@scalekit-sdk/node';
const scalekit = new Scalekit(
process.env.SCALEKIT_ENVIRONMENT_URL!,
process.env.SCALEKIT_CLIENT_ID!,
process.env.SCALEKIT_CLIENT_SECRET!
);
const RESOURCE_ID = 'https://mcp.yourapp.com';
const METADATA_ENDPOINT =
'https://mcp.yourapp.com/.well-known/oauth-protected-resource';
export async function authMiddleware(req, res, next) {
if (req.path.includes('.well-known')) return next();
const authHeader = req.headers.authorization;
const token = authHeader?.startsWith('Bearer ')
? authHeader.slice('Bearer '.length).trim()
: null;
if (!token) {
return res
.status(401)
.set(
'WWW-Authenticate',
`Bearer realm="OAuth", resource_metadata="${METADATA_ENDPOINT}"`
)
.end();
}
await scalekit.validateToken(token, { audience: [RESOURCE_ID] });
next();
}
from scalekit import ScalekitClient
import os
client = ScalekitClient(
env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
client_id=os.getenv("SCALEKIT_CLIENT_ID"),
client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),
)
RESOURCE_ID = "https://mcp.yourapp.com"
async def verify_token(token: str):
return client.validate_access_token(token, {"audience": [RESOURCE_ID]})
Your metadata endpoint should include:
authorization_serversbearer_methods_supportedresourceresource_documentationscopes_supportedSource these values from the Scalekit dashboard for the registered MCP resource instead of inventing them manually.