Skip to main content
Glama
danielvillasrc

ClimaMX MCP

README.md
# ClimaMX MCP

An MCP (Model Context Protocol) server that lets AI assistants answer **Mexico weather questions** using official public data.

Ask something like *“What’s the weather today in Guadalajara, Jalisco?”* and the agent resolves the municipality, fetches the SMN forecast, and replies with real temperatures, sky conditions, and rain probability.

![MCP Test in Cursor](MCPTest1.png)


![MCP Test in Cursor 2](MCPTest2.png)

---

## Why this project

Most weather demos depend on commercial APIs. This one wires together **two Mexican government data sources** behind a clean MCP tool:

| Source | Role |
|--------|------|
| **INEGI** | Resolve municipality / state names → geo IDs |
| **CONAGUA / SMN** | Daily municipal forecast (compressed national dataset) |

The agent never handles gzip payloads or multi‑megabyte JSON. The server does the heavy work and returns a small, structured result.

---

## Features

- **One MCP tool:** `pronosticoCiudad(ciudad, estado?)`
- **Accent‑tolerant lookup** (e.g. `merida` + `Yucatan` → Mérida, Yucatán)
- **Ambiguity handling** — when several municipalities match, returns candidates so the agent can ask the user which state to use
- **Gzip decompression + filtering** of the national SMN feed
- **In‑memory cache** (15 minutes) to avoid re‑downloading ~5 MB on every request
- **No API keys** — public endpoints only

---

## Architecture

```
User → Agent → MCP tool (pronosticoCiudad)
                           │
                           ├─► INEGI  (name → ides / idmun)
                           └─► CONAGUA/SMN method=1 (gzip JSON → filter → today's forecast)
```

**Response statuses the agent understands:**

| Status | Meaning |
|--------|---------|
| `ok` | Forecast returned for that municipality |
| `ambiguo` | Several matches — ask the user for the state |
| `no_encontrado` | No municipality found |
| `error` | Network / unexpected failure |

---

## Project structure

```text
ClimaMX-MCP/
├── server.py          # MCP server + tool registration
├── inegi.py           # Municipality resolution (INEGI)
├── conagua.py         # Forecast download, decompress, filter, cache
├── requirements.txt
└── README.md
```

---

## Requirements

- Python 3.10+
- [Cursor](https://cursor.com) (or any MCP‑compatible client)

---

## Setup

```bash
git clone https://github.com/danielvillasrc/ClimaMX-MCP.git
cd ClimaMX-MCP

python -m venv .venv

# Windows
.venv\Scripts\activate

# macOS / Linux
source .venv/bin/activate

pip install -r requirements.txt
```

---

## Configure in Cursor

Add the server to your MCP config (`~/.cursor/mcp.json` or project `.cursor/mcp.json`):

```json
{
  "mcpServers": {
    "clima-mx-server": {
      "command": "C:\\path\\to\\ClimaMX-MCP\\.venv\\Scripts\\python.exe",
      "args": [
        "C:\\path\\to\\ClimaMX-MCP\\server.py"
      ]
    }
  }
}
```

On macOS / Linux, point `command` at `.venv/bin/python` instead.

Reload MCP (or restart Cursor). You should see the tool **`pronosticoCiudad`**.

---

## Usage examples

In Cursor chat:

- *What's the weather today in Guadalajara, Jalisco?*
- *Clima hoy en Mérida, Yucatán*
- *Weather in Zapopan, Jalisco*

Example successful payload (simplified):

```json
{
  "status": "ok",
  "ides": "14",
  "idmun": "39",
  "municipio": "Guadalajara",
  "estado": "Jalisco",
  "pronostico": [
    {
      "dia": "0",
      "tmax": "30.5",
      "tmin": "13.2",
      "cielo": "Cielo nublado",
      "prob_lluvia": "90",
      "precipitacion_mm": "10.2"
    }
  ]
}
```

---

## Manual smoke tests

With the virtualenv active:

```bash
python inegi.py
python conagua.py
```

These scripts exercise municipality lookup and forecast filtering without starting the MCP server.

---

## Design notes

- SMN `method=1` returns the **full national** daily forecast as gzip. The server decompresses, filters by `ides` / `idmun`, and keeps **today** (`ndia == "0"`).
- INEGI’s name search is accent‑sensitive. When a state is provided, a fallback lists that state’s municipalities and matches with accent‑stripped comparison.
- IDs are compared as **strings** to match SMN’s JSON shape (`"14"`, `"39"`).

---

## Data sources

- [SMN / CONAGUA Web Service](https://smn.conagua.gob.mx/es/web-service-api)
- [INEGI Geoestadística catalog API](https://www.inegi.org.mx/servicios/catalogounico.html)

---

## Limitations

- Forecast coverage is municipal (Mexico), not street‑level.
- First uncached CONAGUA call downloads a multi‑MB payload (then cached for 15 minutes).
- Municipality name ambiguity depends on what INEGI’s search returns for a given query.

---

## License

MIT — feel free to use and adapt.

---

## Author

Built as a portfolio project to practice **MCP servers**, **public API integration**, and **agent‑friendly tool design** with real Mexican open data.