MCP Weather Server
by dolgova
README.md
# MCP Weather Server
Minimal MCP server that exposes weather data via tools using the [Open-Meteo](https://open-meteo.com/) API (no API key required).
---
## Architecture
The project has three parts: a **client** (Cursor or the Python test client), the **MCP server** (this repo), and the **Open-Meteo API**. The client and server talk over **stdio** (stdin/stdout); the server talks to the API over **HTTPS**.
```mermaid
flowchart LR
subgraph local [Your machine]
Client[MCP Client]
Server[MCP Server]
end
API[Open-Meteo API]
Client <-->|"stdio (JSON-RPC)"| Server
Server -->|"HTTPS GET"| API
```
**How client and server communicate:**
1. The client starts the server as a **subprocess** and connects to it via **stdio** (standard input/output).
2. Messages are **JSON-RPC** over stdio: the client sends requests (e.g. "list tools", "call tool X with args Y"); the server responds with results.
3. When a tool is called, the server runs the tool logic (e.g. `get_current_weather`), which may call the Open-Meteo API; the server then sends the tool result back to the client over stdio.
```mermaid
sequenceDiagram
participant Client as MCP Client
participant Server as MCP Server
participant API as Open-Meteo API
Client->>Server: Initialize (stdio)
Server-->>Client: Ready
Client->>Server: ListTools
Server-->>Client: get_current_weather, get_forecast
Client->>Server: CallTool get_current_weather(5.98, 80.43)
Server->>API: GET forecast?latitude=5.98&longitude=80.43
API-->>Server: JSON weather data
Server-->>Client: "Temperature: ...°C, Humidity: ...%..."
```
**Summary:**
| Component | Role |
|-----------|------|
| **MCP Client** | Starts the server process, sends JSON-RPC over stdin, reads responses from stdout. Can be Cursor, the Python `client.py`, or MCP Inspector. |
| **MCP Server** | Runs as a subprocess. Listens on stdin for requests, executes tools (calling `weather.get_weather`), returns results on stdout. |
| **Open-Meteo API** | External HTTP API. The server calls it when a weather tool is invoked; the client never talks to it directly. |
---
## Setup
**Windows (PowerShell):**
```bash
python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt
```
**Linux / WSL:**
```bash
# If venv fails, install first: sudo apt install python3.10-venv
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
If you cannot create a venv (e.g. WSL without `python3-venv`), install into your user site-packages and use `python3`:
```bash
pip install --user -r requirements.txt
```
---
## Run the server (for Cursor / other MCP hosts)
```bash
python server.py
# or on Linux/WSL: python3 server.py
```
The server uses **stdio** transport: it reads from stdin and writes to stdout. Cursor (or another MCP host) starts this process and talks to it over those streams.
---
## How to use the Python client
The **client** (`client.py`) is a small script that connects to the MCP server via stdio and calls the weather tools. Use it to verify that the server works without Cursor.
**Steps:**
1. **From the project directory**, with dependencies installed (see Setup):
**Windows:**
```bash
python client.py
```
**Linux / WSL:**
```bash
python3 client.py
```
2. **What the client does:**
- Starts `server.py` as a subprocess.
- Connects to it over stdio (stdin/stdout).
- Sends **ListTools** and prints the tool names.
- Calls **get_current_weather(5.98, 80.43)** (Weligama, Sri Lanka) and prints the result.
- Calls **get_forecast(5.98, 80.43, days=3)** (Weligama, 3 days) and prints the result.
3. **Example output (Weligama, Sri Lanka):**
```
Tools: ['get_current_weather', 'get_forecast']
--- Weligama, Sri Lanka — current weather ---
Temperature: 28.5°C, Humidity: 75%, Wind: 5.2 km/h, Weather code: 1
--- Weligama, Sri Lanka — 3-day forecast ---
Temperature: 28.5°C, Humidity: 75%, Wind: 5.2 km/h, Weather code: 1
2026-02-08: max 29.1°C, min 25.2°C
2026-02-09: max 29.5°C, min 25.8°C
2026-02-10: max 29.2°C, min 25.5°C
```
You do **not** need to run `server.py` in another terminal; the client starts it automatically.
---
## Cursor MCP config
Add the server to Cursor so the editor can call the weather tools (e.g. from chat).
**Settings → MCP** (or edit `~/.cursor/mcp.json`):
```json
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["C:\\Users\\dolgo\\Desktop\\ai_projects\\mcp_server\\server.py"]
}
}
}
```
**WSL:** use `python3` and the Linux path to `server.py`:
```json
"command": "python3",
"args": ["/mnt/c/Users/dolgo/Desktop/ai_projects/mcp_server/server.py"]
```
Optional: use the venv Python so Cursor uses the same environment:
```json
"command": "C:\\Users\\dolgo\\Desktop\\ai_projects\\mcp_server\\.venv\\Scripts\\python.exe",
"args": ["C:\\Users\\dolgo\\Desktop\\ai_projects\\mcp_server\\server.py"]
```
---
## Tools
| Tool | Arguments | Description |
|------|-----------|-------------|
| **get_current_weather** | `latitude`, `longitude` | Current temperature, humidity, wind speed, weather code. |
| **get_forecast** | `latitude`, `longitude`, `days` (1–7) | Current conditions plus daily min/max for the next `days` days. |
| **get_model_forecast** | `latitude`, `longitude` | Next-day max temperature from the trained ML model (requires training first). |
Example: “What’s the weather in Weligama?” → use latitude **5.98**, longitude **80.43** (Weligama, Sri Lanka).
---
## ML predictive model (next-day max temperature)
A small **Random Forest** model predicts **tomorrow's max temperature** from today's daily weather (max/min temp, humidity, wind, day of year). It is trained on historical data from Open-Meteo and exposed as the **get_model_forecast** MCP tool.
### One-time setup: fetch data and train
1. **Fetch historical daily weather** (e.g. Weligama, 2022–today):
```bash
python scripts/fetch_history.py
# optional: --lat 5.98 --lon 80.43 --start 2022-01-01 --end 2025-02-06
```
Output: `data/weligama_history.csv`.
2. **Train the model:**
```bash
python scripts/train.py
# optional: --data data/weligama_history.csv --out model/model.joblib
```
Output: `model/model.joblib` (and MAE in °C on a held-out set).
3. **Use the tool:** After training, **get_model_forecast(latitude, longitude)** uses today's conditions (from the forecast API) and the trained model to return a predicted tomorrow max temperature.
### Flow
- **Training:** `scripts/fetch_history.py` → historical daily data → `scripts/train.py` → `model/model.joblib`.
- **Inference:** MCP tool **get_model_forecast** calls the forecast API for today's daily values, builds the feature vector, runs the model, returns e.g. `"Model predicts tomorrow's max temperature: 29.2°C"`.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues