Claude-skill-registry fastmcp-patterns
FastMCP server patterns for building MCP servers. Use when implementing MCP tools, resources, or server configuration.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/fastmcp-patterns" ~/.claude/skills/majiayu000-claude-skill-registry-fastmcp-patterns && rm -rf "$T"
manifest:
skills/data/fastmcp-patterns/SKILL.mdsource content
FastMCP Patterns
Server Setup with Lifespan
from contextlib import asynccontextmanager from mcp.server.fastmcp import FastMCP @asynccontextmanager async def lifespan(server: FastMCP): """Initialize resources on startup, cleanup on shutdown.""" driver = create_neo4j_driver(config) driver.verify_connectivity() try: yield {"driver": driver, "config": config} finally: driver.close() mcp = FastMCP( "requirements-graphrag-mcp", lifespan=lifespan, )
Tool Registration
Basic Tool with Pydantic Validation
from pydantic import BaseModel, Field class SearchInput(BaseModel): query: str = Field(..., description="Search query text") limit: int = Field(default=10, ge=1, le=100, description="Max results") @mcp.tool() async def semantic_search(input: SearchInput) -> list[dict]: """Search articles using semantic similarity.""" driver = mcp.state["driver"] return await execute_vector_search(driver, input.query, input.limit)
Tool with Annotations
from mcp.server.fastmcp import Context @mcp.tool( annotations={ "readOnlyHint": True, "openWorldHint": False, } ) async def get_schema(ctx: Context) -> dict: """Get database schema. Read-only operation.""" driver = ctx.state["driver"] return await fetch_schema(driver)
Resource Registration
@mcp.resource("schema://database") async def database_schema() -> str: """Expose database schema as a resource.""" driver = mcp.state["driver"] schema = await fetch_schema(driver) return json.dumps(schema, indent=2)
Error Handling Pattern
from requirements_graphrag_api.exceptions import ( Neo4jConnectionError, QueryExecutionError, ) @mcp.tool() async def execute_cypher(query: str) -> dict: """Execute a Cypher query.""" try: driver = mcp.state["driver"] return await run_query(driver, query) except Neo4jConnectionError as e: return {"error": "Database connection failed", "details": str(e)} except QueryExecutionError as e: return {"error": "Query execution failed", "details": str(e)}
Configuration Pattern
from dataclasses import dataclass @dataclass(frozen=True, slots=True) class AppConfig: neo4j_uri: str neo4j_username: str neo4j_password: str neo4j_database: str = "neo4j" neo4j_max_connection_pool_size: int = 5 @classmethod def from_env(cls) -> "AppConfig": return cls( neo4j_uri=os.environ["NEO4J_URI"], neo4j_username=os.environ["NEO4J_USERNAME"], neo4j_password=os.environ["NEO4J_PASSWORD"], neo4j_database=os.environ.get("NEO4J_DATABASE", "neo4j"), )
Entry Point
# src/requirements_graphrag_api/__main__.py from requirements_graphrag_api.server import mcp def main(): mcp.run() if __name__ == "__main__": main()
pyproject.toml Script
[project.scripts] requirements-graphrag-api = "requirements_graphrag_api.__main__:main"