Fastmcp Server Dynamic
All-in-one skill covering complete, guide, building, servers. Includes structured workflows, validation checks, and reusable patterns for development.
FastMCP Server Development Skill
A Claude Code skill for building production-ready MCP (Model Context Protocol) servers using FastMCP — the fast, Pythonic framework for exposing tools, resources, and prompts to LLM-powered applications.
When to Use This Skill
Choose this skill when:
- Building a new MCP server to expose tools to Claude or other LLMs
- Adding tools, resources, or prompts to an existing MCP server
- Implementing data connectors (database, API, file system) as MCP servers
- Creating custom integrations between LLMs and internal services
- Developing and testing MCP servers locally before deployment
Consider alternatives when:
- You need a TypeScript MCP server (use the TypeScript MCP SDK)
- You need to use existing MCP tools, not build new ones (use MCP client)
- You need a simple API without MCP protocol (use FastAPI or Express)
Quick Start
# Install FastMCP pip install fastmcp # Create a basic MCP server claude "create a FastMCP server with database query tools"
# server.py - Basic FastMCP Server from fastmcp import FastMCP mcp = FastMCP("My Data Server") @mcp.tool() def query_database(sql: str, limit: int = 100) -> str: """Execute a read-only SQL query against the analytics database. Args: sql: The SQL query to execute (SELECT only) limit: Maximum rows to return """ if not sql.strip().upper().startswith("SELECT"): return "Error: Only SELECT queries are allowed" results = db.execute(sql, limit=limit) return format_results(results) @mcp.tool() def search_documents(query: str, collection: str = "default") -> list[dict]: """Search documents by semantic similarity. Args: query: Natural language search query collection: Document collection to search """ results = vector_store.search(query, collection=collection, top_k=10) return [{"title": r.title, "content": r.content, "score": r.score} for r in results] @mcp.resource("config://app") def get_app_config() -> str: """Current application configuration.""" return json.dumps(load_config(), indent=2) if __name__ == "__main__": mcp.run()
Core Concepts
MCP Components
| Component | Purpose | Example |
|---|---|---|
| Tools | Functions the LLM can invoke | query_database(), send_email() |
| Resources | Read-only data the LLM can access | config://app, schema://users |
| Prompts | Reusable prompt templates | summarize(text), analyze(data) |
Tool Patterns
from fastmcp import FastMCP, Context from pydantic import BaseModel, Field mcp = FastMCP("API Server") # Tool with structured input class CreateUserInput(BaseModel): name: str = Field(description="Full name of the user") email: str = Field(description="Email address") role: str = Field(default="member", description="User role: admin, member, viewer") @mcp.tool() def create_user(input: CreateUserInput) -> dict: """Create a new user account with the specified details.""" user = User.create(name=input.name, email=input.email, role=input.role) return {"id": user.id, "name": user.name, "created": True} # Tool with context for logging and progress @mcp.tool() async def process_batch(items: list[str], ctx: Context) -> dict: """Process a batch of items with progress reporting.""" results = [] for i, item in enumerate(items): await ctx.report_progress(i, len(items)) result = await process_item(item) results.append(result) return {"processed": len(results), "results": results} # Resource with URI template @mcp.resource("users://{user_id}/profile") def get_user_profile(user_id: str) -> str: """User profile data.""" user = User.find(user_id) return json.dumps(user.profile)
Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
name | string | — | Server name displayed to clients (required) |
host | string | "localhost" | Server bind address |
port | number | 8000 | Server port number |
transport | string | "stdio" | Transport: stdio, sse, streamable-http |
log_level | string | "info" | Logging level: debug, info, warning, error |
auth | string | "none" | Authentication: none, token, oauth |
max_concurrent | number | 10 | Maximum concurrent tool executions |
timeout | number | 30 | Default tool execution timeout in seconds |
Best Practices
-
Write detailed tool descriptions and parameter docs — LLMs use the tool description to decide when and how to call it; vague descriptions lead to incorrect tool usage and wasted API calls.
-
Make tools idempotent when possible — tools that can be safely called multiple times with the same input simplify error handling and retries on the LLM side.
-
Return structured data, not formatted text — return JSON objects or structured strings rather than prose; the LLM can format the data for the user, but it can't extract structure from formatted text.
-
Validate inputs inside tools — don't assume the LLM will provide valid inputs; check types, ranges, and required fields, and return clear error messages explaining what's wrong.
-
Use async for I/O-bound tools — database queries, API calls, and file operations should be async to prevent blocking the server when multiple tools are invoked concurrently.
Common Issues
LLM calls the wrong tool — Tool descriptions are too similar or too vague. Make each tool description specific about when to use it and how it differs from similar tools. Include examples in the description.
Tool execution timeout on large operations — Long-running tools (batch processing, large queries) exceed the default timeout. Use ctx.report_progress() to show progress and increase the timeout for specific tools.
Server crashes on invalid input — Missing input validation causes unhandled exceptions. Wrap tool implementations in try-catch and return error messages instead of raising exceptions that crash the server.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.