Metadata-Version: 2.4
Name: shearline
Version: 1.1.0
Summary: Analyst-grade US severe-weather tools for AI agents over MCP: warning polygons with IBW tags, SPC outlooks, RAP point environments, MRMS hail/rotation, storm reports, and a composite threat brief.
Keywords: mcp,weather,severe-weather,meteorology,nws,spc,mrms,radar,ai-agents
Author: Backshear LLC
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
Requires-Dist: boto3>=1.43.27
Requires-Dist: cfgrib>=0.9.15.1
Requires-Dist: eccodeslib>=2.47.1.20
Requires-Dist: h5netcdf>=1.8.1
Requires-Dist: h5py>=3.16.0
Requires-Dist: httpx>=0.28.1
Requires-Dist: mcp[cli]>=1.27.2
Requires-Dist: metpy>=1.7.1
Requires-Dist: numpy>=2.4.6
Requires-Dist: pydantic>=2.13.4
Requires-Dist: shapely>=2.1.2
Requires-Dist: xarray>=2026.4.0
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/lostnumber07/shearline
Project-URL: Repository, https://github.com/lostnumber07/shearline
Project-URL: Issues, https://github.com/lostnumber07/shearline/issues
Description-Content-Type: text/markdown

<!-- mcp-name: io.github.lostnumber07/shearline -->

# SHEARLINE

