QuakeScope
by NoelVFX
README.md
# QuakeScope — Earthquake Activity Explorer for Athena
An [Athena AI Agent SDK](https://athenachat.bot/docs) app that lets you explore recent
earthquakes by **magnitude, depth, place and time range**, rendered as an interactive
world map inside the Athena chat.
- **Data source:** [USGS Earthquake Hazards Program](https://earthquake.usgs.gov/fdsnws/event/1/)
FDSN event API (live, public, no key required).
- **Protocol:** Model Context Protocol over Streamable HTTP.
- **UI:** a `text/html+skybridge` widget resource driven by `window.openai`.
## MCP endpoint
```
https://<your-deployment>.vercel.app/mcp
```
## Tools
| Tool | Purpose |
| --- | --- |
| `search_earthquakes` | Query the live USGS feed by `time_window` (`hour`/`day`/`week`/`month`) or explicit `start_time`/`end_time`, `min_magnitude`, `max_magnitude`, `min_depth_km`, `max_depth_km`, named `region`, `place_contains` and `limit`. Returns structured stats plus the event list, and renders the interactive map. |
| `get_earthquake_details` | Full USGS record for one event id — felt reports, PAGER alert, tsunami flag, official event page. |
| `assess_earthquake_impact` | Impact and recovery assessment for one event, for government damage assessment and reconstruction budgeting. Renders the impact widget. |
### Official vs. derived — read this before using the impact tool
`assess_earthquake_impact` returns two deliberately separated objects.
**`official`** is [USGS PAGER](https://earthquake.usgs.gov/data/pager/) — real, published,
citable. Estimated direct economic loss (USD), estimated fatalities, alert level, the full
loss probability distribution, population exposure by shaking intensity (MMI), a per-country
breakdown, and USGS's own narrative comments. Nothing here is computed by this server.
**`reconstruction_scenario`** is **derived, and clearly labelled as such**. USGS does not
publish reconstruction cost or rebuild duration — no authoritative source does — so this is
transparent parametric sizing built on top of the official loss figure, following the
damage→needs convention used in World Bank / GFDRR post-disaster needs assessments:
reconstruction need = direct damage × build-back-better multiplier, with duration taken from
a severity-tier band driven by population exposed to damaging shaking. Every coefficient is
returned in `assumptions` and is caller-overridable; outputs are ranges, never point forecasts.
It is planning arithmetic to scope a response. It does not replace a field-based PDNA, it
excludes tsunami, landslide and liquefaction damage (PAGER is shaking-only), and it excludes
indirect losses such as lost output and trade disruption. The widget renders the two layers in
visually distinct sections so they cannot be confused, and the tool description instructs the
model to state which figures are which.
`search_earthquakes` is marked `openai/widgetAccessible`, so the widget itself can
re-invoke it — changing the time range in the UI is a real MCP round trip, not a
client-side filter.
## Widget interactions
1. **Magnitude slider** — drag to raise the M threshold; map, list and summary stats
recompute live.
2. **Depth-band chips** — toggle shallow (<70 km) / intermediate (70–300 km) /
deep (>300 km); markers are colour-coded by band.
3. **Linked selection** — click a marker on the map *or* a row in the list; the two
stay in sync and a detail card shows time, depth, coordinates, felt reports,
significance and a link to the USGS event page.
4. **Sort** — reorder the event list by recency, magnitude or depth.
5. **Time-range switch (1h / 24h / 7d / 30d)** — calls `search_earthquakes` again
through `window.openai.callTool` and re-renders from fresh USGS data.
The impact widget adds its own: **tabbed official breakdowns** (shaking exposure, per-country,
loss probability, USGS notes), a **build-back-better multiplier slider**, and a
**recovery-pace selector** — the last two recompute the reconstruction need, annual funding
requirement and phased budget live.
UI state is persisted with `window.openai.setWidgetState`, so filters and the selected
event survive re-renders.
## Layout
```
api/mcp.js Vercel serverless entry (stateless Streamable HTTP)
server.js Local dev server -> http://localhost:8787/mcp
src/quake-server.js MCP server: resource + tool definitions, USGS client
src/widget-html.js GENERATED widget bundle (do not edit)
public/quake-widget.html Map widget source (HTML + CSS + JS)
public/impact-widget.html Impact assessment widget source
src/impact.js PAGER client + derived reconstruction model
public/land-path.txt World coastline as an equirectangular SVG path
scripts/build-widget.cjs Inlines the map into the widget -> src/widget-html.js
```
## Develop
```bash
npm install
npm run build:widget # after editing public/quake-widget.html
npm start # http://localhost:8787/mcp
npx @modelcontextprotocol/inspector@latest --server-url http://localhost:8787/mcp --transport http
```
Expose it with `ngrok http 8787` and point the Athena agent at
`https://<subdomain>.ngrok.app/mcp`.
## Deploy
Any Node host works. On Vercel, `vercel.json` rewrites `/mcp` to the
`api/mcp.js` function; the transport is stateless
(`sessionIdGenerator: undefined`, `enableJsonResponse: true`) as serverless requires.
## Attribution
Earthquake data courtesy of the U.S. Geological Survey. Coastlines from
[world-atlas](https://github.com/topojson/world-atlas) (Natural Earth, public domain).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues