Skip to content

PMFrancisco/geohazard-mcp

Repository files navigation

Geohazard MCP

An open-source MCP server that aggregates real-time environmental and natural-hazard data from 12 public sources into a unified risk assessment. Point any MCP-compatible client (Claude Desktop, Cursor, your own agent) at the server and query planetary conditions by coordinate.

Data Sources

Source Layer
Open-Meteo Weather (temperature, wind, precipitation, UV)
Open-Meteo AQ Air quality forecasts (PM2.5, PM10, O3, NO2)
OpenAQ Physical air quality station measurements
USGS Earthquake Seismic events — 7-day lookback with Omori decay
NASA FIRMS Fire hotspots (density + nearest proximity, VIIRS confidence-filtered)
GloFAS (Copernicus) Flood discharge forecasts
NOAA NWS Severe weather alerts (US / PR / VI / Guam only)
NOAA SWPC Space weather (Kp index, geomagnetic storms)
NOAA Tsunami Active tsunami warnings
Smithsonian GVP Volcanic activity with alert-level × proximity scoring
CMEMS (Copernicus) Marine conditions (SST, wave height, currents)
GDACS Global disaster alerts — contributes cyclone score to the weather layer

All sources are free/public. NASA FIRMS and OpenAQ need API keys (free to register) — without them those layers are skipped. OpenAQ and Open-Meteo AQ are distance-weighted and blended into a single air quality result with pollutants normalized to the US EPA AQI scale so cross-source comparisons are meaningful.

Each source is wired through a central registry (src/sources/registry.ts) that declares its fetch function, freshness window, applicability predicate, and — where relevant — its risk-scoring hook. Adding a new source is ~3 files.

Risk Scoring

The overall risk score (0–1) is a weighted sum of per-layer scores, with two safeguards:

  • Critical override: if any single layer scores ≥ 0.9, the overall score is at least 0.7 (high). If any layer scores ≥ 0.75, at least 0.5 (moderate). This prevents a catastrophic single-hazard event from being diluted by calm conditions elsewhere.
  • Omori seismic decay: earthquake risk uses a modified Omori model based on actual event time rather than flat exponential decay. Large earthquakes (M6+) maintain elevated risk for days 0–3 reflecting real aftershock patterns.

Layer weights (declared in the registry):

Layer Weight Contributing source(s)
Seismic 0.25 USGS Earthquake
Weather 0.20 Open-Meteo, GDACS (cyclone)
Fire 0.20 NASA FIRMS
Flood 0.15 GloFAS
Air quality 0.10 OpenAQ + Open-Meteo AQ (blended)
Space weather 0.05 NOAA SWPC
Volcanic 0.05 Smithsonian GVP
Level Score
Critical ≥ 0.80
High ≥ 0.60
Moderate ≥ 0.35
Low ≥ 0.15
Minimal < 0.15

Confidence Scoring

Confidence is the fraction of location-applicable sources that returned fresh, ok data:

overall = okCount / applicableCount
  • Applicability: a source is counted only if its scope covers the query location. In practice this only excludes NOAA NWS outside the US/PR/VI/Guam (where api.weather.gov hard-fails with 404). Every other source is global; its own ok signal is trusted.
  • Staleness: a source is counted as failed if its data is older than 2 × freshnessMinutes (freshness windows live in the registry).
  • Shape: ConfidenceScore exposes applicableSources, okSources, failedSources, and notApplicableSources so clients can see exactly which sources contributed.
Level Score
Reliable ≥ 0.80
Partial ≥ 0.60
Limited ≥ 0.40
Estimate < 0.40

Discrepancies

Cross-source disagreements are detected separately and surfaced on AggregatedConditions.discrepancies (and on compare_sources). Discrepancies between sources that are intentionally blended (e.g. OpenAQ vs Open-Meteo AQ) are tagged expected: true and don't influence downstream interpretation. Discrepancies no longer penalise the confidence score — they stand on their own for UI-level auditing.

MCP Tools

