Help us improve
Share bugs, ideas, or general feedback.
From fastmcp
Builds Python MCP servers to expose tools, resources, and prompts to LLMs like Claude. Supports storage backends (memory, disk, Redis, DynamoDB), OAuth proxy, and cloud deployment.
npx claudepluginhub secondsky/claude-skills --plugin fastmcpHow this skill is triggered — by the user, by Claude, or both
Slash command
/fastmcp:fastmcpThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
FastMCP is a Python framework for building Model Context Protocol (MCP) servers that expose tools, resources, and prompts to Large Language Models like Claude.
references/cli-commands.mdreferences/cloud-deployment.mdreferences/common-errors.mdreferences/context-features.mdreferences/error-catalog.mdreferences/integration-patterns.mdreferences/production-patterns.mdscripts/check-versions.shscripts/deploy-cloud.shscripts/test-server.shtemplates/api-client-pattern.pytemplates/basic-server.pytemplates/client-example.pytemplates/error-handling.pytemplates/openapi-integration.pytemplates/prompts-examples.pytemplates/pyproject.tomltemplates/requirements.txttemplates/resources-examples.pytemplates/self-contained-server.pyBuilds Python MCP servers with FastMCP: define/expose tools, resources, prompts to LLMs; scaffold code, test locally with inspector, deploy to cloud/Docker.
Provides patterns, architecture diagrams, and decision trees for building, testing, and deploying Model Context Protocol (MCP) servers in Python and TypeScript with tools, resources, prompts, and transports like stdio, SSE, streamable HTTP.
Guides creation of MCP servers exposing tools, resources, and prompts to Claude. Supports TypeScript and Python for APIs, integrations, OAuth auth, with workflows for setup and troubleshooting.
Share bugs, ideas, or general feedback.
FastMCP is a Python framework for building Model Context Protocol (MCP) servers that expose tools, resources, and prompts to Large Language Models like Claude.
pip install fastmcp
# or: uv pip install fastmcp
from fastmcp import FastMCP
# MUST be at module level for FastMCP Cloud
mcp = 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 development
fastmcp dev server.py # With FastMCP CLI
python server.py --transport http --port 8000 # HTTP mode
Copy-Paste Template: See templates/basic-server.py
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:
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
Pre-configured prompts for LLMs:
@mcp.prompt("analyze")
def analyze_prompt(topic: str) -> str:
"""Generate analysis prompt."""
return f"""Analyze {topic} considering:
1. Current state
2. Challenges
3. Opportunities
4. Recommendations"""
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"}
Choose storage based on deployment:
from key_value.stores import DiskStore, RedisStore
from key_value.encryption import FernetEncryptionWrapper
from cryptography.fernet import Fernet
# Memory (default) - Development only
mcp = FastMCP("Dev Server")
# Disk - Single instance
mcp = FastMCP(
"Production Server",
storage=FernetEncryptionWrapper(
key_value=DiskStore(path="/var/lib/mcp/storage"),
fernet=Fernet(os.getenv("STORAGE_ENCRYPTION_KEY"))
)
)
# Redis - Multi-instance
mcp = 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"))
)
)
Initialize resources on server startup:
from contextlib import asynccontextmanager
@asynccontextmanager
async 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.
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 BaseMiddleware
class 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
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
FastMCP Cloud Requirements:
# ✅ Cloud-ready pattern
mcp = FastMCP("My Server") # Module level
@mcp.tool()
async def my_tool(): pass
if __name__ == "__main__":
mcp.run()
Deploy:
fastmcp deploy server.py
Error: RuntimeError: No server object found at module level
Fix:
# ❌ WRONG
def create_server():
return FastMCP("server")
# ✅ CORRECT
mcp = FastMCP("server") # At module level
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
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")
Error: RuntimeError: OAuth tokens lost on restart
Fix: Use disk or Redis storage in production (see Storage Backends section above)
Error: ImportError: cannot import name 'X' from partially initialized module
Fix:
# ❌ WRONG: Factory function creating circular dependency
# shared/__init__.py
def get_client():
from .api_client import APIClient # Circular!
return APIClient()
# ✅ CORRECT: Direct imports
# shared/__init__.py
from .api_client import APIClient
from .cache import CacheManager
# shared/monitoring.py
from .api_client import APIClient
client = APIClient()
See all 25 errors: references/error-catalog.md
{
"mcpServers": {
"my-server": {
"command": "python",
"args": ["/path/to/server.py"]
}
}
}
{
"mcpServers": {
"my-server": {
"command": "python",
"args": ["server.py"]
}
}
}
fastmcp dev server.py # Development mode with hot reload
fastmcp run server.py # Production mode
fastmcp deploy server.py # Deploy to FastMCP Cloud
fastmcp test server.py # Run tests
FastMCP.test_tool()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 patternsTemplates (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": {
"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
}
}
fastmcp>=2.13.0)Token Savings: 90-95% vs learning from scratch Errors Prevented: 25 documented issues Production Tested: ✅ Multiple deployments