[![PyPI](https://img.shields.io/pypi/v/shearline)](https://pypi.org/project/shearline/)
[![Python](https://img.shields.io/pypi/pyversions/shearline)](https://pypi.org/project/shearline/)
[![CI](https://github.com/lostnumber07/shearline/actions/workflows/ci.yml/badge.svg)](https://github.com/lostnumber07/shearline/actions/workflows/ci.yml)
[![MCP Registry](https://img.shields.io/badge/MCP%20registry-io.github.lostnumber07%2Fshearline-blue)](https://registry.modelcontextprotocol.io/v0.1/servers?search=shearline)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

**The severe-weather analyst your agent doesn't have.** SHEARLINE is a free, MIT-licensed MCP server that gives AI agents analyst-grade US severe-weather tools: live warning polygons with Impact-Based Warning tags, SPC convective outlooks, RAP-derived point environments (CAPE/shear/SRH/STP computed with MetPy), MRMS radar-derived hail and rotation products, ground-truth storm reports, and a composite threat brief that synthesizes all of it. A dozen weather MCPs already wrap the basic forecast API; SHEARLINE deliberately skips everything they do and ships only what requires radar meteorology to expose correctly.

> **Informational only. Not a substitute for official NWS warnings.** Every tool repeats this, because it matters: when weather threatens, follow official warnings from weather.gov and local authorities.

## Tools

| Tool | What it returns |
| --- | --- |
| `get_active_warnings(lat, lon, radius_km=40)` | Active tornado/severe-thunderstorm/flash-flood warning polygons with IBW tags (max hail size, max gust, tornado detection/damage threat), parsed storm motion, expirations, and whether the exact point is inside a polygon. Watches listed separately. |
| `get_spc_outlook(lat, lon, day=1)` | SPC categorical risk (TSTM→HIGH) at the point plus tornado/hail/wind probabilities and significant-severe flags, days 1–3, with interpretation calibrated to the category. |
| `get_point_environment(lat, lon)` | Latest RAP 13-km analysis profile computed with MetPy: MLCAPE/MUCAPE/CINs, LCL, 0–1/0–6 km shear, 0–1/0–3 km SRH, Bunkers motion, effective inflow layer, effective SRH/shear, SCP, and significant-tornado parameter — interpreted like an analyst (pulse vs. cool-season high-shear vs. classic supercell parameter space). |
| `get_environment_trend(lat, lon)` | The anticipatory view: a short RAP forecast series (f00/f01/f03/f06, one consistent cycle) of MLCAPE, 0–6 km shear, 0–1 km SRH, SCP and STP, with an interpretation of the **trajectory** (intensifying / stabilizing / steady) — for "is this getting worse" rather than "what is it now." |
| `get_mrms_severe(lat, lon, radius_km=40)` | MRMS maxima within radius: 60-min MESH (hail, inches and mm), low-level and mid-level rotation tracks (azimuthal shear), VIL, composite reflectivity — each with valid time and distance/bearing of the max. |
| `get_storm_reports(lat, lon, radius_km=80, hours=6)` | Normalized Local Storm Reports: type, magnitude with units, time, location, distance/bearing, remarks. |
| `get_lightning(lat, lon, radius_km=40, minutes=15)` | GOES-East GLM total-lightning activity in the recent window: flash count and rate, nearest strike (distance/bearing/time), and a tiered outdoor-safety interpretation (overhead / within-striking-distance / in-the-area). |
| `get_historical_storm_reports(lat, lon, date, radius_km=80)` | What hail/wind/tornado hit a point on a specific past date (`YYYY-MM-DD`, UTC) — normalized reports with magnitude+units and distance/bearing, for the insurance / ag / forensic use case. Coverage from ~2005; preliminary LSRs, not the final NCEI record. |
| `get_threat_brief(lat, lon)` | The showpiece: runs everything above concurrently and synthesizes a threat level (none/marginal/elevated/significant/extreme) **with stated logic**, hazards ranked, environment summary, nearest storm signature, and a recommended attention window. |
| `get_radar_snapshot(lat, lon)` | Nearest WSR-88D's latest Level 2 volume metadata: VCP (scan strategy), max reflectivity with range/azimuth, coarse echo-top estimate. |

Every tool returns structured JSON with `data` (numeric fields, units stated), `interpretation` (plain-language analyst sentences), `degraded` (which upstream sources failed, if any — partial data instead of errors), and the safety `disclaimer`.

## Example: threat brief during a real outbreak

Real output from 2026-06-10, point inside an active tornado warning in northern Missouri:

```json
{
  "threat_level": "extreme",
  "threat_logic": [
    "Tornado Warning in effect at the point, corroborated by confirmed tornado reports nearby — treat as an immediate life-safety situation.",
    "Severe Thunderstorm Warning at the point tagged 'Considerable' (hail to 1.75\", gusts to 60 mph).",
    "Significant-tornado parameter of 4.0 with storms ongoing — environment strongly supports tornadic supercells.",
    "MRMS MESH of 2.3\" hail within radius in the last hour.",
    "Intense rotation track (azimuthal shear 0.013 /s) nearby in the last hour.",
    "6 tornado report(s) near the point in the report window."
  ],
  "hazards_ranked": [
    {"hazard": "tornado", "level": "extreme"},
    {"hazard": "hail", "level": "extreme"},
    {"hazard": "damaging_wind", "level": "extreme"},
    {"hazard": "flash_flood", "level": "moderate"}
  ],
  "nearest_storm_signature": {
    "signature": "composite reflectivity", "value": "58.5 dBZ",
    "distance_km": 18.0, "direction": "ENE", "valid_utc": "2026-06-10T22:14Z"
  },
  "attention_window": {"window": "now", "until_utc": "2026-06-10T21:00:00-05:00"}
}
```

And the same tool for a quiet coastal Maine point reads as confidently quiet — not as an error: `"threat_level": "none"` with the environment numbers shown so the agent can see *why* it's quiet.

## Install

Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/). No API keys — every data source is public and anonymous. `uvx` downloads and runs the published package in one step; nothing is installed permanently.

**Claude Code:**

```sh
claude mcp add shearline -- uvx shearline
```

**Claude Desktop** (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "shearline": {
      "command": "uvx",
      "args": ["shearline"]
    }
  }
}
```

**Streamable HTTP** (for remote/agent-platform use):

```sh
uvx shearline --http --port 8741
# serves at http://127.0.0.1:8741/mcp
```

The HTTP transport is built to be hosted: it emits one structured JSON log line
per tool call (tool, coarse 1° lat/lon bucket, latency, `degraded` list, cache
hit/miss) and applies a per-client token-bucket rate limit, returning `429` with
`Retry-After` when exceeded. Both are HTTP-only — **stdio behaviour is
unchanged**. Configure via environment variables:

| Env var | Default | Effect |
| --- | --- | --- |
| `SHEARLINE_RATE_RPM` | `60` | sustained requests/minute/client (`0` disables the limit) |
| `SHEARLINE_RATE_BURST` | `30` | token-bucket capacity (max burst) |
| `SHEARLINE_HTTP_LOG` | `1` | set `0` to silence per-request logging |
| `SHEARLINE_LOG_LEVEL` | `INFO` | log level for the `shearline.http` logger |
| `SHEARLINE_UPSTREAM_CONCURRENCY` | `8` | max concurrent upstream fetches (politeness toward NOAA) |

To run the latest unreleased `main` instead of the PyPI release, swap `shearline` for `--from git+https://github.com/lostnumber07/shearline shearline`.

## Why these tools

A forecast API tells you it might rain. None of the questions that matter on a severe weather day — *is this storm rotating, how big is the hail, is the environment loaded for tornadoes, am I inside the polygon* — are answerable from a forecast endpoint. They require the warning's IBW tags, radar-derived products, and a real sounding:

- **Warnings with IBW tags, not just warning text.** A base-tier Severe Thunderstorm Warning and one tagged `DESTRUCTIVE` with 80 mph gusts are different planning problems. SHEARLINE parses the machine-readable tags (max hail size, max gust, tornado detection/damage threat) and the storm-motion vector, and does the point-in-polygon test for you.
- **The environment, computed honestly.** CAPE without shear is a pulse-storm day; shear without CAPE is wind-driven rain. SHEARLINE pulls the current RAP analysis profile and computes the discriminating quantities with MetPy — including the effective inflow layer, effective SRH/shear, SCP, and STP — because high-CAPE/low-shear, low-CAPE/high-shear, and classic supercell parameter spaces produce very different hazards, and the interpretation says which one you're in.
- **MRMS, because warnings lag storms.** MESH tells you what hail a storm has *already* produced; rotation tracks show where mesocyclones have tracked in the last hour — both on a ~2-minute cadence from the national radar mosaic, often ahead of the next warning update.
- **LSRs, because radar isn't ground truth.** Spotter reports confirm what's actually reaching the ground.
- **One brief that reasons across all of it.** The threat level is rule-based with the triggered rules quoted back, so an agent can audit the logic instead of trusting a vibe.

## Data sources (all public, no keys)

- Warnings: [api.weather.gov](https://www.weather.gov/documentation/services-web-api) (NWS)
- Outlooks: [Storm Prediction Center](https://www.spc.noaa.gov/) public GeoJSON
- Point environment: [NOMADS](https://nomads.ncep.noaa.gov/) RAP grib filter, derived with [MetPy](https://unidata.github.io/MetPy/)
- MRMS: [NOAA MRMS on AWS Open Data](https://registry.opendata.aws/noaa-mrms-pds/)
- Storm reports (real-time and historical): [Iowa Environmental Mesonet](https://mesonet.agron.iastate.edu/) LSR service
- NEXRAD Level 2: [Unidata on AWS Open Data](https://registry.opendata.aws/noaa-nexrad/)
- Lightning: [GOES GLM on AWS Open Data](https://registry.opendata.aws/noaa-goes/) (GOES-East GLM-L2-LCFA)

Coverage is **continental US only** — out-of-bounds coordinates are rejected with a clear error. Upstream fetches are cached (warnings 60 s, MRMS 120 s, LSRs 300 s, outlooks/RAP 30 min) and degrade gracefully: if one source is down, you get partial data plus a `degraded` field, never a bare exception.

## Recipes for non-meteorologists

You don't need to know what an STP is to use SHEARLINE. The [`.claude/skills/`](.claude/skills)
directory ships three end-to-end recipes that name the exact tool sequence for a
domain task — drop them into any agent that has SHEARLINE connected:

- **[hail-claim-verification](.claude/skills/hail-claim-verification/SKILL.md)** — did damaging hail occur at this address on this date? (insurance / forensic)
- **[chase-day-briefing](.claude/skills/chase-day-briefing/SKILL.md)** — outlook → environment → trend → warnings → radar, into a go/no-go with a target window (chase / EM)
- **[event-day-lightning-watch](.claude/skills/event-day-lightning-watch/SKILL.md)** — poll lightning proximity and issue suspend/shelter/resume calls by the 30-30 / 10-mile rules (venues / outdoor ops)

## Architecture

SHEARLINE is a thin, layered async server: per-source fetch/parse modules feed a meteorology derivation layer, which feeds a uniform tool layer. Every tool returns the same `{data, interpretation, degraded, disclaimer}` envelope, every upstream call is TTL-cached, and one failing source degrades to partial data instead of an exception. See **[ARCHITECTURE.md](ARCHITECTURE.md)** for the module map, the request lifecycle of `get_threat_brief`, the concurrency model, and the upstream quirks each source module encodes.

## Development

```sh
git clone https://github.com/lostnumber07/shearline && cd shearline
uv sync
uv run pytest          # offline test suite against recorded fixtures
uv run ruff check .
uv run shearline       # stdio
uv run python scripts/smoke.py   # live smoke test, both transports
```

See [ARCHITECTURE.md](ARCHITECTURE.md#adding-a-tool) for how to add a tool or data source.

## License

MIT © Backshear LLC. Weather data is produced by NOAA/NWS and other public services; this project is not affiliated with or endorsed by NOAA.
