OSS · Python CLI · MCP Server

quake-lens

Earthquakes cannot be predicted. Aftershock rates can be forecast.

Fetch public earthquake catalogs (JMA, P2P, USGS) and compute the statistics behind honest aftershock forecasting: Gutenberg-Richter b-value via Aki’s closed-form MLE, and modified Omori decay via Ogata’s MLE with a pure-Python Nelder-Mead. Zero runtime dependencies. An optional MCP server exposes the same computations to LLM clients as 4 tools.

View on GitHub v0.1.0 release notes

Terminal demo: quake-lens recent fetches live JMA earthquakes, then estimates b = 1.0449 ± 0.1306 from 130 Noto 2024 aftershocks and fits Omori-Utsu decay with p = 0.8861.
Live JMA feed, then the 2024 Noto aftershock sequence: b-value 1.04 ± 0.13 (consistent with the global average of ~1.0) and Omori-Utsu decay p = 0.89. Real data, real outputs.

Four subcommands, four MCP tools

The CLI pipes JSON between steps. The MCP tools run fetch + estimation server-side and return statistics only, so large event arrays never travel through the LLM context.

Command / tool What it does
recent --src p2p|jma Latest quakes from the P2P or JMA feed, normalized to one event schema (sentinel filtering + telegram dedupe included).
catalog USGS FDSN catalog query: time window, minimum magnitude, bounding box. JSON or table output.
bvalue --mc <m> Gutenberg-Richter b-value via Aki’s closed-form MLE, with standard error b/√N.
omori --mainshock <t> Modified Omori fit via Ogata’s MLE: grid search, then Nelder-Mead in log space. Returns K, c, p, logL.
get_recent / get_catalog (MCP) The same fetchers exposed as MCP tools for LLM clients.
estimate_bvalue / fit_omori (MCP) Fetch + estimate server-side; only statistics return to the LLM context.

Install

Runs from a clone with zero dependencies. The optional extra adds the MCP server (SDK 1.x and 2.x both supported).

git clone https://github.com/kenimo49/quake-lens.git
cd quake-lens
python3 -m quake_lens --help     # zero dependencies, runs as-is

# optional: MCP server (mcp SDK 1.x / 2.x)
pip install ".[mcp]"
claude mcp add quake-lens -- quake-lens-mcp

Usage

The full pipeline on the 2024 Noto earthquake, exactly as measured for the write-up:

quake-lens recent --src jma --limit 5

quake-lens catalog --start 2024-01-01 --end 2024-01-11 \
  --min-mag 4.0 --format json > noto.json

quake-lens bvalue noto.json --mc 4.5
# b = 1.0449   se = 0.1306   n_used = 64

quake-lens omori noto.json --mainshock 2024-01-01T07:10:00Z
# K = 23.3856  c = 0.0224  p = 0.8861  n_used = 130

Four traps found while building it

Each of these surfaced by running against real APIs and real SDKs, not from documentation.

  1. USGS cannot see Japan’s small earthquakes

    The global USGS catalog misses most M3-class events in Japan. Set the completeness magnitude Mc below what the catalog actually records and the b-value estimate silently collapses: the same Noto dataset gives b = 1.04 at Mc 4.5 but b = 0.27 at Mc 3.0. More data made the estimate worse. Catalog completeness comes before statistics.

  2. JMA writes very shallow depth as positive zero

    JMA’s list.json encodes hypocenters as ISO 6709-ish strings where depth is a negative altitude in meters. Except very shallow quakes, which arrive as "+0", a positive zero. Negate it naively and you get IEEE 754 -0.0, which renders as "-0.0" in the output table. Found live, fixed by normalizing to positive zero.

  3. P2P marks unknown hypocenters with sentinels, not null

    The P2P quake API reports missing hypocenter data as latitude/longitude -200 and magnitude -1 rather than null. A null check passes and a garbage row "-200.000 -200.000 -1.0" reaches the output. The same feed also delivers up to three telegrams per quake, so dedupe by origin time keeps only the latest detailed report.

  4. mcp SDK 2.0 renamed FastMCP and the CI never noticed

    mcp 2.0.0 removed mcp.server.fastmcp and renamed FastMCP to MCPServer, so a fresh pip install broke the server at import time. CI stayed green because the SDK is an optional dependency and importorskip skipped the whole test file. Optional-dependency code needs a venv with the SDK actually installed; a try/except dual import now covers both major versions.

Related articles

Related developer tools

All products →

← Back to products