Scalekit FAST MCP Integration is now live
Get started

Securing FastMCP with Scalekit: Remote OAuth Done Right

No items found.

If you’ve built anything that speaks the Model Context Protocol, you’ve almost certainly touched FastMCP.

It’s the most adopted Python framework for MCP servers — 20K+ stars, a healthy contributor base, and a release cadence that rivals many production frameworks.

It’s effectively FastAPI for MCP: typed tools, async I/O, auto-discovery, and a decorator-first developer experience.

As adoption has grown, FastMCP has become the default backbone for custom LLM integrations — powering internal copilots, AI assistants, and backend tools that expose domain-specific capabilities over the MCP spec.

With that kind of usage, the conversation quickly shifts from “how do I expose a tool?” to “how do I secure it?”

FastMCP’s Built-in Auth

FastMCP ships with three in-built auth options:

  • Bearer tokens — hard-coded secrets, easy for local dev.
  • JWT validation — lets you validate stateless tokens.
  • Full OAuth Server — a self-contained IdP, where FastMCP issues and manages tokens.

It’s a solid spread, but even the maintainers recommend caution:

“The vast majority of applications should use external identity providers instead.” — FastMCP Auth Guide

That’s not a hand-wave; it’s a boundary. FastMCP is in the tool-serving business, not the identity business.

Running an OAuth server means owning PKCE, JWK rotation, token introspection, and compliance — a full-time surface area.

For most production setups, that’s unnecessary.

What you actually need is an auth server that exists outside your MCP process — something purpose-built for issuing and validating OAuth 2.1 tokens.

That’s exactly why FastMCP introduced Remote OAuth.

Where Remote OAuth Fits

Think of FastMCP’s auth modes as a spectrum:

Mode
Description
Best For
Bearer / JWT
Simple static tokens; good for internal dev.
Local or test environments
Full OAuth Server
FastMCP hosts its own issuer and keys.
Self-contained or air-gapped installs
Remote OAuth
Delegates token issuance to an external IdP; server validates signatures and scopes.
Production environments

Remote OAuth keeps your authorization server independent — a key best practice in any distributed system.

Your MCP server becomes a resource server: it only validates JWTs and enforces scopes.

Everything else — user login, consent, client registration — is handled by your IdP.

This is the same pattern that drives every modern web API stack: microservices shouldn’t mint their own tokens.

They should validate tokens from a trusted source.

Why Scalekit Fits That Role

This is where Scalekit’s MCP Auth drops in naturally.

Scalekit is a standards-compliant OAuth 2.1 provider that already implements the same discovery and token endpoints FastMCP expects in its Remote OAuth flow.

So when you connect the two:

  • FastMCP acts as the resource server.
  • Scalekit acts as the authorization server.
  • Tokens, scopes, and validation all flow seamlessly.

That means:

  • No local user management.
  • No key rotation code.
  • No refresh token handling.
  • No re-implementing RFC 9126 on a Tuesday.

Scalekit handles OAuth 2.1 with Dynamic Client Registration (DCR), supports SSO via Google Workspace, Azure AD, and Okta, and exposes well-known JWKS and introspection endpoints.

FastMCP just points to those endpoints and validates every incoming bearer token automatically.

Setting It Up

Before wiring up any code, let’s connect the dots.

The Remote OAuth flow in FastMCP expects two things:

  1. An authorization server that exposes the standard OAuth discovery endpoints and issues JWT access tokens (that’s Scalekit), and
  2. An MCP resource server (your FastMCP instance) configured to validate those tokens and enforce scopes.

To make this concrete, we’ll use a simple Todo MCP server as our example.

It’s a minimal FastMCP app that exposes two tools — one for reading todos and one for writing them — secured by the scopes todo:read and todo:write.

The same pattern applies to any MCP toolset you build, whether it’s file sync, issue tracking, or internal dev automation.

Once you’ve registered your MCP server as a protected resource inside Scalekit, everything else becomes mechanical — a few environment variables, a provider import, and FastMCP does the validation automatically.

1. Register your MCP server in Scalekit

Tell Scalekit what your MCP server is and what scopes it enforces.

