Scaffold production-ready Python MCP servers using FastMCP. Use when creating new MCP servers, initializing MCP projects, generating server boilerplate, or setting up MCP development environments. Supports all MCP primitives (tools, resources, prompts) with Pydantic validation, async patterns, and proper project structure.
Scaffold production-ready Python MCP servers with FastMCP.
Generate a new MCP server:
python scripts/scaffold.py my-server --output ./my-server
This creates a complete project structure with:
server.py - Main server with example tool, resource, and promptrequirements.txt - Dependencies (fastmcp, pydantic)README.md - Usage instructionspython scripts/scaffold.py my-server --template basic
python scripts/scaffold.py my-server --template full
python scripts/scaffold.py my-server \
--tools \
--resources \
--prompts \
--lifespan \
--output ./servers/my-server
Validate an existing MCP server:
python scripts/validate.py path/to/server.py
Checks:
Generated projects follow this structure:
my-server/
├── server.py # Main MCP server
├── requirements.txt # Python dependencies
├── README.md # Usage documentation
└── data/ # Default data directory (gitignored)
Minimal server with one tool:
from fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool
def hello(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run()
Complete server with tools, resources, prompts, and lifespan. See assets/templates/full-server.py.
from pydantic import Field
@mcp.tool
def my_tool(
param: str = Field(description="Parameter description"),
optional: int = Field(default=10, description="Optional with default")
) -> dict:
"""Tool description shown to LLM."""
return {"result": param}
@mcp.resource("myscheme://path/to/resource")
def static_resource() -> str:
"""Resource description."""
return json.dumps({"data": "value"})
@mcp.resource("myscheme://items/{item_id}")
def dynamic_resource(item_id: str) -> str:
"""Dynamic resource with URI template."""
return json.dumps({"id": item_id})
@mcp.prompt(name="my_prompt", tags={"category"})
def my_prompt(
topic: str = Field(description="What to analyze")
) -> str:
"""Prompt description."""
return f"Please analyze {topic} and provide insights."
python server.pyclaude mcp add