infoclimat-mcp
by cmer81
README.md
# infoclimat-mcp
A [FastMCP](https://github.com/jlowin/fastmcp) server that exposes [Infoclimat](https://www.infoclimat.fr/) weather data via the Model Context Protocol (MCP). The server proxies requests to the Infoclimat API, injecting your API token server-side so clients never see it.
## Tools
| Tool | Description |
|------|-------------|
| `list_stations` | List stations with optional filters (département, pays, genre, active_only) |
| `search_stations` | Search stations by name or département — use this to resolve a place name to station IDs |
| `find_nearest_stations` | Find stations within a radius of a lat/lon point |
| `get_observations` | Observations for one or more stations over a date range — raw (~10 min resolution) or aggregated daily (`aggregate="daily"`) |
| `get_latest` | Latest observation for each requested station |
| `get_precipitation_summary` | Precipitation totals over a period, with lat/lon for mapping |
## Installation
### With uv (recommended)
```bash
git clone <repo>
cd infoclimat-mcp
uv sync
```
### With pip
```bash
pip install fastmcp httpx cachetools python-dotenv
```
## Configuration
Copy `.env.example` to `.env` and fill in your token:
```bash
cp .env.example .env
```
```env
INFOCLIMAT_TOKEN=your_token_here
MCP_HOST=0.0.0.0 # optional, default 0.0.0.0
MCP_PORT=8000 # optional, default 8000
```
Get a token at [infoclimat.fr](https://www.infoclimat.fr/).
## Running
```bash
uv run python main.py
```
The server starts an SSE endpoint at `http://0.0.0.0:8000/sse`.
## Docker
The image is published automatically to GitHub Container Registry on every push to `master` and on version tags.
```bash
docker pull ghcr.io/cmer81/infoclimat-mcp:latest
```
Run the server:
```bash
docker run -d \
-e INFOCLIMAT_TOKEN=your_token_here \
-p 8000:8000 \
ghcr.io/cmer81/infoclimat-mcp:latest
```
Optional environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `INFOCLIMAT_TOKEN` | *(required)* | Your Infoclimat API token |
| `MCP_HOST` | `0.0.0.0` | Host to bind |
| `MCP_PORT` | `8000` | Port to listen on |
The SSE endpoint is available at `http://localhost:8000/sse`.
> **Note:** Never pass `INFOCLIMAT_TOKEN` as a build argument — always supply it at runtime via `-e`.
## MCP Client Configuration
> The Docker image exposes the same SSE endpoint (`/sse`) on port 8000. The configuration below applies whether you're running the server directly or via Docker.
### Claude Desktop (remote server via SSE)
> **Note:** Claude Desktop natively uses stdio for *local* MCP servers. The config below assumes the server is deployed remotely (e.g., behind a reverse proxy with TLS).
```json
{
"mcpServers": {
"infoclimat": {
"transport": "sse",
"url": "https://your-server.example.com/sse"
}
}
}
```
### Generic HTTP/SSE MCP client
```
SSE endpoint: https://your-server.example.com/sse
```
## Reverse proxy (TLS)
Example Caddyfile for TLS termination:
```
your-server.example.com {
reverse_proxy localhost:8000
}
```
## Daily Aggregation
`get_observations` accepts an optional `aggregate` parameter:
| Value | Behaviour |
|-------|-----------|
| `"raw"` (default) | Returns all raw ~10-minute observations |
| `"daily"` | Returns compact per-day statistics — suitable for injecting into LLM context |
Example daily response per station:
```json
{
"STATIC0183": {
"station_name": "Sainte-Radegonde",
"period": { "start": "2026-03-01", "end": "2026-03-21" },
"daily": [
{
"date": "2026-03-01",
"temp_min": 2.2,
"temp_mean": 6.9,
"temp_max": 13.8,
"humidity_mean": 79.0,
"wind_mean_kmh": 7.2,
"wind_gust_max_kmh": 63.7,
"pressure_mean": 1023.8,
"precip_mm": 0.0
}
],
"summary": {
"temp_min_abs": -4.1,
"temp_max_abs": 21.4,
"temp_mean": 8.2,
"precip_total_mm": 29.8,
"days_count": 21
}
}
}
```
Fields with all-null source values are omitted. `precip_mm` is the last `pluie_cumul_0h` value of the day (cumul since midnight).
## Caching
- Station list: cached 1 hour in memory
- Observations: cached 10 minutes per (stations, start, end) key
- Cache is lost on server restart
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues