npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

geohazard-mcp

v0.1.2

Published

MCP server aggregating real-time environmental and natural-hazard data from 12 public sources into a unified risk assessment.

Readme

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.