Open-Meteo MCP Server
Overview
The Open-Meteo MCP Server is a Python project that demonstrates how to build a Model Context Protocol (MCP) server that interfaces with an external service instead of implementing a traditional CRUD application.
The server exposes weather-related functionality as MCP tools that AI assistants can discover and invoke.
It uses the public Open-Meteo API to retrieve weather information for cities around the world.
Features
The server currently exposes the following MCP tools:
| Tool | Description |
|---|---|
search_city |
Search for a city and retrieve its location information |
get_weather |
Retrieve the current weather for a city |
get_weather_forecast |
Retrieve a multi-day weather forecast |
compare_weather |
Compare the current weather between two cities |
find_warmest_day |
Find the warmest forecast day within a given period |
Architecture
AI Assistant
│
│
MCP Protocol
│
▼
Open-Meteo MCP Server
│
▼
weather_client.py
│
HTTP REST Requests
│
▼
Open-Meteo Public API
Project Structure
open-meteo-mcp/
├── main.py
├── weather_client.py
├── weather_models.py
├── errors.py
├── tests/
│ ├── __init__.py
│ ├── test_weather_client.py
│ └── test_tools.py
├── .python-version
├── .gitignore
├── pyproject.toml
├── uv.lock
└── README.md
Technologies
- Python 3.14
- Model Context Protocol
- Open-Meteo API
- httpx
- Pydantic
- pytest
- pytest-asyncio
- respx
- uv
Installation
1. Clone the repository
git clone <repository-url>
cd open-meteo-mcp
Replace <repository-url> with the URL of your Git repository.
2. Install uv
If uv is not already installed:
curl -LsSf https://astral.sh/uv/install.sh | sh
3. Install the project dependencies
uv sync
The command creates the virtual environment and installs the dependencies from pyproject.toml and uv.lock.
4. Activate the virtual environment
On macOS or Linux:
source .venv/bin/activate
5. Verify the Python version
python --version
Expected output:
Python 3.14.x
Running the Project
Launch the MCP development server with MCP Inspector:
uv run mcp dev main.py
The Inspector lets you:
- View the available MCP tools
- Examine tool input schemas
- Execute tools manually
- Inspect tool results
- Debug errors
To run the server directly:
uv run python main.py
Available MCP Tools
search_city
Searches for a city and returns its location details.
Input
{
"city": "Tunis"
}
Example output
{
"name": "Tunis",
"country": "Tunisia",
"latitude": 36.8065,
"longitude": 10.1815,
"timezone": "Africa/Tunis"
}
get_weather
Retrieves the current weather for a city.
Input
{
"city": "Munich"
}
Example output
{
"city": "Munich",
"country": "Germany",
"temperature": 22.4,
"temperature_unit": "°C",
"apparent_temperature": 21.8,
"wind_speed": 10.2,
"wind_speed_unit": "km/h",
"weather_code": 1,
"timezone": "Europe/Berlin"
}
The actual values depend on the current weather.
get_weather_forecast
Retrieves a multi-day weather forecast.
The days value must be between 1 and 7.
Input
{
"city": "Paris",
"days": 5
}
Example output
{
"city": "Paris",
"days": [
{
"date": "2026-08-02",
"maximum_temperature": 25.1,
"minimum_temperature": 16.4,
"precipitation_probability": 20
}
]
}
compare_weather
Compares the current temperatures of two cities.
Input
{
"first_city": "Tunis",
"second_city": "Munich"
}
Returns
- Current weather for both cities
- The warmer city
- Whether both cities have the same temperature
- The temperature difference
find_warmest_day
Finds the day with the highest forecast temperature.
The days value must be between 1 and 7.
Input
{
"city": "Rome",
"days": 7
}
Example output
{
"city": "Rome",
"warmest_day": {
"date": "2026-08-05",
"maximum_temperature": 31.5,
"minimum_temperature": 21.2,
"precipitation_probability": 5
}
}
Error Handling
Error handling is centralized in errors.py.
The project returns consistent error responses for:
- Empty city names
- Invalid forecast periods
- Unknown cities
- Network failures
- Request timeouts
- HTTP errors
- Unexpected application errors
Example:
{
"error": "City name cannot be empty."
}
Running Tests
Run all tests:
uv run pytest -v
Run a specific test file:
uv run pytest tests/test_tools.py -v
Verify all Python files compile:
uv run python -m py_compile \
main.py \
weather_client.py \
weather_models.py \
errors.py
Testing Strategy
The project includes:
- Input-validation tests
- MCP tool tests
- Weather-client tests
- Mocked HTTP responses using
respx - Tests for cities that cannot be found
External API calls are mocked during automated testing, making the test suite faster and more reliable.
Application Flow
User asks an AI assistant a weather question
│
▼
The AI assistant selects an MCP tool
│
▼
The MCP server validates the arguments
│
▼
weather_client.py calls Open-Meteo
│
▼
The response is validated with Pydantic
│
▼
Structured data is returned to the AI assistant
Why MCP Instead of CRUD?
A traditional CRUD application mainly manages records:
Create
Read
Update
Delete
This project follows a different pattern:
AI request
↓
MCP tool selection
↓
External service integration
↓
Structured result
The application does not maintain its own weather database. It provides an AI-friendly interface to an existing external service.
Future Improvements
Potential enhancements include:
- Air-quality information
- Weather alerts
- Sunrise and sunset times
- Historical weather data
- Response caching
- Rate limiting
- Structured logging
- Additional unit tests
- Docker support
- GitHub Actions CI
- GitHub MCP integration
- Gitea MCP integration
- PostgreSQL MCP integration
Learning Outcomes
This project demonstrates:
- Building an MCP server
- Exposing Python functions as MCP tools
- Integrating an external REST API
- Using asynchronous Python with
httpx - Validating external data with Pydantic
- Separating MCP tools from API-client logic
- Centralizing application error handling
- Mocking HTTP requests in tests
- Designing AI tools instead of CRUD endpoints
License
This project is intended for educational and portfolio purposes.