Marketplace

Unnamed Skill

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.

$ Instalar

git clone https://github.com/secondsky/claude-skills /tmp/claude-skills && cp -r /tmp/claude-skills/plugins/fastmcp/skills/fastmcp ~/.claude/skills/claude-skills

// tip: Run this command in your terminal to install the skill


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.

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 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"

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 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

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 state
    2. Challenges
    3. Opportunities
    4. 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, 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"))
    )
)

Server Lifespans

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.

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 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

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:

  1. Server MUST be at module level
  2. Use disk/Redis storage (not memory)
  3. No import-time execution
# ✅ 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

Top 5 Critical Errors

1. Missing Server Object

Error: RuntimeError: No server object found at module level

Fix:

# ❌ WRONG
def create_server():
    return FastMCP("server")

# ✅ CORRECT
mcp = 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__.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

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 reload
fastmcp run server.py              # Production mode
fastmcp deploy server.py           # Deploy to FastMCP Cloud
fastmcp test server.py             # Run tests

Best Practices

  1. Server Structure: Keep module-level server, organize tools in separate files
  2. Type Hints: Use Pydantic models for complex validation
  3. Documentation: Write detailed docstrings (LLMs read them!)
  4. Error Handling: Catch and return structured errors
  5. Storage: Use encrypted disk/Redis in production
  6. Lifespans: Initialize connections once per server
  7. Middleware: Order matters (error handling → timing → logging → rate limiting → caching)
  8. 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 requirements
  • common-errors.md - All 25 documented errors with solutions and prevention
  • context-features.md - Progress tracking, user input, and Context API patterns
  • error-catalog.md - Comprehensive error catalog with fixes
  • integration-patterns.md - Server composition (import/mount), OAuth Proxy, OpenAPI
  • production-patterns.md - Storage backends, lifespans, middleware, architecture patterns

Templates (templates/):

  • basic-server.py - Minimal MCP server with tools, resources, prompts
  • client-example.py - MCP client integration examples
  • api-client-pattern.py - API integration patterns
  • error-handling.py - Error handling best practices
  • openapi-integration.py - OpenAPI schema integration
  • prompts-examples.py - Prompt template patterns
  • resources-examples.py - Resource URI patterns and examples
  • tools-examples.py - Tool definition patterns
  • self-contained-server.py - Complete production-ready self-contained server
  • .env.example - Environment variables template
  • requirements.txt - Python dependencies
  • pyproject.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

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