Skill v1.0.1
currentAutomated scan100/100+12 new, ~1 modified
version: "1.0.1" name: fastmcp description: "FastMCP Python framework for MCP servers with tools, resources, storage backends (memory/disk/Redis/DynamoDB). Use for Claude tool exposure, OAuth Proxy, cloud deployment, or encountering storage, lifespan, middleware, circular import, async errors." license: MIT metadata: version: "2.0.0" package_version: "fastmcp>=2.13.0" python_version: ">=3.10" token_savings: "90-95%" errors_prevented: 25 production_tested: true last_updated: "2025-11-18" keywords:
- FastMCP
- MCP server Python
- Model Context Protocol Python
- fastmcp framework
- mcp tools
- mcp resources
- mcp prompts
- fastmcp storage
- fastmcp memory storage
- fastmcp disk storage
- fastmcp redis
- fastmcp dynamodb
- fastmcp lifespan
- fastmcp middleware
- fastmcp oauth proxy
- server composition mcp
- fastmcp import
- fastmcp mount
- fastmcp cloud
- fastmcp deployment
- mcp authentication
- fastmcp icons
- openapi mcp
- claude mcp server
- fastmcp testing
- storage misconfiguration
- lifespan issues
- middleware order
- circular imports
- module-level server
- async await mcp
FastMCP - Build MCP Servers in Python
FastMCP is a Python framework for building Model Context Protocol (MCP) servers that expose tools, resources, and prompts to Large Language Models like Claude.
Quick Start
Installation
pip install fastmcp# or: uv pip install fastmcp
Minimal Server
from fastmcp import FastMCP# MUST be at module level for FastMCP Cloudmcp = FastMCP("My Server")@mcp.tool()async def hello(name: str) -> str:"""Say hello to someone."""return f"Hello, {name}!"if __name__ == "__main__":mcp.run()
Run:
python server.py # Local developmentfastmcp dev server.py # With FastMCP CLIpython server.py --transport http --port 8000 # HTTP mode
Copy-Paste Template: See templates/basic-server.py
Core Concepts
Tools
Functions that LLMs can call:
@mcp.tool()def calculate(operation: str, a: float, b: float) -> float:"""Perform mathematical operations."""operations = {"add": lambda x, y: x + y,"subtract": lambda x, y: x - y,"multiply": lambda x, y: x * y,"divide": lambda x, y: x / y if y != 0 else None}return operations.get(operation, lambda x, y: None)(a, b)
Best Practices:
- Clear, descriptive function names
- Comprehensive docstrings (LLMs read these!)
- Strong type hints (Pydantic validates automatically)
- Return structured data (dicts/lists)
- Handle errors gracefully
Resources
Expose static or dynamic data:
@mcp.resource("data://config")def get_config() -> dict:"""Provide application configuration."""return {"version": "1.0.0", "features": ["auth", "api"]}# Dynamic resource with parameters@mcp.resource("user://{user_id}/profile")async def get_user_profile(user_id: str) -> dict:"""Get user profile by ID."""return {"id": user_id, "name": f"User {user_id}"}
URI Schemes: data://, file://, resource://, info://, api://, or custom
Prompts
Pre-configured prompts for LLMs:
@mcp.prompt("analyze")def analyze_prompt(topic: str) -> str:"""Generate analysis prompt."""return f"""Analyze {topic} considering:1. Current state2. Challenges3. Opportunities4. Recommendations"""
Context Features
Progress Tracking:
from fastmcp import Context@mcp.tool()async def batch_process(items: list, context: Context) -> dict:"""Process items with progress updates."""for i, item in enumerate(items):await context.report_progress(i + 1, len(items), f"Processing {item}")await process_item(item)return {"processed": len(items)}
User Input:
@mcp.tool()async def confirm_action(action: str, context: Context) -> dict:"""Perform action with user confirmation."""confirmed = await context.request_elicitation(prompt=f"Confirm {action}? (yes/no)",response_type=str)return {"confirmed": confirmed.lower() == "yes"}
Storage Backends
Choose storage based on deployment:
from key_value.stores import DiskStore, RedisStorefrom key_value.encryption import FernetEncryptionWrapperfrom cryptography.fernet import Fernet# Memory (default) - Development onlymcp = FastMCP("Dev Server")# Disk - Single instancemcp = FastMCP("Production Server",storage=FernetEncryptionWrapper(key_value=DiskStore(path="/var/lib/mcp/storage"),fernet=Fernet(os.getenv("STORAGE_ENCRYPTION_KEY"))))# Redis - Multi-instancemcp = FastMCP("Production Server",storage=FernetEncryptionWrapper(key_value=RedisStore(host=os.getenv("REDIS_HOST"),password=os.getenv("REDIS_PASSWORD")),fernet=Fernet(os.getenv("STORAGE_ENCRYPTION_KEY"))))
Server Lifespans
Initialize resources on server startup:
from contextlib import asynccontextmanager@asynccontextmanagerasync def app_lifespan(server: FastMCP):"""Runs ONCE when server starts (v2.13.0+)."""db = await Database.connect()print("Server starting")try:yield {"db": db}finally:await db.disconnect()print("Server stopping")mcp = FastMCP("My Server", lifespan=app_lifespan)
Critical: v2.13.0+ lifespans run per-server (not per-session). For per-session logic, use middleware.
Middleware System
8 built-in middleware types:
from fastmcp.middleware import (LoggingMiddleware,TimingMiddleware,RateLimitingMiddleware,ResponseCachingMiddleware)# Order matters!mcp.add_middleware(LoggingMiddleware())mcp.add_middleware(TimingMiddleware())mcp.add_middleware(RateLimitingMiddleware(max_requests=100, window_seconds=60))mcp.add_middleware(ResponseCachingMiddleware(ttl_seconds=3600))
Custom Middleware:
from fastmcp.middleware import BaseMiddlewareclass CustomMiddleware(BaseMiddleware):async def on_call_tool(self, tool_name, arguments, context):print(f"Before: {tool_name}")result = await self.next(tool_name, arguments, context) # MUST call next()print(f"After: {tool_name}")return result
Server Composition
Import Server (static, one-time copy):
main_server.import_server(vendor_server) # Static bundle
Mount Server (dynamic, runtime delegation):
main_server.mount(api_server, prefix="api") # Changes appear immediately
Cloud Deployment
FastMCP Cloud Requirements:
- Server MUST be at module level
- Use disk/Redis storage (not memory)
- No import-time execution
# ✅ Cloud-ready patternmcp = FastMCP("My Server") # Module level@mcp.tool()async def my_tool(): passif __name__ == "__main__":mcp.run()
Deploy:
fastmcp deploy server.py
Top 5 Critical Errors
1. Missing Server Object
Error: RuntimeError: No server object found at module level
Fix:
# ❌ WRONGdef create_server():return FastMCP("server")# ✅ CORRECTmcp = FastMCP("server") # At module level
2. Async/Await Confusion
Error: RuntimeError: no running event loop
Fix:
# ❌ WRONG: Sync function calling async@mcp.tool()def bad_tool():result = await async_function() # Error!# ✅ CORRECT: Async tool@mcp.tool()async def good_tool():result = await async_function()return result
3. Context Not Injected
Error: TypeError: missing 1 required positional argument: 'context'
Fix:
from fastmcp import Context# ❌ WRONG: No type hint@mcp.tool()async def bad_tool(context): # Missing type!await context.report_progress(...)# ✅ CORRECT: Proper type hint@mcp.tool()async def good_tool(context: Context):await context.report_progress(0, 100, "Starting")
4. Storage Backend Not Configured
Error: RuntimeError: OAuth tokens lost on restart
Fix: Use disk or Redis storage in production (see Storage Backends section above)
5. Circular Import Errors
Error: ImportError: cannot import name 'X' from partially initialized module
Fix:
# ❌ WRONG: Factory function creating circular dependency# shared/__init__.pydef get_client():from .api_client import APIClient # Circular!return APIClient()# ✅ CORRECT: Direct imports# shared/__init__.pyfrom .api_client import APIClientfrom .cache import CacheManager# shared/monitoring.pyfrom .api_client import APIClientclient = APIClient()
See all 25 errors: references/error-catalog.md
Client Configuration
Claude Desktop
{"mcpServers": {"my-server": {"command": "python","args": ["/path/to/server.py"]}}}
Claude Code CLI
{"mcpServers": {"my-server": {"command": "python","args": ["server.py"]}}}
CLI Commands
fastmcp dev server.py # Development mode with hot reloadfastmcp run server.py # Production modefastmcp deploy server.py # Deploy to FastMCP Cloudfastmcp test server.py # Run tests
Best Practices
- Server Structure: Keep module-level server, organize tools in separate files
- Type Hints: Use Pydantic models for complex validation
- Documentation: Write detailed docstrings (LLMs read them!)
- Error Handling: Catch and return structured errors
- Storage: Use encrypted disk/Redis in production
- Lifespans: Initialize connections once per server
- Middleware: Order matters (error handling → timing → logging → rate limiting → caching)
- Testing: Unit test tools with
FastMCP.test_tool()
Bundled Resources
References (references/):
cli-commands.md- Complete CLI command reference (dev, run, deploy, test)cloud-deployment.md- FastMCP Cloud deployment guide with module-level requirementscommon-errors.md- All 25 documented errors with solutions and preventioncontext-features.md- Progress tracking, user input, and Context API patternserror-catalog.md- Comprehensive error catalog with fixesintegration-patterns.md- Server composition (import/mount), OAuth Proxy, OpenAPIproduction-patterns.md- Storage backends, lifespans, middleware, architecture patterns
Templates (templates/):
basic-server.py- Minimal MCP server with tools, resources, promptsclient-example.py- MCP client integration examplesapi-client-pattern.py- API integration patternserror-handling.py- Error handling best practicesopenapi-integration.py- OpenAPI schema integrationprompts-examples.py- Prompt template patternsresources-examples.py- Resource URI patterns and examplestools-examples.py- Tool definition patternsself-contained-server.py- Complete production-ready self-contained server.env.example- Environment variables templaterequirements.txt- Python dependenciespyproject.toml- Python project configuration
Dependencies
{"dependencies": {"fastmcp": ">=2.13.0","pydantic": ">=2.0.0"},"optionalDependencies": {"py-key-value-aio": ">=0.1.0", // For storage backends"cryptography": ">=41.0.0", // For encryption"redis": ">=5.0.0" // For Redis storage}}
Official Documentation
- FastMCP GitHub: https://github.com/jlowin/fastmcp
- MCP Protocol: https://modelcontextprotocol.io
- FastMCP Cloud: https://fastmcp.com
Verification Checklist
- [ ] FastMCP installed (
fastmcp>=2.13.0) - [ ] Server object at module level
- [ ] Tool docstrings comprehensive
- [ ] Context type hints for context parameters
- [ ] Resource URIs have schemes
- [ ] Storage backend configured (production)
- [ ] Lifespan pattern correct (v2.13.0+)
- [ ] Middleware order logical
- [ ] Client configuration tested
- [ ] Production deployment successful
Token Savings: 90-95% vs learning from scratch Errors Prevented: 25 documented issues Production Tested: ✅ Multiple deployments