Metadata-Version: 2.4
Name: irm-kmi-mcp
Version: 1.0.1
Summary: MCP server exposing official Belgian weather data (IRM/KMI): current conditions, forecasts and warnings.
Author: kthys
License-Expression: MIT
Keywords: mcp,weather,belgium,irm,kmi,meteo,forecast,warnings
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastmcp>=2.0
Requires-Dist: httpx>=0.27.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Dynamic: license-file

# irm-kmi-mcp

[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/)

An [MCP](https://modelcontextprotocol.io) server exposing **official Belgian weather data** from the
[Royal Meteorological Institute of Belgium](https://www.meteo.be) (IRM/KMI): observed conditions,
daily and hourly forecasts, and weather warnings, for MCP clients such as Claude, Hermes or
Openclaw.

```text
"What's the weather in Namur?"            →  current_conditions("Namur")
"Forecast for Oostende, 5 days, in Dutch" →  daily_forecast("Oostende", days=5, language="nl")
"Any warnings in Belgium right now?"      →  warnings()
```

## Features

- **Observed conditions**: temperature, condition, UV index, sunrise/sunset from the nearest
  IRM weather station.
- **Daily forecast (1–8 days)**: min/max temperature, condition, wind, precipitation, plus the
  **official IRM text bulletin** in fr/nl/en/de.
- **Hourly forecast (1–49 h)**: temperature, precipitation, pressure, wind and gusts.
- **Official weather warnings**: yellow/orange/red alerts, either for a single municipality
  (with level and validity period) or for the whole country.
- **Municipality resolution by name**: "Namur", "Bruxelles", "Oostende", … resolved through the
  IRM's own city search.
- **Caching**: weather data is cached for 10 minutes, city lookups for 24 hours.

## Tools

| Tool                  | Parameters                                       | Returns |
|-----------------------|--------------------------------------------------|---------|
| `current_conditions`  | `commune`                                        | temperature, condition (ww code + canonical English label), UV index, day/night, sunrise/sunset |
| `daily_forecast`      | `commune`, `days` (1–8, default 3), `language` (fr/nl/en/de) | per day: temps, condition (ww code + label), wind, precipitation, official text |
| `hourly_forecast`     | `commune`, `hours` (1–49, default 24)             | per hour: temperature, condition (ww code + label), precipitation, pressure, wind |
| `warnings`            | `commune` (optional), `language`                 | alert type, text; level + validity for a municipality, per-region level/validity otherwise |

## Data source & disclaimer

> ⚠️ **Unofficial.** This project is not affiliated with the IRM/KMI. It works by calling the
> same backend service that powers the official IRM mobile app. That service was never meant for
> public use: it is undocumented and it can break or disappear without notice. Please use it for **personal,
> low-frequency** purposes only.

The API surface was reverse-engineered and documented by
[Jules Dejaeghere](https://github.com/jdejaegh) in
[`jdejaegh/irm-kmi-api`](https://github.com/jdejaegh/irm-kmi-api) and
[`jdejaegh/irm-kmi-ha`](https://github.com/jdejaegh/irm-kmi-ha). Many thanks for the groundwork.
This project is **not affiliated with, sponsored or endorsed by the IRM/KMI**.

## Installation

From [PyPI](https://pypi.org/project/irm-kmi-mcp/):

```bash
pip install irm-kmi-mcp
```

…or run it zero-install on every invocation with
[`uvx`](https://docs.astral.sh/uv/guides/tools/) (recommended for MCP clients —
no venv to manage):

```bash
uvx irm-kmi-mcp
```

See [Development](#development) below for installing from source.

## Usage

Run the server (stdio transport):

```bash
irm-kmi-mcp
# or
python -m irm_kmi_mcp
```

### Claude Desktop

Zero-install with `uvx` (recommended):

```json
{
  "mcpServers": {
    "irm-kmi-mcp": {
      "command": "uvx",
      "args": ["irm-kmi-mcp"]
    }
  }
}
```

Or, after `pip install irm-kmi-mcp`:

```json
{
  "mcpServers": {
    "irm-kmi-mcp": {
      "command": "irm-kmi-mcp"
    }
  }
}
```

To set a default language (see [Configuration](#configuration)), add an `"env"`
key to either form, e.g. `"env": { "IRM_LANG": "fr" }`.

### Hermes Agent

After `pip install irm-kmi-mcp` (so the `irm-kmi-mcp` command is on `PATH`):

```yaml
# config.yaml
mcp_servers:
  irm-kmi-mcp:
    command: "irm-kmi-mcp"
    enabled: true
    # env:
    #   IRM_LANG: "fr"  # optional: default language for official texts
```

No API keys or configuration required. The daily request key is derived automatically.

## Configuration

- `IRM_LANG`: default language for official texts (bulletins, warning texts,
  day names, wind directions): `fr`, `nl`, `en` or `de`. Unset or invalid
  values fall back to English. Read once at server startup; set it before
  launching the server.

## Development

Install from source in an editable dev environment:

```bash
git clone https://github.com/kthys/irm-kmi-mcp.git
cd irm-kmi-mcp
python3 -m venv .venv
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest
.venv/bin/ruff check .
```

Tests run against recorded API responses (`tests/fixtures/`) with a mocked HTTP transport,
so no network access is required. Re-record fixtures after upstream API changes.