In the Scalekit dashboard:

  • Navigate to MCP Servers → Add New Server
  • Enter your local or public URL (e.g., http://localhost:3002/
  • Define scopes (todo:read and todo:write, etc).
  • Save and copy your Resourc

You’ll end up with something like:

SCALEKIT_ENVIRONMENT_URL=https://your-env.scalekit.com SCALEKIT_CLIENT_ID=skc_12345 SCALEKIT_RESOURCE_ID=res_67890 MCP_URL=http://localhost:3002/mcp

2. Add Scalekit Auth to FastMCP

Point your FastMCP app to Scalekit so it can validate tokens automatically.

from fastmcp import FastMCP from fastmcp.server.auth.providers.scalekit import ScalekitProvider import os 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"), ) mcp = FastMCP(name="Todo Server", auth=auth) @mcp.tool def status() -> dict: return {"authenticated": True, "provider": "Scalekit"}

Then start your server:

uv run python server.py

FastMCP automatically validates tokens against Scalekit’s JWKS URL — no manual verification logic required.


3. Or configure via environment only

Prefer 12-factor style? You can declare the provider entirely through environment variables.

FASTMCP_SERVER_AUTH=fastmcp.server.auth.providers.scalekit.ScalekitProvider FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_ENVIRONMENT_URL=https://your-env.scalekit.com FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_CLIENT_ID=skc_123 FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_RESOURCE_ID=res_456 FASTMCP_SERVER_AUTH_SCALEKITPROVIDER_MCP_URL=http://localhost:3002/mcp

Then your FastMCP entrypoint can be minimal:

from fastmcp import FastMCP mcp = FastMCP(name="Scalekit Protected Server") @mcp.tool def hello(): return {"message": "Authenticated via Scalekit!"}

That’s it — all validation, token introspection, and scope enforcement happen under the hood.

Example: Scoped Todo Tools

You can use the same pattern to protect individual MCP tools based on scopes.

from fastmcp.server.dependencies import get_access_token import uuid _TODOS = {} def require_scope(scope: str): token = get_access_token() if scope not in token.scopes: return {"error": f"Missing `{scope}` scope"} @mcp.tool def create_todo(title: str): if err := require_scope("todo:write"): return err tid = str(uuid.uuid4()) _TODOS[tid] = {"id": tid, "title": title, "done": False} return _TODOS[tid] @mcp.tool def list_todos(): if err := require_scope("todo:read"): return err return list(_TODOS.values())

Each incoming request carries a bearer token that includes the granted scopes.

FastMCP validates the token via Scalekit; your tools simply enforce scope logic.

Debugging and Inspection

Need to see what’s inside a token? Add a quick tool to inspect claims.

from fastmcp.server.context import request_ctx import jwt @mcp.tool def inspect_token(): ctx = request_ctx.get() auth = ctx.request.headers.get("authorization", "") token = auth.split(" ")[1] claims = jwt.decode(token, options={"verify_signature": False}) return claims

And for local debugging:

import logging logging.basicConfig(level=logging.DEBUG)

You’ll see validation events, discovery calls, and auth flow logs.

Best Practices

  • Keep your auth server separate. Your MCP server should only validate.
  • Use HTTPS in production; Remote OAuth won’t register otherwise.
  • Scope narrowly. Define granular permissions like todo:read, not admin*.
  • Rotate credentials regularly. Use Scalekit’s dashboard or your secret manager.
  • Log auth errors, but never tokens or secrets.

Why This Pattern Works

Remote OAuth gives you:

  • A clean separation between auth and app logic
  • Centralized security and SSO integration
  • Standards alignment with OAuth 2.1 and DCR
  • Zero auth boilerplate inside FastMCP

Scalekit just happens to make it frictionless — a single provider import, a few environment variables, and your FastMCP server behaves like any modern, secure resource API.

Further Reading

Ready to secure your MCP Servers?
On this page
Share this article
Ready to secure your MCP Servers?

Acquire enterprise customers with zero upfront cost

Every feature unlocked. No hidden fees.
Start Free
$0
/ month
1 million Monthly Active Users
100 Monthly Active Organizations
1 SSO and SCIM connection each
20K Tool Calls
10K Connected Accounts
Unlimited Dev & Prod environments