Building an MCP server in Python is short work thanks to FastMCP, the high-level helper in the official Python SDK. Here is a minimal server that exposes one tool — under 30 lines — runnable in Claude Desktop and Cursor.
Setup
Use uv (recommended) or pip:
uv init weather-mcp && cd weather-mcp
uv add "mcp[cli]"
The server
Create server.py:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
@mcp.tool()
def get_weather(city: str) -> str:
"""Get the current weather for a given city."""
# TODO: call a real weather API. For now, fake it.
return f"{city}: 18°C, partly cloudy"
if __name__ == "__main__":
mcp.run()
That is the whole server. The @mcp.tool() decorator turns a typed function into an MCP tool — the docstring becomes the tool description, and type hints become the input schema. No boilerplate.
Test it
Run the MCP inspector against it:
uv run mcp dev server.py
This opens a browser UI. List tools → you should see get_weather. Call it with a city and you get the fake forecast.
Use it in Claude Desktop
Add to your config (see MCP config file location):
{
"mcpServers": {
"weather": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/weather-mcp", "run", "server.py"]
}
}
}
Restart Claude, click the hammer icon, and ask "what's the weather in Tokyo?" — it calls your tool.
Make it real
- Replace the fake body with a real HTTP call (
httpx). Read the API key from an environment variable. - Add more tools — each is another
@mcp.tool()function. - Log to stderr, never stdout — stdout carries the MCP protocol, and printing there closes the connection. See MCP "connection closed" error.
Going further
Prefer TypeScript? See build your first MCP server in Node.js. Already have a REST API? Generate an MCP server from OpenAPI. When it is ready, submit it to Loadout.