Build a Custom MCP Server in Python (MCPServer, formerly FastMCP)
Expose your own functions as MCP tools and resources using the official Python SDK in about 20 lines.
Install
uv init my-mcp && cd my-mcp
uv add "mcp[cli]>=2"server.py
from mcp.server.mcpserver import MCPServer # mcp>=2; on mcp<2: from mcp.server.fastmcp import FastMCP
mcp = MCPServer("notes")
NOTES: dict[str, str] = {}
@mcp.tool()
def add_note(title: str, body: str) -> str:
"""Save a note under a title."""
NOTES[title] = body
return f"Saved '{title}'"
@mcp.tool()
def search_notes(query: str) -> list[str]:
"""Return titles of notes containing the query."""
return [t for t, b in NOTES.items() if query.lower() in (t + b).lower()]
@mcp.resource("notes://{title}")
def read_note(title: str) -> str:
return NOTES.get(title, "Not found")
if __name__ == "__main__":
mcp.run() # stdio transport by defaultTest and connect
uv run mcp dev server.py # opens the MCP Inspector{"mcpServers": {"notes": {"command": "uv", "args": ["--directory", "/abs/path/my-mcp", "run", "server.py"]}}}Docstrings and type hints become the tool description and input schema, so write them carefully.
Failure modes
- Code written for mcp 1.x (FastMCP import) fails on mcp 2.x; pin your major version.
- Printing to stdout corrupts the stdio protocol stream.
- Weak docstrings and type hints produce vague tool schemas the model misuses.
Markdown version: /blueprints/mcp-python-server.md
Want a deeper build of this?
Vote for an extended, fully tested version (more tools, a full workflow file). Votes decide what we build next.
Get one fully built blueprint a week
A weekly email: one blueprint with config, cost, setup time and failure modes, plus a vote on what we build next.
Related blueprints
Build a Custom MCP Server in TypeScript
A minimal stdio MCP server using @modelcontextprotocol/sdk with a zod-validated tool.
GitHub MCP Server with a Scoped Token
Run GitHub's official MCP server in Docker with a fine-grained, least-privilege personal access token.
MCP Starter Config for Claude Desktop
A claude_desktop_config.json wiring up filesystem, fetch, and git MCP servers with scoped access.