Build MCP Servers in Python with FastMCP in 2026 — ship tools your AI hosts can call. FastMCP turns ordinary Python functions into MCP tools, resources, and prompts.
If you already use something like MotherDuck MCP for AI agents, this guide flips the perspective: you build the server.
TL;DR
- Tools — actions the model can call
- Resources — read-only context the host can fetch
- Prompts — reusable message templates
- Start on stdio for Cursor; move to Streamable HTTP when remote
Project setup with uv
uv init pyinns-mcp-demo
cd pyinns-mcp-demo
uv add fastmcp
Minimal FastMCP server
from __future__ import annotations
from datetime import date
from typing import Any
from fastmcp import FastMCP
mcp = FastMCP("PyInns Ops Tools")
CHECKLIST = ["Run pytest + ruff", "Smoke-test /health", "Watch errors 15 min"]
@mcp.tool
def estimate_release_window(open_bugs: int, test_coverage: float) -> dict[str, Any]:
"""Estimate a safe release window from open bugs and coverage."""
if open_bugs < 0 or not 0.0 <= test_coverage <= 1.0:
raise ValueError("invalid inputs")
if open_bugs == 0 and test_coverage >= 0.85:
return {"window": "same-day", "risk": "low", "as_of": date.today().isoformat()}
if open_bugs <= 2 and test_coverage >= 0.75:
return {"window": "this-week", "risk": "medium", "as_of": date.today().isoformat()}
return {"window": "hold", "risk": "high", "as_of": date.today().isoformat()}
@mcp.resource("docs://release-checklist")
def release_checklist() -> dict[str, Any]:
"""Return the standard release checklist."""
return {"owner": "platform-team", "items": CHECKLIST}
@mcp.prompt
def incident_status_update(service: str, severity: str) -> str:
"""Draft a short incident status update."""
return f"Write a calm status update for `{service}` at severity `{severity}`."
if __name__ == "__main__":
mcp.run()
Connect from Cursor (stdio)
{
"mcpServers": {
"pyinns-ops": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/pyinns-mcp-demo", "python", "server.py"]
}
}
}
Production notes
- Never expose Streamable HTTP without auth
- Validate tool inputs (domain checks on top of schemas)
- Log tool name + latency; never log secrets
- Pair with durable agents — see LangGraph stateful agents and the 2026 AI engineer stack
Conclusion
With FastMCP, a few typed functions become tools hosts like Cursor can call today. Start on stdio, prove the tools are safe, then graduate to Streamable HTTP with real auth.