mcp-auth-fastmcp-scalekit
Add OAuth auth to a FastMCP server (Scalekit)
What this skill builds
- A FastMCP server with
stateless_http=Truethat boots an HTTP transport on a configured port. - OAuth protection via
ScalekitProvider— handles token validation, .well-known discovery, and WWW-Authenticate on 401 automatically. - Per-tool scope enforcement using
get_access_token()fromfastmcp.server.dependencies. - Scopes are pre-configured in the Scalekit dashboard; tools check them at runtime.
Key difference from Express skill
- No manual middleware, no manual .well-known route.
- Auth is injected at the
FastMCP(auth=...)constructor. ScalekitProviderusesresource_id(starts withres_) andmcp_url(base URL + trailing slash).- FastMCP appends
/mcpto the base URL automatically — always register the BASE URL with trailing slash in Scalekit, not the /mcp path.
Inputs to collect (ask if missing)
- SCALEKIT_ENVIRONMENT_URL (your Scalekit env URL, e.g. https://your-env.scalekit.com)
- SCALEKIT_CLIENT_ID
- SCALEKIT_RESOURCE_ID (starts with res_, from Dashboard > MCP Servers)
- MCP_URL: base URL with trailing slash (e.g. http://localhost:3002/)
- PORT (default 3002)
- Scopes to configure (e.g. todo:read, todo:write); these must also be created in the Scalekit dashboard
Mode detection
Ask: "Are we scaffolding a new FastMCP server, or adding auth to an existing FastMCP server?"
- Mode A: New server → use assets/server.py or assets/server-minimal.py as the base
- Mode B: Existing server → apply the patch plan below
Mode A — New server scaffold
Steps
-
Create a directory and virtual environment:
mkdir -p <project-name> cd <project-name> python3 -m venv venv source venv/bin/activate -
Install dependencies using assets/requirements.txt:
pip install -r requirements.txt -
Create .env using assets/env.example (fill real values from Scalekit dashboard).
-
Copy assets/server-minimal.py to server.py and add your tools.
-
Run:
python server.py -
Test with MCP Inspector (point to http://localhost:3002/mcp — note: /mcp, not /):
npx @modelcontextprotocol/inspector@latestLeave Authentication fields empty; DCR handles client registration automatically.
Mode B — Retrofit an existing FastMCP server
Identify insertion points
Ask for the existing server file. Look for:
- How
FastMCP(...)is instantiated - Whether
mcp.run(...)is already present
Patch plan (minimal diffs)
1. Add env vars
Add to .env:
SCALEKIT_ENVIRONMENT_URL=...
SCALEKIT_CLIENT_ID=...
SCALEKIT_RESOURCE_ID=...
MCP_URL=http://localhost:3002/
PORT=3002
2. Add imports
from fastmcp.server.auth.providers.scalekit import ScalekitProvider
from fastmcp.server.dependencies import AccessToken, get_access_token
3. Patch FastMCP constructor
Before (typical):
mcp = FastMCP("My Server")
After:
mcp = FastMCP(
"My Server",
stateless_http=True,
auth=ScalekitProvider(
environment_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),
client_id=os.getenv("SCALEKIT_CLIENT_ID"),
resource_id=os.getenv("SCALEKIT_RESOURCE_ID"),
mcp_url=os.getenv("MCP_URL"),
),
)
4. Add scope helper
Add once near the top of the file:
def _require_scope(scope: str):
token: AccessToken = get_access_token()
if scope not in token.scopes:
return f"Insufficient permissions: `{scope}` scope required."
return None
5. Add scope checks to each tool
At the top of each @mcp.tool function body, add:
error = _require_scope("your:scope")
if error:
return {"error": error}
See assets/tool-template.py for the full pattern.
6. Patch run call
if __name__ == "__main__":
mcp.run(transport="http", port=int(os.getenv("PORT", "3002")))
Scope design guide
- Register scopes in Scalekit dashboard BEFORE running the server.
- Group by read vs write per resource: e.g. todo:read, todo:write.
- Tools that only read → require read scope.
- Tools that mutate (create/update/delete) → require write scope.
- A token with no matching scope will get {"error": "Insufficient permissions: required."}.
Verification checklist
- Server boots and logs HTTP transport on http://localhost:PORT/
- MCP Inspector connects to http://localhost:PORT/mcp
- Tool with correct scope → success
- Tool with wrong scope → {"error": "Insufficient permissions..."}
- No token → 401 + WWW-Authenticate (handled by ScalekitProvider automatically)
See references/TROUBLESHOOTING.md for common issues.
More from scalekit-inc/skills
integrating-agent-auth
Integrates Scalekit Agent Auth into a project to handle OAuth flows, token storage, and automatic refresh for third-party services (Gmail, Slack, Notion, Calendar). Use when a user needs to connect to an external service, authorize OAuth access, fetch access or refresh tokens, or execute API calls on behalf of a user.
4adding-mcp-oauth
Guides users through adding OAuth 2.1 authorization to Model Context Protocol (MCP) servers using Scalekit. Use when setting up MCP servers, implementing authentication for AI hosts like Claude Desktop, Cursor, or VS Code, or when users mention MCP security, OAuth, or Scalekit integration.
3modular-sso
Implements complete SSO and authentication flows using Scalekit. Handles modular SSO, IdP-initiated login, user session management, and enterprise customer onboarding. Use when adding authentication, SSO, SAML, OIDC, or user login to applications.
3implementing-fsa-logout
Implements a complete logout flow for Scalekit FSA integrations by clearing application session cookies and redirecting the browser to Scalekit’s /oidc/logout endpoint to invalidate the Scalekit session. Use when adding or fixing logout in Node.js, Python, Go, or Java web apps that use Scalekit OIDC.
2implementing-scim-provisioning
Implements SCIM user provisioning using Scalekit's Directory API and webhooks. Use when the user asks to add SCIM, directory sync, user provisioning, deprovisioning, or lifecycle management to their existing application.
2production-readiness-scim
Walks through a structured production readiness checklist for Scalekit SCIM provisioning implementations. Use when the user says they are going live, launching to production, doing a pre-launch review, or wants to verify their SCIM directory sync implementation is production-ready.
2