FastMCP integration quickstart 🚀
This guide shows you how Scalekit’s provider secures any FastMCP server. We’ll register a sample server as a protected resource, configure a local FastMCP runtime, and use Scalekit as the Authentication server. We will able confirm that every request from MCP Client carries the right scopes and validate them on the MCP Server.
Use this quickstart to experience a working reference for authorizing any FastMCP project with Scalekit. We walk through a simple Todo MCP application. The Application will allow adding tasks and completing them. You can use this to understand the authenticatin pattern for MCP and apply it in your own tools.
Prerequisites
- A Scalekit account with permission to manage MCP servers
- Python 3.11+ installed locally
- Familiarity with OAuth scopes (
todo:read,todo:write) and basic terminal commands
Review the FastMCP authorization flow
-
Register your MCP server in Scalekit
Section titled “Register your MCP server in Scalekit”Create a protected resource so Scalekit can issue scoped tokens that FastMCP will validate on every request.
- Go to Dashboard > MCP Servers > Add MCP Server.
- Enter a descriptive name (for example,
FastMCP Todo Server). - Set Server URL to
http://localhost:3002/(keep the trailing slash). - Create or link the scopes below, then click Save.

Scope Description Required todo:readGrants read access to todo tasks Yes todo:writeAllows creating, updating, or deleting tasks Yes -
Create your FastMCP todo server
Section titled “Create your FastMCP todo server”Prepare a fresh directory and virtual environment so you can keep the FastMCP dependencies isolated.
Terminal mkdir -p fastmcp-todocd fastmcp-todopython3 -m venv venvsource venv/bin/activate -
Add dependencies and configuration templates
Section titled “Add dependencies and configuration templates”Create the support files that FastMCP and Scalekit expect, then install the required libraries.
Terminal cat <<'EOF' > requirements.txtfastmcp>=2.13.0.2python-dotenv>=1.0.0EOFpip install -r requirements.txtcat <<'EOF' > env.examplePORT=3002SCALEKIT_ENVIRONMENT_URL=https://your-environment-url.scalekit.comSCALEKIT_CLIENT_ID=your_client_idSCALEKIT_RESOURCE_ID=mcp_server_idMCP_URL=http://localhost:3002/EOF -
Implement the FastMCP todo server
Section titled “Implement the FastMCP todo server”Copy the following code into
server.py. It registers the Scalekit provider, defines an in-memory todo store, and exposes CRUD tools guarded by thetodo:readandtodo:writescopes.server.py """Scalekit-authenticated FastMCP server providing in-memory CRUD tools for todos.This example mirrors the greeting-fastmcp project structure while exposingtodo management capabilities through FastMCP tools."""import osimport uuidfrom dataclasses import dataclass, asdictfrom typing import Optionalfrom dotenv import load_dotenvfrom fastmcp import FastMCPfrom fastmcp.server.auth.providers.scalekit import ScalekitProviderfrom fastmcp.server.dependencies import AccessToken, get_access_tokenload_dotenv()mcp = FastMCP("Todo 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"),# FastMCP appends /mcp automatically; keep base URL with trailing slash only.mcp_url=os.getenv("MCP_URL"),),)@dataclassclass TodoItem:id: strtitle: strdescription: Optional[str]completed: bool = Falsedef to_dict(self) -> dict:return asdict(self)_TODO_STORE: dict[str, TodoItem] = {}def _require_scope(scope: str) -> Optional[str]:token: AccessToken = get_access_token()if scope not in token.scopes:return f"Insufficient permissions: `{scope}` scope required."return None@mcp.tooldef create_todo(title: str, description: Optional[str] = None) -> dict:error = _require_scope("todo:write")if error:return {"error": error}todo = TodoItem(id=str(uuid.uuid4()), title=title, description=description)_TODO_STORE[todo.id] = todoreturn {"todo": todo.to_dict()}@mcp.tooldef list_todos(completed: Optional[bool] = None) -> dict:error = _require_scope("todo:read")if error:return {"error": error}todos = [todo.to_dict()for todo in _TODO_STORE.values()if completed is None or todo.completed == completed]return {"todos": todos}@mcp.tooldef get_todo(todo_id: str) -> dict:error = _require_scope("todo:read")if error:return {"error": error}todo = _TODO_STORE.get(todo_id)if todo is None:return {"error": f"Todo `{todo_id}` not found."}return {"todo": todo.to_dict()}@mcp.tooldef update_todo(todo_id: str,title: Optional[str] = None,description: Optional[str] = None,completed: Optional[bool] = None,) -> dict:error = _require_scope("todo:write")if error:return {"error": error}todo = _TODO_STORE.get(todo_id)if todo is None:return {"error": f"Todo `{todo_id}` not found."}if title is not None:todo.title = titleif description is not None:todo.description = descriptionif completed is not None:todo.completed = completedreturn {"todo": todo.to_dict()}@mcp.tooldef delete_todo(todo_id: str) -> dict:error = _require_scope("todo:write")if error:return {"error": error}todo = _TODO_STORE.pop(todo_id, None)if todo is None:return {"error": f"Todo `{todo_id}` not found."}return {"deleted": todo_id}if __name__ == "__main__":mcp.run(transport="http", port=int(os.getenv("PORT", "3002"))) -
Provide runtime secrets
Section titled “Provide runtime secrets”Copy the environment template, populate the values from the Scalekit dashboard, and review them with your security process.
Terminal cp env.example .envopen .envVariable Description SCALEKIT_ENVIRONMENT_URLYour Scalekit environment URL from Dashboard -> Settings SCALEKIT_CLIENT_IDScalekit Client ID Dashboard -> Settings SCALEKIT_RESOURCE_IDThe resource identifier assigned to your MCP server in Scalekit res_xxxxxx.MCP_URLThe base public URL you registered (keep the trailing slash, e.g., http://localhost:3002/).PORTLocal port for the FastMCP HTTP transport (defaults to 3002). -
Run the FastMCP server locally
Section titled “Run the FastMCP server locally”Start the server so it can accept authenticated MCP requests at
/mcp.Terminal source venv/bin/activatepython server.pyWhen the server boots successfully, you’ll see FastMCP announce the HTTP transport and listen on
http://localhost:3002/, ready to enforce Scalekit-issued tokens.
-
Connect with an MCP client
Section titled “Connect with an MCP client”Use any MCP-compatible client to exercise the todo tools with scoped tokens. During development, the MCP Inspector demonstrates how the Scalekit provider enforces scopes end-to-end.
Terminal npx @modelcontextprotocol/inspector@latestIn the Inspector UI, point the client to
http://localhost:3002/mcpand click connect. Run any tool (the example exposescreate_todo,list_todos,get_todo,update_todo,delete_todo).
Once you’re satisfied with the quickstart example, extend server.py with your own FastMCP tools or replace the in-memory store with your production data source. Scalekit’s provider handles authentication for any toolset you add. Continue with the MCP OAuth 2.1 implementation guide to enforce additional grant types, rotate credentials, and automate client onboarding.
You can get the full code example at GitHub.