I recently built a small Python starter template for creating a stateless MCP server using FastMCP and FastAPI.
The goal was simple: expose Python functions as MCP tools over Streamable HTTP, while keeping the server easy to run, test, and deploy.
What the project includes
This server includes:
- Stateless MCP HTTP initialization
- JSON response mode
- FastAPI lifecycle management
- A health check endpoint
- Example MCP tools
- Structured tool responses
- MCP Inspector testing support
The MCP server is initialized like this:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP(
"Stateless Python MCP Server",
stateless_http=True,
json_response=True,
)
The important part is:
stateless_http=True
This makes the HTTP server stateless, which is useful when deploying MCP servers as normal web services.
FastAPI integration
The MCP server is wrapped inside a FastAPI application.
@asynccontextmanager
async def lifespan(app: FastAPI):
async with AsyncExitStack() as stack:
await stack.enter_async_context(mcp.session_manager.run())
yield
Then the MCP application is mounted:
app = FastAPI(lifespan=lifespan)
app.mount("/", mcp.streamable_http_app())
A health endpoint is also included:
@app.get("/health")
async def health():
return {"status": "healthy"}
This is useful for deployment checks, containers, reverse proxies, and cloud platforms.
Example MCP tools
Here is a simple tool:
@mcp.tool()
async def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
And another one with structured output:
class UserResult(TypedDict):
id: int
name: str
status: str
@mcp.tool()
async def get_user_by_id(user_id: int) -> UserResult:
"""Get user details by ID."""
return {
"id": user_id,
"name": "Demo User",
"status": "active",
}
Using clear type hints helps MCP clients understand the input and output schema.
Running the server
The server can be started with:
uv run uvicorn app:app --host 0.0.0.0 --port 8000 --reload
Health check:
curl http://localhost:8000/health
Expected response:
{
"status": "healthy"
}
Testing with MCP Inspector
For local testing:
uv run mcp dev app.py
The MCP Inspector can list available tools and call them with sample inputs.
Why this pattern is useful
This setup is useful when you want to expose Python functions as MCP tools without tying the server to a local-only or stateful runtime.
It can be used as a base for:
- Internal automation tools
- Database query tools
- API wrappers
- AI agent integrations
- Developer productivity tools
- Backend services exposed through MCP
Final thoughts
This project is a simple but practical starting point for building production-ready MCP servers in Python.
The next step is to replace the demo tools with real business logic, connect them to databases or APIs, and place the server behind authentication before exposing it publicly.
Top comments (0)