Skip to main content
Glama
README.md
# igepn-mcp

Ecuador earthquakes and volcano activity from the **IGEPN** (Instituto Geofísico de la Escuela Politécnica
Nacional) → SQLite (**accumulating**, never pruned) → structured MCP tools.
Source: the IGEPN public Telegram channel, read through its keyless public preview `t.me/s/SismosVolcanesIGEPN`.
Design rationale: [CLAUDE.md](CLAUDE.md).

## Tools
| tool | use |
|---|---|
| `last_quake()` | the most recent quake (revised value if available, plus the preliminary estimate) — *"¿qué fue ese temblor?"* |
| `latest_quakes(hours=24, min_mag?, place?, n=15)` | recent quakes, one per event; `place` is accent-insensitive (`"Manabí"`, `"Quito"`) |
| `volcano_status(volcano?)` | latest surface/internal activity level + trend (all volcanoes reported in the last 30 days, or one) |
| `ig_alerts(hours=48, volcano?, n=10)` | `#IGAlInstante` bulletins (lahars, ash, activity) and special volcano reports, as written |

Times come in Ecuador local time (`occurred_local_ec`, UTC−5) and UTC. Quakes keep IGEPN's `status`
(`PRELIMINAR` / `REVISADO`, older posts `CONFIRMADO`). Every item carries a `post_url` (the Telegram post, with
its image) for the UI to show.

## Run
```bash
uv sync
uv run igepn-mcp poll                        # fetch new posts once (watermark-incremental; run every ~3 min)
uv run igepn-mcp backfill --pages 50         # walk history backwards, ~20 posts/page, resumable (see below)
uv run igepn-mcp reparse                     # rebuild parsed tables from the raw log after a parser change
uv run igepn-mcp serve                       # stdio (Claude Desktop / dev)
IGEPN_MCP_TOKEN=secret uv run igepn-mcp serve --transport http --host 0.0.0.0 --port 8000   # streamable-http at /mcp
uv run pytest
```

| env | default | |
|---|---|---|
| `IGEPN_DB` | `data/igepn.db` | SQLite path (WAL; poller and server can share it) |
| `IGEPN_POLL_MINUTES` | `0` (off) | >0: `serve` also polls in the background (no timer needed); `3` recommended |
| `IGEPN_MCP_TOKEN` | unset | bearer token required on HTTP (`/healthz` stays open) |
| `IGEPN_CHANNEL` | `SismosVolcanesIGEPN` | Telegram channel |
| `IGEPN_MAX_CATCHUP_PAGES` | `25` | pages one poll may walk back to reach the watermark after downtime |
| `IGEPN_USER_AGENT`, `IGEPN_FETCH_TIMEOUT` | honest UA, `20` | |

### Storage
`posts_raw` is the append-only record of every kept post (procurement notices are dropped). `quakes` keeps
**every** report (preliminary and revised) and the view `v_quake_current` gives the latest per event (the
revised one wins). `volcano_reports` covers daily, weekly and monthly reports, and `alerts` holds the free-text
bulletins. The parsed tables are derived from `posts_raw`, so `reparse` can rebuild them at any time.

### History
The preview pages back to the channel's first post (2019), so `backfill` can recover the full archive through
the same keyless route, about 620 pages. Its default of 3 s between pages keeps it polite. It is resumable, so
it can run in chunks (`--pages 100` at a time). The parser handles all three post formats the channel has used
(2019, 2021, 2023+).

## Claude Desktop
`%APPDATA%\Claude\claude_desktop_config.json`:
```json
{
  "mcpServers": {
    "igepn": {
      "command": "uv",
      "args": ["--directory", "C:\\Code\\igepn-mcp", "run", "igepn-mcp", "serve"],
      "env": { "IGEPN_DB": "C:\\Code\\igepn-mcp\\data\\igepn.db", "IGEPN_POLL_MINUTES": "3" }
    }
  }
}
```

## Docker Compose (e.g. mcpo → Open WebUI)
Build the image with `docker build -t igepn-mcp .`. It serves HTTP on :8000 at `/mcp`, and the healthcheck uses
the open `/healthz` endpoint.
```yaml
services:
  igepn-mcp:
    image: igepn-mcp:latest
    restart: unless-stopped
    environment:
      IGEPN_MCP_TOKEN: ${IGEPN_MCP_TOKEN}    # put it in .env; clients send "Authorization: Bearer <token>"
      IGEPN_POLL_MINUTES: "3"                # poll at startup, then every 3 min (no timer needed)
      IGEPN_USER_AGENT: "igepn-mcp/0.1 (+https://example.org/your-contact)"   # identify your deployment
    volumes:
      - igepn-data:/data                     # SQLite; local disk, not NFS/SMB. Accumulates - back it up.
volumes:
  igepn-data:
```
One-time history backfill into the same volume: `docker compose run --rm igepn-mcp backfill --pages 700`.

mcpo entry (from a container on the same network):
```json
{ "mcpServers": { "igepn": { "type": "streamable-http", "url": "http://igepn-mcp:8000/mcp",
  "headers": { "Authorization": "Bearer ${IGEPN_MCP_TOKEN}" } } } }
```

## AI assistance
igepn-mcp is developed openly with the help of Claude (Anthropic). We state this plainly: commits
Claude helped write carry a `Co-Authored-By: Claude` trailer. The code and design are open source so the
work can be inspected, reused, and given back.

## License
Code: [MPL-2.0](LICENSE). The earthquake and volcano reports belong to the **IGEPN**
([igepn.edu.ec](https://www.igepn.edu.ec)); they are fetched from its public channel and stay in your local
database. Attribute them to the IGEPN, keep polling polite (≥3 min), and set `IGEPN_USER_AGENT` to identify
your own deployment. For official information and emergencies, follow the IGEPN and Ecuador's risk-management
authorities directly.

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: last_quake fetches a single most-recent event, latest_quakes lists events with filters, volcano_status provides activity reports, and ig_alerts delivers bulletins. The descriptions explicitly differentiate use cases, leaving no ambiguity.

Naming Consistency4/5

All names use snake_case consistently, but the structural patterns vary (adjective_noun, noun_noun, abbreviation_noun). This minor deviation from a uniform pattern prevents a perfect score.

Tool Count5/5

Four tools are well-scoped for a focused monitoring server, covering core needs of recent earthquakes, volcano status, and alerts without redundancy. Each tool earns its place.

Completeness4/5

The surface covers the main earthquake and volcano information needs, but lacks detailed historical querying beyond hourly windows or event-specific lookups. These minor gaps are workable with existing filters.

Maintenance

ActivityMaintained
ResponsivenessNo issues