Tool Description
get_conditions Real-time environmental conditions at a coordinate
get_alerts Active natural-hazard alerts nearby (seismic, fire, severe weather, tsunami, cyclones)
get_risk_assessment Overall risk score and per-layer breakdown
get_forecast Multi-hazard forecast with per-day risk and confidence (up to 16 days)
compare_sources Raw per-source data plus detected discrepancies for auditing

Quick Start

Use with Claude Desktop / Cursor

Add to your MCP client config:

{
  "mcpServers": {
    "geohazard": {
      "command": "npx",
      "args": ["-y", "geohazard-mcp"],
      "env": {
        "NASA_FIRMS_KEY": "your-key-here",
        "OPENAQ_API_KEY": "your-key-here"
      }
    }
  }
}

Windows: use "command": "npx.cmd" instead of "command": "npx".

API keys are optional — without them those layers are skipped. Register for free: NASA FIRMS · OpenAQ.

Use with Docker

docker compose up

The container starts on port 3000 with HTTP transport. Pass API keys via environment variables in docker-compose.yml or a .env file.

Configuration

Variable Default Description
NASA_FIRMS_KEY NASA FIRMS API key — fire layer skipped if unset
OPENAQ_API_KEY OpenAQ API key — station AQ layer skipped if unset
CACHE_TTL_SECONDS 300 In-memory cache TTL
DEFAULT_RADIUS_KM 500 Default search radius for nearby events (seismic lookback is 7 days)
MCP_PORT 3000 HTTP server port
MCP_TRANSPORT stdio stdio or http
MCP_ALLOWED_ORIGINS Comma-separated CORS origins
LOG_DIR ./logs Directory for discrepancy and request logs
LOG_LEVEL info Log verbosity

Development

Prerequisites

  • Node.js >= 20
  • pnpm >= 10

Setup

git clone https://github.com/PMFrancisco/geohazard-mcp.git
cd geohazard-mcp
pnpm install
cp .env.example .env   # edit to add optional API keys

Run locally

pnpm dev:server        # HTTP transport on :3000
pnpm dev               # Quick smoke test (prints conditions for Madrid)

Code quality

pnpm typecheck    # Type-check without emitting
pnpm lint         # ESLint
pnpm format       # Prettier (write)
pnpm build        # Compile to dist/

Commits follow Conventional Commits enforced by commitlint and husky.

Project Structure

src/
  types/          Shared TypeScript interfaces
  sources/
    registry.ts   Source registry: fetch wiring, freshness, applicability, risk hooks
    http.ts       fetchWithTimeout + sourceError helpers shared by every adapter
    aqi.ts        US EPA AQI computation + unit conversions
    *.ts          One adapter per external data source
  aggregator/
    index.ts      Registry-driven fan-out; merges sources into AggregatedConditions
    riskScore.ts  Per-layer score functions + weighted rollup with critical override
    forecast.ts   Multi-day risk/confidence projection
    compareSources.ts  Cross-source discrepancy detection
  confidence/
    static.ts     okCount / applicableCount, with staleness cutoff
  logger/
    discrepancy.ts  JSONL discrepancy log writer
  server/
    tools/        MCP tool definitions (one file per tool + registry)
    middleware/   CORS, rate limiting, request logging
    http.ts       Express wrapper for HTTP transport
    index.ts      MCP entry point (stdio or HTTP based on MCP_TRANSPORT)
  index.ts        Library export + Madrid smoke test

Testing

pnpm test            # Run the full suite
pnpm test:watch      # Re-run on change
pnpm test:coverage   # HTML coverage report under coverage/

The suite is Vitest + supertest and is organized in three tiers under tests/:

Tier Location What it covers
Unit tests/aggregator/, tests/confidence/ Pure scoring, confidence, discrepancy-detection logic
Adapters tests/sources/ One file per source — global.fetch is stubbed and a fixture asserts normalization of the upstream schema
Server tests/server/ supertest against buildHttpApp with the aggregator mocked, covering routing, Zod validation, middleware, and tool wiring

No live API calls are made. NASA FIRMS and OpenAQ API keys are mocked at the environment level, so the suite runs fully offline.

License

Apache 2.0 — see LICENSE.

About

MCP server that unifies global geohazard data (quakes, storms, volcanoes, wildfires) for AI agents.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages