@@ -6,15 +6,15 @@ description: "Create a simple MCP server in Python in 15 minutes"
66Let's build your first MCP server in Python! We'll create a weather server that provides current weather data as a resource and lets Claude fetch forecasts using tools.
77
88<Note >
9- This guide uses the OpenWeatherMap API. You'll need a free API key from [ OpenWeatherMap] ( https://openweathermap.org/api ) to follow along.
9+ This guide uses the OpenWeatherMap API. You'll need a free API key from [ OpenWeatherMap] ( https://openweathermap.org/api ) to follow along.
1010</Note >
1111
1212## Prerequisites
1313
1414<Steps >
1515 <Step title = " Install Python" >
16- You'll need Python 3.9 or higher:
17-
16+ You'll need Python 3.10 or higher:
17+
1818 ``` bash
1919 python --version # Should be 3.9 or higher
2020 pip --version
@@ -25,19 +25,19 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
2525 ``` bash
2626 mkdir weather-server
2727 cd weather-server
28- python -m venv venv
29- source venv/bin/activate # On Windows use: venv\Scripts\activate
28+ uv init --package --app --name weather-server
3029 ```
3130 </Step >
3231
3332 <Step title = " Install dependencies" >
3433 ``` bash
35- pip install modelcontextprotocol requests python-dotenv
34+ uv add mcp
3635 ```
3736 </Step >
3837
3938 <Step title = " Set up environment" >
4039 Create ` .env ` :
40+
4141 ``` bash
4242 OPENWEATHER_API_KEY=your-api-key-here
4343 ```
@@ -61,7 +61,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
6161 import json
6262 from datetime import datetime
6363 from typing import Any, Dict, List, Optional
64-
64+
6565 import requests
6666 from dotenv import load_dotenv
6767 from modelcontextprotocol import Server, StdioServerTransport
@@ -127,7 +127,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
127127 print (" Weather MCP server running on stdio" , flush = True )
128128
129129 # Handler implementations will continue in next sections
130- ```
130+ ```
131131 </Step >
132132
133133 <Step title = " Add resource handlers" >
@@ -298,6 +298,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
298298 ```
299299
300300 Create ` setup.py ` :
301+
301302 ``` python
302303 from setuptools import setup
303304
@@ -331,6 +332,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
331332 ) -> Dict[str , Any]:
332333 # ...
333334 ```
335+
334336 Python type hints help catch errors early and improve code maintainability.
335337 </Tab >
336338
@@ -348,6 +350,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
348350 }]
349351 }
350352 ```
353+
351354 Resources provide data that Claude can access as context.
352355 </Tab >
353356
@@ -365,17 +368,15 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
365368 }
366369 }
367370 ```
371+
368372 Tools let Claude take actions through your server with validated inputs.
369373 </Tab >
370374</Tabs >
371375
372376## Best practices
373377
374378<CardGroup cols = { 1 } >
375- <Card
376- title = " Error Handling"
377- icon = " shield"
378- >
379+ <Card title = " Error Handling" icon = " shield" >
379380 ``` python
380381 try :
381382 response = self .session.get(... )
@@ -388,10 +389,7 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
388389 ```
389390 </Card >
390391
391- <Card
392- title = " Type Validation"
393- icon = " check"
394- >
392+ <Card title = " Type Validation" icon = " check" >
395393 ``` python
396394 if not isinstance (args, dict ) or " city" not in args:
397395 raise McpError(
@@ -401,20 +399,14 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
401399 ```
402400 </Card >
403401
404- <Card
405- title = " Environment Variables"
406- icon = " gear"
407- >
402+ <Card title = " Environment Variables" icon = " gear" >
408403 ``` python
409404 if not API_KEY :
410405 raise ValueError (" OPENWEATHER_API_KEY is required" )
411406 ```
412407 </Card >
413408
414- <Card
415- title = " Constants"
416- icon = " box"
417- >
409+ <Card title = " Constants" icon = " box" >
418410 ``` python
419411 API_CONFIG = {
420412 " BASE_URL" : " ..." ,
@@ -432,12 +424,14 @@ This guide uses the OpenWeatherMap API. You'll need a free API key from [OpenWea
432424While this guide uses stdio transport, MCP supports multiple transport options:
433425
434426### WebSocket
427+
435428``` python
436429from modelcontextprotocol import WebSocketServerTransport
437430transport = WebSocketServerTransport()
438431```
439432
440433### SSE (Server-Sent Events)
434+
441435``` python
442436from modelcontextprotocol import SSEServerTransport
443437transport = SSEServerTransport(" /events" , response)
@@ -446,6 +440,7 @@ transport = SSEServerTransport("/events", response)
446440## Troubleshooting
447441
448442### Installation issues
443+
449444``` bash
450445# Check Python version
451446python --version
@@ -456,13 +451,15 @@ pip install -r requirements.txt
456451```
457452
458453### Runtime errors
454+
459455``` bash
460456# Enable debug logging
461457export MCP_LOG_LEVEL=DEBUG
462458python weather_server.py
463459```
464460
465461### Type checking
462+
466463``` bash
467464# Install mypy
468465pip install mypy
@@ -493,7 +490,9 @@ mypy weather_server.py
493490
494491 <Step title = " Restart Claude" >
495492 1 . Quit Claude completely
493+
496494 2 . Start Claude again
495+
497496 3 . Look for your weather server in the 🔌 menu
498497 </Step >
499498</Steps >
@@ -503,20 +502,23 @@ mypy weather_server.py
503502<AccordionGroup >
504503 <Accordion title = " Check Current Weather" active >
505504 Ask Claude:
505+
506506 ```
507507 What's the current weather in San Francisco? Can you analyze the conditions and tell me if it's a good day for outdoor activities?
508508 ```
509509 </Accordion >
510510
511511 <Accordion title = " Get a Forecast" >
512512 Ask Claude:
513+
513514 ```
514515 Can you get me a 5-day forecast for Tokyo and help me plan what clothes to pack for my trip?
515516 ```
516517 </Accordion >
517518
518519 <Accordion title = " Compare Weather" >
519520 Ask Claude:
521+
520522 ```
521523 Can you analyze the forecast for both Tokyo and San Francisco and tell me which city would be better for outdoor photography this week?
522524 ```
@@ -692,27 +694,21 @@ mypy weather_server.py
692694## Deployment
693695
694696<CardGroup cols = { 1 } >
695- <Card
696- title = " Docker"
697- icon = " docker"
698- >
697+ <Card title = " Docker" icon = " docker" >
699698 ``` dockerfile
700699 FROM python:3.11-slim
701-
700+
702701 WORKDIR /app
703702 COPY requirements.txt .
704703 RUN pip install -r requirements.txt
705-
704+
706705 COPY . .
707-
706+
708707 CMD ["python" , "weather_server.py" ]
709708 ```
710709 </Card >
711710
712- <Card
713- title = " Systemd Service"
714- icon = " server"
715- >
711+ <Card title = " Systemd Service" icon = " server" >
716712 ``` ini
717713 [Unit]
718714 Description =Weather MCP Server
@@ -732,19 +728,11 @@ mypy weather_server.py
732728## Next steps
733729
734730<CardGroup cols = { 2 } >
735- <Card
736- title = " Architecture overview"
737- icon = " sitemap"
738- href = " /docs/concepts/architecture"
739- >
731+ <Card title = " Architecture overview" icon = " sitemap" href = " /docs/concepts/architecture" >
740732 Learn more about the MCP architecture
741733 </Card >
742734
743- <Card
744- title = " Python SDK"
745- icon = " python"
746- href = " /api-reference/python/class-reference"
747- >
735+ <Card title = " Python SDK" icon = " python" href = " /api-reference/python/class-reference" >
748736 Read more about the Python SDK
749737 </Card >
750738</CardGroup >
0 commit comments