From 9fd2b80b50d4c0a7b8f4299b6315efaaa87e749c Mon Sep 17 00:00:00 2001 From: Jade Michael Thornton Date: Sun, 20 Sep 2026 13:24:52 -0500 Subject: [PATCH 1/5] document calling tools from scripts Show the in-memory FastMCP client as a way to use the tools without an AI assistant or a running server. --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 6157c93..2aa8922 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,39 @@ Create `.claude/skills/` skills for common patterns: - **Evening review**: `get_forecast mode=daily days=2` for tonight and tomorrow - **Chase prep**: `get_spc_outlook outlook_type=tornado` + `get_surface_analysis` + `get_upper_air` + `get_sounding` + `get_radar` + `get_alerts detail=full` +## Using from scripts + +The tools can be called without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script starts, makes its calls and exits. + +```python +# /// script +# requires-python = ">=3.11" +# dependencies = ["stormscope @ git+https://github.com/thornjad/stormscope"] +# /// +import asyncio + +from fastmcp import Client + +from stormscope.server import mcp + + +async def main(): + async with Client(mcp) as client: + result = await client.call_tool( + "get_conditions", {"latitude": 44.98, "longitude": -93.27} + ) + print(result.data) + + +asyncio.run(main()) +``` + +Run it with `uv run script.py`. `uv` installs the dependencies into a cached environment on first run. Inside a checkout, `uv run python script.py` works the same way with the dependency block omitted. + +`call_tool` takes any tool name from the [Tools](#tools) table and the same parameters, and `result.data` is the dict the tool returns. Configuration is read from the environment as usual (see [Configuration](#configuration)). + +Each run starts a fresh process, so the response cache starts empty and importing MetPy adds around a second of startup. A script that makes several calls should keep them inside one `async with` block to share the cache. For a one-off call from the shell, `fastmcp call path/to/server.py get_alerts latitude=44.98 longitude=-93.27 --json` also works from a checkout. + ## Data sources StormScope aggregates data from several upstream services. None of these services require authentication or API keys. From 6618dc524ff4716c737cd97354437fd49a3b2e52 Mon Sep 17 00:00:00 2001 From: Jade Michael Thornton Date: Sun, 20 Sep 2026 13:30:30 -0500 Subject: [PATCH 2/5] rewrite readme for new users Lead with a quick start, group setup and configuration, and fold the duplicate Tempest variable table into prose. Document the units override, fix the skills section wording, and rewrite prose to follow the project voice. --- README.md | 218 ++++++++++++++++++++++++++---------------------------- 1 file changed, 106 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index 2aa8922..f2e1493 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,23 @@ # StormScope -Real-time US weather data for AI assistants via MCP. Uses the NWS API, NOAA Storm Prediction Center data, NOAA Weather Prediction Center surface analysis, Iowa Environmental Mesonet radar and radiosonde soundings, and Open-Meteo pressure-level model data. Optionally uses data from your Tempest personal weather station. +StormScope is an MCP server that gives AI assistants live US weather data. Ask your assistant for current conditions, a forecast, severe weather outlooks, radar, upper-air analysis, fronts, or a sounding, and it pulls the answer from the National Weather Service, NOAA, the Iowa Environmental Mesonet, and Open-Meteo. If you own a Tempest personal weather station, StormScope can also use your station's readings. -**US locations only**. Covers all 50 states, DC, and US territories (Puerto Rico, Guam, USVI, American Samoa). Requests for non-US locations return a clear error. The SPC national outlook covers the contiguous US only. +Coverage is limited to US locations, meaning the 50 states and DC as well as the territories (Puerto Rico, Guam, USVI, American Samoa). Requests for anywhere else return an error that says so, with one exception, since the upper-air tool reads global model data and works at any location. The SPC national outlook covers the contiguous US only. -## What it does - -Most tools support a `detail` parameter: **standard** gives a clean summary, **full** adds the technical depth (METAR, VTEC codes, polygon geometry, probabilistic outlooks). - -- Current conditions: temperature, wind, humidity, sky, pressure -- Forecast in daily narrative periods, hourly, or raw gridpoint time-value series -- Active weather alerts with severity filtering -- SPC severe weather outlook, both categorical risk and probabilistic tornado/wind/hail -- National severe outlook with human-readable region descriptions -- NEXRAD radar station metadata and imagery URLs -- 500mb upper-air analysis: geopotential heights, temperature, wind, and derived vorticity (synoptic-scale resolution from a 5-point finite-difference grid — useful for identifying troughs, ridges, and jet stream patterns, but not mesoscale features) -- Soundings: the latest observed radiosonde from the nearest launch site (with its distance and direction from you) or a model profile at your exact location, with CAPE/CIN, LCL, freezing level, lapse rates, precipitable water, bulk shear, storm-relative helicity, and temperature inversions -- Surface analysis: fronts, pressure centers (highs/lows), and warm/cold sector detection relative to the nearest cold front -- Combined briefing that pulls everything together and adapts to the situation +## Quick start -## Installation - -Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/). +You need Python 3.11 or newer and [uv](https://docs.astral.sh/uv/). Register the server with Claude Code, swapping in your own coordinates: ```bash -claude mcp add --scope user stormscope -- uvx --from git+https://github.com/thornjad/stormscope stormscope +claude mcp add --scope user \ + --env PRIMARY_LATITUDE=44.98 \ + --env PRIMARY_LONGITUDE=-93.27 \ + stormscope -- uvx --from git+https://github.com/thornjad/stormscope stormscope ``` -Or add to your Claude Code MCP config: +Start a new session and ask "What's the weather?" The assistant calls `get_briefing` and answers for your coordinates. + +If you would rather edit your MCP config by hand, or your client is something other than Claude Code, the same server definition looks like this. Any client that can launch a stdio MCP server will work. ```json { @@ -44,69 +34,28 @@ Or add to your Claude Code MCP config: } ``` -## Configuration - -| Variable | Default | Description | -|--------------------------------|---------|----------------------------------------------------------------------------------------| -| `PRIMARY_LATITUDE` | none | Default latitude when coordinates aren't passed explicitly | -| `PRIMARY_LONGITUDE` | none | Default longitude when coordinates aren't passed explicitly | -| `UNITS` | `us` | Unit system (`us` or `si`) | -| `ENABLE_CORELOCATION` | `false` | Set to `true` to enable macOS CoreLocation (requires Xcode Command Line Tools) | -| `DISABLE_AUTO_GEOLOCATION` | `false` | Set to `true` to disable CoreLocation and IP geolocation | -| `TEMPEST_TOKEN` | none | Tempest Personal Access Token — enables Tempest station integration | -| `TEMPEST_STATION_ID` | none | Explicit station ID to use (optional, see [Tempest station](#tempest-weather-station)) | -| `TEMPEST_STATION_NAME` | none | Station name to match instead of ID (optional) | -| `USE_TEMPEST_STATION_GEOLOCATION` | `false` | Use Tempest station coordinates as the primary location | - -### Location detection - -All location-aware tools accept optional `latitude` and `longitude` parameters. When omitted, the server resolves location through a fallback chain: - -1. **Explicit `latitude`/`longitude` params** — the AI can pass coordinates for any location -2. **Tempest station location** (opt-in) — set `USE_TEMPEST_STATION_GEOLOCATION=true` with a configured station to use its coordinates -3. **`PRIMARY_LATITUDE`/`PRIMARY_LONGITUDE` env vars** — precise, recommended for your home location -4. **macOS CoreLocation** (opt-in) — set `ENABLE_CORELOCATION=true`, requires Xcode Command Line Tools, ~100m WiFi-based accuracy, prompts for location permission on first use. Compiles a small Swift helper into `~/Library/Application Support/stormscope/` -5. **IP geolocation** via [ipinfo.io](https://ipinfo.io) — automatic, city-level accuracy, one request per session - -Setting `DISABLE_AUTO_GEOLOCATION=true` disables both CoreLocation and IP geolocation (tiers 4 and 5). With auto-geolocation disabled and no env vars or explicit params, tools return an error. - -## Tempest personal weather station - -If you have a [Tempest](https://tempest.earth/tempest-home-weather-system/) personal weather station, StormScope can enrich NWS data with hyper-local sensor readings that NWS cannot provide: solar radiation, UV index, lightning strike counts, air density, and wet bulb temperature. Tempest also supplies sunrise/sunset times in its forecast, which are added to `get_forecast` output. +The coordinates are optional, and without them StormScope guesses your location from your IP address, which is only accurate to the city. See [Location detection](#location-detection) for the other options. -**Tempest data supplements NWS, it doesn't replace it.** NWS provides authoritative alert text, detailed narrative forecasts, and broad coverage. Tempest provides hyper-local precision at your exact station location. When a Tempest station is within range, StormScope uses Tempest values for temperature, feels-like, humidity, wind, and pressure, and sets `data_source: "tempest"` in the response. - -If the Tempest API is unavailable, all tools fall back to NWS data without error. - -### Setup - -1. Get a Personal Access Token from the [Tempest developer portal](https://tempest.earth/tempest-home-weather-system/). -2. Find your station ID from the Tempest app or API (Settings → Stations, or from the URL at `tempestwx.com/station/`). -3. Add to your MCP environment: - -```json -{ - "TEMPEST_TOKEN": "your-token-here", - "TEMPEST_STATION_ID": "your-station-id" -} -``` - -### Station resolution +## What it does -When `TEMPEST_STATION_ID` is not set, StormScope auto-discovers the nearest station associated with your token. If the nearest station is more than 5 miles from the request coordinates, it is not used (to avoid attaching irrelevant data to a distant location). You can also identify a station by name with `TEMPEST_STATION_NAME` (matched case-insensitively against the station's `name` and `public_name` fields). +Most tools take a `detail` parameter. **Standard** returns the summary fields, and **full** adds raw and technical data such as METAR, VTEC codes, polygon geometry, and probabilistic outlooks. -| Variable | Purpose | -|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| -| `TEMPEST_TOKEN` | Required. Enables all Tempest functionality. | -| `TEMPEST_STATION_ID` | Use a specific station by numeric ID. | -| `TEMPEST_STATION_NAME` | Use a specific station by name. | -| `USE_TEMPEST_STATION_GEOLOCATION` | Set to `true` to use the station's GPS coordinates as the primary location. Requires `TEMPEST_STATION_ID` or `TEMPEST_STATION_NAME`. | -| | | +- Current conditions, including temperature, wind, humidity, sky, and pressure +- Forecasts as daily narrative periods, hourly rows, or raw gridpoint time series +- Active weather alerts, with an optional severity filter +- SPC severe weather outlooks, both categorical risk and probabilistic tornado, wind, and hail +- A national severe outlook with region descriptions written for people +- NEXRAD radar station metadata and imagery URLs +- 500mb upper-air analysis with geopotential heights, temperature, wind, and derived vorticity +- Soundings, either the latest observed radiosonde from the nearest launch site (with its distance and direction from you) or a model profile at your exact location, with CAPE/CIN, LCL, freezing level, lapse rates, precipitable water, bulk shear, storm-relative helicity, and temperature inversions +- Surface analysis of fronts and pressure centers (highs and lows), with warm or cold sector detection relative to the nearest cold front +- A combined briefing of conditions, forecast, alerts, and the SPC outlook, with probabilistic outlooks, radar, and the national picture added at `detail=full` ## Tools | Tool | Description | Key params | |------------------------|------------------------------------------------------------------|------------------------------------------------------------------------------------| +| `get_briefing` | Combined briefing, the default for general weather questions | `detail`: standard or full | | `get_conditions` | Current conditions at a station | `detail`: standard or full | | `get_forecast` | Forecast in multiple formats | `mode`: daily, hourly, or raw; `days` (1-7, default 7); `hours` (1-48, default 24) | | `get_alerts` | Active weather alerts | `severity_filter`: Extreme, Severe, Moderate, or Minor; `detail`: standard or full | @@ -116,19 +65,24 @@ When `TEMPEST_STATION_ID` is not set, StormScope auto-discovers the nearest stat | `get_upper_air` | 500mb heights, temperature, wind, derived vorticity (Open-Meteo) | | | `get_sounding` | Observed radiosonde or model sounding with CAPE, shear, SRH | `source`: observed or model; `station`; `hours_ahead`: 0-48; `detail` | | `get_surface_analysis` | Fronts, pressure centers, warm/cold sector detection (WPC) | `day`: 1-3; `detail`: standard or full | -| `get_briefing` | Combined briefing, the default for general weather questions | `detail`: standard or full | -All location-aware tools accept optional `latitude`/`longitude`, falling back to the configured location (see [Location detection](#location-detection)). +Every tool except `get_national_outlook` accepts optional `latitude` and `longitude` parameters and falls back to your configured location when they are omitted. All tools also take an optional `units` override, either a base system (`us` or `si`) or a base with field overrides such as `us,pressure:mb,wind:kt`. + +### Notes on upper-air data + +Upper-air data comes from [Open-Meteo](https://open-meteo.com/) under CC-BY 4.0. Vorticity is derived from model wind fields at roughly 110 km grid spacing, so it captures synoptic-scale features such as shortwave troughs and jet maxima but misses mesoscale detail. + +### Notes on soundings -Upper-air data provided by [Open-Meteo](https://open-meteo.com/) under CC-BY 4.0. Vorticity is derived from model wind fields at ~110km grid spacing — this captures synoptic-scale features (shortwave troughs, jet maxima) but not mesoscale detail. +Observed soundings come from the NWS radiosonde network via IEM. Balloons launch around 00Z and 12Z from about 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. With `source=observed`, `get_sounding` reports the site's distance and bearing from you and adds a note when the site is far or the data is old. Use `source=model` for a profile at your exact location or at a forecast hour (up to 48). -Soundings come from the NWS radiosonde network via IEM, launched around 00Z and 12Z from roughly 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. `get_sounding` with `source=observed` reports the site's distance and bearing from you and adds a note when it is far or old. Use `source=model` for a profile at your exact location or a forecast hour (up to 48). Both report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below ~5 km. Index calculations use [MetPy](https://unidata.github.io/MetPy/). +Both sources report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below about 5 km. The index calculations use [MetPy](https://unidata.github.io/MetPy/). -### Example conversation +## Example conversations -These examples show how an AI assistant might present StormScope data. The tools return structured JSON, and the assistant formats it for the user. +The tools return structured JSON and your assistant turns it into prose, roughly like this. -**"What's the weather?"** (uses `get_briefing`): +**"What's the weather?"** calls `get_briefing`: ``` Currently 72F and Mostly Sunny in Minneapolis, MN. @@ -139,7 +93,7 @@ Severe Weather: Marginal Risk (MRGL) - isolated severe storms possible. Alerts: None active. ``` -**"What's the severe weather outlook?"** (uses `get_briefing detail=full`): +**"What's the severe weather outlook?"** calls `get_briefing` with `detail=full`: ``` ...plus dewpoint 50F, cloud layers FEW at 3000m, METAR: KMSP 041200Z... @@ -149,18 +103,60 @@ Radar: KMPX, latest scan 12:00Z, N0B/N0S available Day 2: TSTM, Day 3: NONE ``` -## Skill suggestions +## Configuration + +Set these as environment variables in your MCP server definition. + +| Variable | Default | Description | +|-----------------------------------|---------|------------------------------------------------------------------------------------------------------| +| `PRIMARY_LATITUDE` | none | Default latitude when coordinates aren't passed explicitly | +| `PRIMARY_LONGITUDE` | none | Default longitude when coordinates aren't passed explicitly | +| `UNITS` | `us` | Unit system, `us` or `si` | +| `ENABLE_CORELOCATION` | `false` | Set to `true` to use macOS CoreLocation (needs Xcode Command Line Tools) | +| `DISABLE_AUTO_GEOLOCATION` | `false` | Set to `true` to turn off both CoreLocation and IP geolocation | +| `TEMPEST_TOKEN` | none | Tempest Personal Access Token, which turns on the Tempest integration | +| `TEMPEST_STATION_ID` | none | Numeric ID of the station to use (optional, see [Tempest](#tempest-personal-weather-station)) | +| `TEMPEST_STATION_NAME` | none | Name of the station to use instead of an ID (optional) | +| `USE_TEMPEST_STATION_GEOLOCATION` | `false` | Set to `true` to use the station's coordinates as your primary location (needs a station ID or name) | + +### Location detection + +Every location-aware tool resolves its location in this order and uses the first match. + +1. **Explicit `latitude` and `longitude` parameters.** The assistant can pass coordinates for any place you ask about. +2. **Tempest station location** (opt-in). Set `USE_TEMPEST_STATION_GEOLOCATION=true` with a configured station to use its coordinates. +3. **`PRIMARY_LATITUDE` and `PRIMARY_LONGITUDE`.** These are precise and the best choice for your home location. +4. **macOS CoreLocation** (opt-in). Set `ENABLE_CORELOCATION=true` to get roughly 100 m WiFi-based accuracy. This needs Xcode Command Line Tools, compiles a small Swift helper into `~/Library/Application Support/stormscope/`, and prompts for location permission on first use. +5. **IP geolocation** through [ipinfo.io](https://ipinfo.io). It runs automatically at city-level accuracy, with one request per session. + +`DISABLE_AUTO_GEOLOCATION=true` removes options 4 and 5, so if you configured no coordinates and the assistant passes none, tools return an error. + +## Tempest personal weather station + +A [Tempest](https://tempest.earth/tempest-home-weather-system/) station measures things NWS cannot, so StormScope adds its solar radiation, UV index, lightning strike counts, air density, and wet bulb temperature to the NWS data. The station's sunrise and sunset times also show up in `get_forecast`. -Create `.claude/skills/` skills for common patterns: +NWS still supplies alert text and narrative forecasts, and it is the only source with national coverage, while Tempest adds precision at your exact location. When a station is in range, StormScope takes temperature, feels-like, humidity, wind, and pressure from it and sets `data_source: "tempest"` in the response. If the Tempest API is down, every tool falls back to NWS data without an error. -- **Morning briefing**: `get_briefing detail=full` for a full picture to start the day -- **Quick check**: `get_conditions` for just current conditions -- **Evening review**: `get_forecast mode=daily days=2` for tonight and tomorrow -- **Chase prep**: `get_spc_outlook outlook_type=tornado` + `get_surface_analysis` + `get_upper_air` + `get_sounding` + `get_radar` + `get_alerts detail=full` +### Setup + +1. Create a Personal Access Token at [tempestwx.com/settings/tokens](https://tempestwx.com/settings/tokens). +2. Find your station ID in the Tempest app under Settings and then Stations, or in the URL `tempestwx.com/station/`. +3. Add both to the `env` block of your MCP server definition, or pass them as `--env` flags to `claude mcp add`. + +```json +{ + "TEMPEST_TOKEN": "your-token-here", + "TEMPEST_STATION_ID": "your-station-id" +} +``` + +### Which station gets used + +`TEMPEST_TOKEN` is the only required variable. Without `TEMPEST_STATION_ID`, StormScope finds the nearest station on your account, and it can match a station by name instead if you set `TEMPEST_STATION_NAME` (compared case-insensitively against the station's `name` and `public_name`). A station more than 5 miles from the requested coordinates is ignored so that distant readings never get attached to the wrong place. ## Using from scripts -The tools can be called without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script starts, makes its calls and exits. +The tools also work without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script runs its calls and exits. ```python # /// script @@ -185,35 +181,33 @@ async def main(): asyncio.run(main()) ``` -Run it with `uv run script.py`. `uv` installs the dependencies into a cached environment on first run. Inside a checkout, `uv run python script.py` works the same way with the dependency block omitted. +Run it with `uv run script.py`, and `uv` installs the dependencies into a cached environment on first run. Inside a checkout, `uv run python script.py` works the same way with the dependency block removed. -`call_tool` takes any tool name from the [Tools](#tools) table and the same parameters, and `result.data` is the dict the tool returns. Configuration is read from the environment as usual (see [Configuration](#configuration)). +`call_tool` accepts any tool name from the [Tools](#tools) table with the same parameters, and `result.data` is the dict the tool returns. Configuration comes from the environment as usual (see [Configuration](#configuration)). -Each run starts a fresh process, so the response cache starts empty and importing MetPy adds around a second of startup. A script that makes several calls should keep them inside one `async with` block to share the cache. For a one-off call from the shell, `fastmcp call path/to/server.py get_alerts latitude=44.98 longitude=-93.27 --json` also works from a checkout. +Each run starts a fresh process, so the response cache begins empty and importing MetPy adds around a second of startup. A script that makes several calls should keep them inside one `async with` block to share the cache. For a one-off call from a shell in a checkout, `fastmcp call path/to/server.py get_alerts latitude=44.98 longitude=-93.27 --json` also works. -## Data sources +## Ideas for Claude Code skills -StormScope aggregates data from several upstream services. None of these services require authentication or API keys. +If you use Claude Code, you can create skills in `.claude/skills/` for the common patterns. Some ideas follow. -**National Weather Service (NWS)** — [api.weather.gov](https://api.weather.gov) ([terms](https://www.weather.gov/disclaimer)) -Conditions, forecasts, alerts, and gridpoint data. NWS data is produced by the US federal government and is in the public domain under [17 U.S.C. § 105](https://www.law.cornell.edu/uscode/text/17/105). Use of NWS data does not imply NOAA or NWS endorsement of this project. +- **Morning briefing** runs `get_briefing detail=full` for the whole picture at the start of the day. +- **Quick check** runs `get_conditions` for current conditions only. +- **Evening review** runs `get_forecast mode=daily days=2` for tonight and tomorrow. +- **Chase prep** chains `get_spc_outlook outlook_type=tornado`, `get_surface_analysis`, `get_upper_air`, `get_sounding`, `get_radar`, and `get_alerts detail=full`. -**NOAA Storm Prediction Center (SPC)** — [spc.noaa.gov](https://www.spc.noaa.gov) ([terms](https://www.weather.gov/disclaimer)) -Categorical and probabilistic severe weather outlooks (days 1-3). SPC data is US government public domain under the same statute as NWS. - -**NOAA Weather Prediction Center (WPC)** — [mapservices.weather.noaa.gov](https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/natl_fcst_wx_chart/MapServer) -Surface analysis charts with fronts and pressure centers (days 1-3). WPC data is US government public domain under the same statute as NWS. Analysis charts are updated approximately 4 times per day. No pressure values are provided for H/L centers. - -**Iowa Environmental Mesonet (IEM)** — [mesonet.agron.iastate.edu](https://mesonet.agron.iastate.edu) ([disclaimer](https://mesonet.agron.iastate.edu/disclaimer.php)) -NEXRAD radar station metadata and imagery, plus radiosonde (weather balloon) sounding data from the NWS upper-air network. IEM data is in the public domain and may be used freely by anyone for any lawful purpose. Data provided by the Iowa Environmental Mesonet of Iowa State University. +## Data sources -**Open-Meteo** — [open-meteo.com](https://open-meteo.com) ([terms](https://open-meteo.com/en/terms)) -500mb upper-air pressure-level data (geopotential heights, temperature, wind) and model soundings. Provided under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). StormScope uses the free non-commercial tier and does not support paid Open-Meteo subscriptions. +StormScope combines several upstream services, and none of them need an API key. Responses are cached to keep request volume low, so data can lag slightly behind the source. -**ipinfo.io** — [ipinfo.io](https://ipinfo.io) ([terms](https://ipinfo.io/terms-of-service)) -IP-based geolocation, used only as a last-resort fallback when no coordinates are configured and CoreLocation is unavailable. One request per server session. StormScope uses the free tier of this service and does not resell or redistribute the geolocation data. Set `DISABLE_AUTO_GEOLOCATION=true` to prevent this request entirely. +- **National Weather Service (NWS)** ([api.weather.gov](https://api.weather.gov), [terms](https://www.weather.gov/disclaimer)) supplies conditions, forecasts, alerts, and gridpoint data. It is produced by the US federal government and is public domain under [17 U.S.C. § 105](https://www.law.cornell.edu/uscode/text/17/105). Using NWS data does not imply NOAA or NWS endorsement of this project. +- **NOAA Storm Prediction Center (SPC)** ([spc.noaa.gov](https://www.spc.noaa.gov), [terms](https://www.weather.gov/disclaimer)) supplies categorical and probabilistic severe weather outlooks for days 1 to 3. It is public domain under the same statute as NWS. +- **NOAA Weather Prediction Center (WPC)** ([mapservices.weather.noaa.gov](https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/natl_fcst_wx_chart/MapServer)) supplies surface analysis charts with fronts and pressure centers for days 1 to 3. It is public domain under the same statute as NWS. Charts update about four times a day, and the high and low centers carry no pressure values. +- **Iowa Environmental Mesonet (IEM)** ([mesonet.agron.iastate.edu](https://mesonet.agron.iastate.edu), [disclaimer](https://mesonet.agron.iastate.edu/disclaimer.php)) supplies NEXRAD radar station metadata and imagery, along with radiosonde (weather balloon) soundings from the NWS upper-air network. IEM data is public domain and free for any lawful purpose. Data provided by the Iowa Environmental Mesonet of Iowa State University. +- **Open-Meteo** ([open-meteo.com](https://open-meteo.com), [terms](https://open-meteo.com/en/terms)) supplies 500mb pressure-level data (geopotential heights, temperature, wind) and model soundings under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). StormScope uses the free non-commercial tier and does not support paid subscriptions. +- **ipinfo.io** ([ipinfo.io](https://ipinfo.io), [terms](https://ipinfo.io/terms-of-service)) supplies IP-based geolocation as a last resort when no coordinates are configured and CoreLocation is unavailable. StormScope makes one request per server session on the free tier and does not resell or redistribute the results. Set `DISABLE_AUTO_GEOLOCATION=true` to prevent the request entirely. -All upstream services provide data without warranty of accuracy or availability. StormScope caches responses to reduce request volume but cannot guarantee data freshness. Users of StormScope are responsible for complying with each service's terms of use. The authors of StormScope are not liable for how others use this software or the upstream APIs it connects to. +All upstream services provide data without warranty of accuracy or availability. You are responsible for following each service's terms of use, and the authors of StormScope are not liable for how others use this software or the upstream APIs it connects to. ## Disclaimer @@ -234,4 +228,4 @@ uv run python -m pytest --- -Found this useful? [Buy me a coffee!](https://buymeacoffee.com/jademichaelthornton) +If StormScope is useful to you, you can [buy me a coffee](https://buymeacoffee.com/jademichaelthornton). From 787d8d917a3766b664f6a3f3e27bff737772980e Mon Sep 17 00:00:00 2001 From: Jade Michael Thornton Date: Sun, 20 Sep 2026 17:40:34 -0500 Subject: [PATCH 3/5] limit readme edits to copy fixes Restore the original section structure and content, and keep only wording fixes such as dash and colon constructions. --- README.md | 218 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 112 insertions(+), 106 deletions(-) diff --git a/README.md b/README.md index f2e1493..49e269d 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,33 @@ # StormScope -StormScope is an MCP server that gives AI assistants live US weather data. Ask your assistant for current conditions, a forecast, severe weather outlooks, radar, upper-air analysis, fronts, or a sounding, and it pulls the answer from the National Weather Service, NOAA, the Iowa Environmental Mesonet, and Open-Meteo. If you own a Tempest personal weather station, StormScope can also use your station's readings. +Real-time US weather data for AI assistants via MCP. Uses the NWS API, NOAA Storm Prediction Center data, NOAA Weather Prediction Center surface analysis, Iowa Environmental Mesonet radar and radiosonde soundings, and Open-Meteo pressure-level model data. Optionally uses data from your Tempest personal weather station. -Coverage is limited to US locations, meaning the 50 states and DC as well as the territories (Puerto Rico, Guam, USVI, American Samoa). Requests for anywhere else return an error that says so, with one exception, since the upper-air tool reads global model data and works at any location. The SPC national outlook covers the contiguous US only. +**US locations only**. Covers all 50 states, DC, and US territories (Puerto Rico, Guam, USVI, American Samoa). Requests for non-US locations return a clear error. The SPC national outlook covers the contiguous US only. -## Quick start +## What it does + +Most tools support a `detail` parameter. **Standard** gives a clean summary, and **full** adds the technical depth (METAR, VTEC codes, polygon geometry, probabilistic outlooks). + +- Current conditions: temperature, wind, humidity, sky, pressure +- Forecast in daily narrative periods, hourly, or raw gridpoint time-value series +- Active weather alerts with severity filtering +- SPC severe weather outlook, both categorical risk and probabilistic tornado/wind/hail +- National severe outlook with human-readable region descriptions +- NEXRAD radar station metadata and imagery URLs +- 500mb upper-air analysis: geopotential heights, temperature, wind, and derived vorticity (synoptic-scale resolution from a 5-point finite-difference grid, useful for identifying troughs, ridges, and jet stream patterns but not mesoscale features) +- Soundings: the latest observed radiosonde from the nearest launch site (with its distance and direction from you) or a model profile at your exact location, with CAPE/CIN, LCL, freezing level, lapse rates, precipitable water, bulk shear, storm-relative helicity, and temperature inversions +- Surface analysis: fronts, pressure centers (highs/lows), and warm/cold sector detection relative to the nearest cold front +- Combined briefing that pulls everything together and adapts to the situation -You need Python 3.11 or newer and [uv](https://docs.astral.sh/uv/). Register the server with Claude Code, swapping in your own coordinates: +## Installation + +Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/). ```bash -claude mcp add --scope user \ - --env PRIMARY_LATITUDE=44.98 \ - --env PRIMARY_LONGITUDE=-93.27 \ - stormscope -- uvx --from git+https://github.com/thornjad/stormscope stormscope +claude mcp add --scope user stormscope -- uvx --from git+https://github.com/thornjad/stormscope stormscope ``` -Start a new session and ask "What's the weather?" The assistant calls `get_briefing` and answers for your coordinates. - -If you would rather edit your MCP config by hand, or your client is something other than Claude Code, the same server definition looks like this. Any client that can launch a stdio MCP server will work. +Or add to your Claude Code MCP config: ```json { @@ -34,28 +44,69 @@ If you would rather edit your MCP config by hand, or your client is something ot } ``` -The coordinates are optional, and without them StormScope guesses your location from your IP address, which is only accurate to the city. See [Location detection](#location-detection) for the other options. +## Configuration -## What it does +| Variable | Default | Description | +|--------------------------------|---------|----------------------------------------------------------------------------------------| +| `PRIMARY_LATITUDE` | none | Default latitude when coordinates aren't passed explicitly | +| `PRIMARY_LONGITUDE` | none | Default longitude when coordinates aren't passed explicitly | +| `UNITS` | `us` | Unit system (`us` or `si`) | +| `ENABLE_CORELOCATION` | `false` | Set to `true` to enable macOS CoreLocation (requires Xcode Command Line Tools) | +| `DISABLE_AUTO_GEOLOCATION` | `false` | Set to `true` to disable CoreLocation and IP geolocation | +| `TEMPEST_TOKEN` | none | Tempest Personal Access Token, enables Tempest station integration | +| `TEMPEST_STATION_ID` | none | Explicit station ID to use (optional, see [Tempest station](#tempest-weather-station)) | +| `TEMPEST_STATION_NAME` | none | Station name to match instead of ID (optional) | +| `USE_TEMPEST_STATION_GEOLOCATION` | `false` | Use Tempest station coordinates as the primary location | -Most tools take a `detail` parameter. **Standard** returns the summary fields, and **full** adds raw and technical data such as METAR, VTEC codes, polygon geometry, and probabilistic outlooks. +### Location detection -- Current conditions, including temperature, wind, humidity, sky, and pressure -- Forecasts as daily narrative periods, hourly rows, or raw gridpoint time series -- Active weather alerts, with an optional severity filter -- SPC severe weather outlooks, both categorical risk and probabilistic tornado, wind, and hail -- A national severe outlook with region descriptions written for people -- NEXRAD radar station metadata and imagery URLs -- 500mb upper-air analysis with geopotential heights, temperature, wind, and derived vorticity -- Soundings, either the latest observed radiosonde from the nearest launch site (with its distance and direction from you) or a model profile at your exact location, with CAPE/CIN, LCL, freezing level, lapse rates, precipitable water, bulk shear, storm-relative helicity, and temperature inversions -- Surface analysis of fronts and pressure centers (highs and lows), with warm or cold sector detection relative to the nearest cold front -- A combined briefing of conditions, forecast, alerts, and the SPC outlook, with probabilistic outlooks, radar, and the national picture added at `detail=full` +All location-aware tools accept optional `latitude` and `longitude` parameters. When omitted, the server resolves location through a fallback chain: + +1. **Explicit `latitude`/`longitude` params**. The AI can pass coordinates for any location +2. **Tempest station location** (opt-in). Set `USE_TEMPEST_STATION_GEOLOCATION=true` with a configured station to use its coordinates +3. **`PRIMARY_LATITUDE`/`PRIMARY_LONGITUDE` env vars**. These are precise and recommended for your home location +4. **macOS CoreLocation** (opt-in). Set `ENABLE_CORELOCATION=true` to use it. It requires Xcode Command Line Tools, has ~100m WiFi-based accuracy, and prompts for location permission on first use. It compiles a small Swift helper into `~/Library/Application Support/stormscope/` +5. **IP geolocation** via [ipinfo.io](https://ipinfo.io). This is automatic, with city-level accuracy and one request per session + +Setting `DISABLE_AUTO_GEOLOCATION=true` disables both CoreLocation and IP geolocation (tiers 4 and 5). With auto-geolocation disabled and no env vars or explicit params, tools return an error. + +## Tempest personal weather station + +If you have a [Tempest](https://tempest.earth/tempest-home-weather-system/) personal weather station, StormScope can enrich NWS data with hyper-local sensor readings that NWS cannot provide: solar radiation, UV index, lightning strike counts, air density, and wet bulb temperature. Tempest also supplies sunrise/sunset times in its forecast, which are added to `get_forecast` output. + +**Tempest data supplements NWS.** NWS provides authoritative alert text, detailed narrative forecasts, and broad coverage, while Tempest provides hyper-local precision at your exact station location. When a Tempest station is within range, StormScope uses Tempest values for temperature, feels-like, humidity, wind, and pressure, and sets `data_source: "tempest"` in the response. + +If the Tempest API is unavailable, all tools fall back to NWS data without error. + +### Setup + +1. Get a Personal Access Token from the [Tempest developer portal](https://tempest.earth/tempest-home-weather-system/). +2. Find your station ID from the Tempest app or API (Settings → Stations, or from the URL at `tempestwx.com/station/`). +3. Add to your MCP environment: + +```json +{ + "TEMPEST_TOKEN": "your-token-here", + "TEMPEST_STATION_ID": "your-station-id" +} +``` + +### Station resolution + +When `TEMPEST_STATION_ID` is not set, StormScope auto-discovers the nearest station associated with your token. If the nearest station is more than 5 miles from the request coordinates, it is not used (to avoid attaching irrelevant data to a distant location). You can also identify a station by name with `TEMPEST_STATION_NAME` (matched case-insensitively against the station's `name` and `public_name` fields). + +| Variable | Purpose | +|--------------------------------|--------------------------------------------------------------------------------------------------------------------------------------| +| `TEMPEST_TOKEN` | Required. Enables all Tempest functionality. | +| `TEMPEST_STATION_ID` | Use a specific station by numeric ID. | +| `TEMPEST_STATION_NAME` | Use a specific station by name. | +| `USE_TEMPEST_STATION_GEOLOCATION` | Set to `true` to use the station's GPS coordinates as the primary location. Requires `TEMPEST_STATION_ID` or `TEMPEST_STATION_NAME`. | +| | | ## Tools | Tool | Description | Key params | |------------------------|------------------------------------------------------------------|------------------------------------------------------------------------------------| -| `get_briefing` | Combined briefing, the default for general weather questions | `detail`: standard or full | | `get_conditions` | Current conditions at a station | `detail`: standard or full | | `get_forecast` | Forecast in multiple formats | `mode`: daily, hourly, or raw; `days` (1-7, default 7); `hours` (1-48, default 24) | | `get_alerts` | Active weather alerts | `severity_filter`: Extreme, Severe, Moderate, or Minor; `detail`: standard or full | @@ -65,24 +116,19 @@ Most tools take a `detail` parameter. **Standard** returns the summary fields, a | `get_upper_air` | 500mb heights, temperature, wind, derived vorticity (Open-Meteo) | | | `get_sounding` | Observed radiosonde or model sounding with CAPE, shear, SRH | `source`: observed or model; `station`; `hours_ahead`: 0-48; `detail` | | `get_surface_analysis` | Fronts, pressure centers, warm/cold sector detection (WPC) | `day`: 1-3; `detail`: standard or full | +| `get_briefing` | Combined briefing, the default for general weather questions | `detail`: standard or full | -Every tool except `get_national_outlook` accepts optional `latitude` and `longitude` parameters and falls back to your configured location when they are omitted. All tools also take an optional `units` override, either a base system (`us` or `si`) or a base with field overrides such as `us,pressure:mb,wind:kt`. - -### Notes on upper-air data - -Upper-air data comes from [Open-Meteo](https://open-meteo.com/) under CC-BY 4.0. Vorticity is derived from model wind fields at roughly 110 km grid spacing, so it captures synoptic-scale features such as shortwave troughs and jet maxima but misses mesoscale detail. - -### Notes on soundings +All location-aware tools accept optional `latitude`/`longitude`, falling back to the configured location (see [Location detection](#location-detection)). -Observed soundings come from the NWS radiosonde network via IEM. Balloons launch around 00Z and 12Z from about 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. With `source=observed`, `get_sounding` reports the site's distance and bearing from you and adds a note when the site is far or the data is old. Use `source=model` for a profile at your exact location or at a forecast hour (up to 48). +Upper-air data provided by [Open-Meteo](https://open-meteo.com/) under CC-BY 4.0. Vorticity is derived from model wind fields at ~110km grid spacing, which captures synoptic-scale features (shortwave troughs, jet maxima) but not mesoscale detail. -Both sources report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below about 5 km. The index calculations use [MetPy](https://unidata.github.io/MetPy/). +Soundings come from the NWS radiosonde network via IEM, launched around 00Z and 12Z from roughly 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. `get_sounding` with `source=observed` reports the site's distance and bearing from you and adds a note when it is far or old. Use `source=model` for a profile at your exact location or a forecast hour (up to 48). Both report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below ~5 km. Index calculations use [MetPy](https://unidata.github.io/MetPy/). -## Example conversations +### Example conversation -The tools return structured JSON and your assistant turns it into prose, roughly like this. +These examples show how an AI assistant might present StormScope data. The tools return structured JSON, and the assistant formats it for the user. -**"What's the weather?"** calls `get_briefing`: +**"What's the weather?"** (uses `get_briefing`): ``` Currently 72F and Mostly Sunny in Minneapolis, MN. @@ -93,7 +139,7 @@ Severe Weather: Marginal Risk (MRGL) - isolated severe storms possible. Alerts: None active. ``` -**"What's the severe weather outlook?"** calls `get_briefing` with `detail=full`: +**"What's the severe weather outlook?"** (uses `get_briefing detail=full`): ``` ...plus dewpoint 50F, cloud layers FEW at 3000m, METAR: KMSP 041200Z... @@ -103,60 +149,18 @@ Radar: KMPX, latest scan 12:00Z, N0B/N0S available Day 2: TSTM, Day 3: NONE ``` -## Configuration - -Set these as environment variables in your MCP server definition. - -| Variable | Default | Description | -|-----------------------------------|---------|------------------------------------------------------------------------------------------------------| -| `PRIMARY_LATITUDE` | none | Default latitude when coordinates aren't passed explicitly | -| `PRIMARY_LONGITUDE` | none | Default longitude when coordinates aren't passed explicitly | -| `UNITS` | `us` | Unit system, `us` or `si` | -| `ENABLE_CORELOCATION` | `false` | Set to `true` to use macOS CoreLocation (needs Xcode Command Line Tools) | -| `DISABLE_AUTO_GEOLOCATION` | `false` | Set to `true` to turn off both CoreLocation and IP geolocation | -| `TEMPEST_TOKEN` | none | Tempest Personal Access Token, which turns on the Tempest integration | -| `TEMPEST_STATION_ID` | none | Numeric ID of the station to use (optional, see [Tempest](#tempest-personal-weather-station)) | -| `TEMPEST_STATION_NAME` | none | Name of the station to use instead of an ID (optional) | -| `USE_TEMPEST_STATION_GEOLOCATION` | `false` | Set to `true` to use the station's coordinates as your primary location (needs a station ID or name) | - -### Location detection - -Every location-aware tool resolves its location in this order and uses the first match. - -1. **Explicit `latitude` and `longitude` parameters.** The assistant can pass coordinates for any place you ask about. -2. **Tempest station location** (opt-in). Set `USE_TEMPEST_STATION_GEOLOCATION=true` with a configured station to use its coordinates. -3. **`PRIMARY_LATITUDE` and `PRIMARY_LONGITUDE`.** These are precise and the best choice for your home location. -4. **macOS CoreLocation** (opt-in). Set `ENABLE_CORELOCATION=true` to get roughly 100 m WiFi-based accuracy. This needs Xcode Command Line Tools, compiles a small Swift helper into `~/Library/Application Support/stormscope/`, and prompts for location permission on first use. -5. **IP geolocation** through [ipinfo.io](https://ipinfo.io). It runs automatically at city-level accuracy, with one request per session. - -`DISABLE_AUTO_GEOLOCATION=true` removes options 4 and 5, so if you configured no coordinates and the assistant passes none, tools return an error. - -## Tempest personal weather station - -A [Tempest](https://tempest.earth/tempest-home-weather-system/) station measures things NWS cannot, so StormScope adds its solar radiation, UV index, lightning strike counts, air density, and wet bulb temperature to the NWS data. The station's sunrise and sunset times also show up in `get_forecast`. +## Skill suggestions -NWS still supplies alert text and narrative forecasts, and it is the only source with national coverage, while Tempest adds precision at your exact location. When a station is in range, StormScope takes temperature, feels-like, humidity, wind, and pressure from it and sets `data_source: "tempest"` in the response. If the Tempest API is down, every tool falls back to NWS data without an error. +Create `.claude/skills/` skills for common patterns: -### Setup - -1. Create a Personal Access Token at [tempestwx.com/settings/tokens](https://tempestwx.com/settings/tokens). -2. Find your station ID in the Tempest app under Settings and then Stations, or in the URL `tempestwx.com/station/`. -3. Add both to the `env` block of your MCP server definition, or pass them as `--env` flags to `claude mcp add`. - -```json -{ - "TEMPEST_TOKEN": "your-token-here", - "TEMPEST_STATION_ID": "your-station-id" -} -``` - -### Which station gets used - -`TEMPEST_TOKEN` is the only required variable. Without `TEMPEST_STATION_ID`, StormScope finds the nearest station on your account, and it can match a station by name instead if you set `TEMPEST_STATION_NAME` (compared case-insensitively against the station's `name` and `public_name`). A station more than 5 miles from the requested coordinates is ignored so that distant readings never get attached to the wrong place. +- **Morning briefing**: `get_briefing detail=full` for a full picture to start the day +- **Quick check**: `get_conditions` for just current conditions +- **Evening review**: `get_forecast mode=daily days=2` for tonight and tomorrow +- **Chase prep**: `get_spc_outlook outlook_type=tornado` + `get_surface_analysis` + `get_upper_air` + `get_sounding` + `get_radar` + `get_alerts detail=full` ## Using from scripts -The tools also work without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script runs its calls and exits. +The tools can be called without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script starts, makes its calls and exits. ```python # /// script @@ -181,33 +185,35 @@ async def main(): asyncio.run(main()) ``` -Run it with `uv run script.py`, and `uv` installs the dependencies into a cached environment on first run. Inside a checkout, `uv run python script.py` works the same way with the dependency block removed. +Run it with `uv run script.py`. `uv` installs the dependencies into a cached environment on first run. Inside a checkout, `uv run python script.py` works the same way with the dependency block omitted. -`call_tool` accepts any tool name from the [Tools](#tools) table with the same parameters, and `result.data` is the dict the tool returns. Configuration comes from the environment as usual (see [Configuration](#configuration)). +`call_tool` takes any tool name from the [Tools](#tools) table and the same parameters, and `result.data` is the dict the tool returns. Configuration is read from the environment as usual (see [Configuration](#configuration)). -Each run starts a fresh process, so the response cache begins empty and importing MetPy adds around a second of startup. A script that makes several calls should keep them inside one `async with` block to share the cache. For a one-off call from a shell in a checkout, `fastmcp call path/to/server.py get_alerts latitude=44.98 longitude=-93.27 --json` also works. +Each run starts a fresh process, so the response cache starts empty and importing MetPy adds around a second of startup. A script that makes several calls should keep them inside one `async with` block to share the cache. For a one-off call from the shell, `fastmcp call path/to/server.py get_alerts latitude=44.98 longitude=-93.27 --json` also works from a checkout. -## Ideas for Claude Code skills +## Data sources -If you use Claude Code, you can create skills in `.claude/skills/` for the common patterns. Some ideas follow. +StormScope aggregates data from several upstream services. None of these services require authentication or API keys. -- **Morning briefing** runs `get_briefing detail=full` for the whole picture at the start of the day. -- **Quick check** runs `get_conditions` for current conditions only. -- **Evening review** runs `get_forecast mode=daily days=2` for tonight and tomorrow. -- **Chase prep** chains `get_spc_outlook outlook_type=tornado`, `get_surface_analysis`, `get_upper_air`, `get_sounding`, `get_radar`, and `get_alerts detail=full`. +**National Weather Service (NWS)** at [api.weather.gov](https://api.weather.gov) ([terms](https://www.weather.gov/disclaimer)) +Conditions, forecasts, alerts, and gridpoint data. NWS data is produced by the US federal government and is in the public domain under [17 U.S.C. § 105](https://www.law.cornell.edu/uscode/text/17/105). Use of NWS data does not imply NOAA or NWS endorsement of this project. -## Data sources +**NOAA Storm Prediction Center (SPC)** at [spc.noaa.gov](https://www.spc.noaa.gov) ([terms](https://www.weather.gov/disclaimer)) +Categorical and probabilistic severe weather outlooks (days 1-3). SPC data is US government public domain under the same statute as NWS. + +**NOAA Weather Prediction Center (WPC)** at [mapservices.weather.noaa.gov](https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/natl_fcst_wx_chart/MapServer) +Surface analysis charts with fronts and pressure centers (days 1-3). WPC data is US government public domain under the same statute as NWS. Analysis charts are updated approximately 4 times per day. No pressure values are provided for H/L centers. + +**Iowa Environmental Mesonet (IEM)** at [mesonet.agron.iastate.edu](https://mesonet.agron.iastate.edu) ([disclaimer](https://mesonet.agron.iastate.edu/disclaimer.php)) +NEXRAD radar station metadata and imagery, plus radiosonde (weather balloon) sounding data from the NWS upper-air network. IEM data is in the public domain and may be used freely by anyone for any lawful purpose. Data provided by the Iowa Environmental Mesonet of Iowa State University. -StormScope combines several upstream services, and none of them need an API key. Responses are cached to keep request volume low, so data can lag slightly behind the source. +**Open-Meteo** at [open-meteo.com](https://open-meteo.com) ([terms](https://open-meteo.com/en/terms)) +500mb upper-air pressure-level data (geopotential heights, temperature, wind) and model soundings. Provided under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). StormScope uses the free non-commercial tier and does not support paid Open-Meteo subscriptions. -- **National Weather Service (NWS)** ([api.weather.gov](https://api.weather.gov), [terms](https://www.weather.gov/disclaimer)) supplies conditions, forecasts, alerts, and gridpoint data. It is produced by the US federal government and is public domain under [17 U.S.C. § 105](https://www.law.cornell.edu/uscode/text/17/105). Using NWS data does not imply NOAA or NWS endorsement of this project. -- **NOAA Storm Prediction Center (SPC)** ([spc.noaa.gov](https://www.spc.noaa.gov), [terms](https://www.weather.gov/disclaimer)) supplies categorical and probabilistic severe weather outlooks for days 1 to 3. It is public domain under the same statute as NWS. -- **NOAA Weather Prediction Center (WPC)** ([mapservices.weather.noaa.gov](https://mapservices.weather.noaa.gov/vector/rest/services/outlooks/natl_fcst_wx_chart/MapServer)) supplies surface analysis charts with fronts and pressure centers for days 1 to 3. It is public domain under the same statute as NWS. Charts update about four times a day, and the high and low centers carry no pressure values. -- **Iowa Environmental Mesonet (IEM)** ([mesonet.agron.iastate.edu](https://mesonet.agron.iastate.edu), [disclaimer](https://mesonet.agron.iastate.edu/disclaimer.php)) supplies NEXRAD radar station metadata and imagery, along with radiosonde (weather balloon) soundings from the NWS upper-air network. IEM data is public domain and free for any lawful purpose. Data provided by the Iowa Environmental Mesonet of Iowa State University. -- **Open-Meteo** ([open-meteo.com](https://open-meteo.com), [terms](https://open-meteo.com/en/terms)) supplies 500mb pressure-level data (geopotential heights, temperature, wind) and model soundings under [CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). StormScope uses the free non-commercial tier and does not support paid subscriptions. -- **ipinfo.io** ([ipinfo.io](https://ipinfo.io), [terms](https://ipinfo.io/terms-of-service)) supplies IP-based geolocation as a last resort when no coordinates are configured and CoreLocation is unavailable. StormScope makes one request per server session on the free tier and does not resell or redistribute the results. Set `DISABLE_AUTO_GEOLOCATION=true` to prevent the request entirely. +**ipinfo.io** at [ipinfo.io](https://ipinfo.io) ([terms](https://ipinfo.io/terms-of-service)) +IP-based geolocation, used only as a last-resort fallback when no coordinates are configured and CoreLocation is unavailable. One request per server session. StormScope uses the free tier of this service and does not resell or redistribute the geolocation data. Set `DISABLE_AUTO_GEOLOCATION=true` to prevent this request entirely. -All upstream services provide data without warranty of accuracy or availability. You are responsible for following each service's terms of use, and the authors of StormScope are not liable for how others use this software or the upstream APIs it connects to. +All upstream services provide data without warranty of accuracy or availability. StormScope caches responses to reduce request volume but cannot guarantee data freshness. Users of StormScope are responsible for complying with each service's terms of use. The authors of StormScope are not liable for how others use this software or the upstream APIs it connects to. ## Disclaimer @@ -228,4 +234,4 @@ uv run python -m pytest --- -If StormScope is useful to you, you can [buy me a coffee](https://buymeacoffee.com/jademichaelthornton). +Found this useful? [Buy me a coffee!](https://buymeacoffee.com/jademichaelthornton) From 04762df44d1e811db0e10479143568b2b8104ba8 Mon Sep 17 00:00:00 2001 From: Jade Michael Thornton Date: Sun, 20 Sep 2026 17:55:25 -0500 Subject: [PATCH 4/5] update more --- CLAUDE.md => AGENTS.md | 0 README.md | 20 +++++--------------- 2 files changed, 5 insertions(+), 15 deletions(-) rename CLAUDE.md => AGENTS.md (100%) diff --git a/CLAUDE.md b/AGENTS.md similarity index 100% rename from CLAUDE.md rename to AGENTS.md diff --git a/README.md b/README.md index 49e269d..92d3ad4 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ Real-time US weather data for AI assistants via MCP. Uses the NWS API, NOAA Storm Prediction Center data, NOAA Weather Prediction Center surface analysis, Iowa Environmental Mesonet radar and radiosonde soundings, and Open-Meteo pressure-level model data. Optionally uses data from your Tempest personal weather station. -**US locations only**. Covers all 50 states, DC, and US territories (Puerto Rico, Guam, USVI, American Samoa). Requests for non-US locations return a clear error. The SPC national outlook covers the contiguous US only. +**US locations only**. Covers all 50 states, DC, and US territories (Puerto Rico, Guam, USVI, American Samoa). Requests for non-US locations return an error. The SPC national outlook covers the contiguous US only. ## What it does -Most tools support a `detail` parameter. **Standard** gives a clean summary, and **full** adds the technical depth (METAR, VTEC codes, polygon geometry, probabilistic outlooks). +Most tools support a `detail` parameter. Standard gives a clean summary, and full adds more nerd stuff (METAR, VTEC codes, polygon geometry, probabilistic outlooks). - Current conditions: temperature, wind, humidity, sky, pressure -- Forecast in daily narrative periods, hourly, or raw gridpoint time-value series +- Forecast in daily periods, hourly, or raw gridpoint time-value series - Active weather alerts with severity filtering - SPC severe weather outlook, both categorical risk and probabilistic tornado/wind/hail - National severe outlook with human-readable region descriptions @@ -17,7 +17,6 @@ Most tools support a `detail` parameter. **Standard** gives a clean summary, and - 500mb upper-air analysis: geopotential heights, temperature, wind, and derived vorticity (synoptic-scale resolution from a 5-point finite-difference grid, useful for identifying troughs, ridges, and jet stream patterns but not mesoscale features) - Soundings: the latest observed radiosonde from the nearest launch site (with its distance and direction from you) or a model profile at your exact location, with CAPE/CIN, LCL, freezing level, lapse rates, precipitable water, bulk shear, storm-relative helicity, and temperature inversions - Surface analysis: fronts, pressure centers (highs/lows), and warm/cold sector detection relative to the nearest cold front -- Combined briefing that pulls everything together and adapts to the situation ## Installation @@ -76,7 +75,7 @@ If you have a [Tempest](https://tempest.earth/tempest-home-weather-system/) pers **Tempest data supplements NWS.** NWS provides authoritative alert text, detailed narrative forecasts, and broad coverage, while Tempest provides hyper-local precision at your exact station location. When a Tempest station is within range, StormScope uses Tempest values for temperature, feels-like, humidity, wind, and pressure, and sets `data_source: "tempest"` in the response. -If the Tempest API is unavailable, all tools fall back to NWS data without error. +If the Tempest API is unavailable, all tools fall back to NWS data. ### Setup @@ -122,7 +121,7 @@ All location-aware tools accept optional `latitude`/`longitude`, falling back to Upper-air data provided by [Open-Meteo](https://open-meteo.com/) under CC-BY 4.0. Vorticity is derived from model wind fields at ~110km grid spacing, which captures synoptic-scale features (shortwave troughs, jet maxima) but not mesoscale detail. -Soundings come from the NWS radiosonde network via IEM, launched around 00Z and 12Z from roughly 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. `get_sounding` with `source=observed` reports the site's distance and bearing from you and adds a note when it is far or old. Use `source=model` for a profile at your exact location or a forecast hour (up to 48). Both report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below ~5 km. Index calculations use [MetPy](https://unidata.github.io/MetPy/). +Soundings come from the NWS radiosonde network via IEM from roughly 85 US sites, so the nearest site can be hundreds of kilometers away and up to 12 hours old. `get_sounding` with `source=observed` reports the site's distance and bearing from you and adds a note when it is far or old. Use `source=model` for a profile at your exact location or a forecast hour (up to 48). Both report surface-based CAPE/CIN, LCL/LFC/EL, freezing level, lapse rates, precipitable water, 0-1 and 0-6 km bulk shear, 0-1 and 0-3 km storm-relative helicity, and temperature inversions below ~5 km. Index calculations use [MetPy](https://unidata.github.io/MetPy/). ### Example conversation @@ -149,15 +148,6 @@ Radar: KMPX, latest scan 12:00Z, N0B/N0S available Day 2: TSTM, Day 3: NONE ``` -## Skill suggestions - -Create `.claude/skills/` skills for common patterns: - -- **Morning briefing**: `get_briefing detail=full` for a full picture to start the day -- **Quick check**: `get_conditions` for just current conditions -- **Evening review**: `get_forecast mode=daily days=2` for tonight and tomorrow -- **Chase prep**: `get_spc_outlook outlook_type=tornado` + `get_surface_analysis` + `get_upper_air` + `get_sounding` + `get_radar` + `get_alerts detail=full` - ## Using from scripts The tools can be called without an AI assistant or a running server. FastMCP's in-memory client talks to the server object directly, so the script starts, makes its calls and exits. From 4404fe091c3411fcd9207b1521f368450d47e74b Mon Sep 17 00:00:00 2001 From: Jade Michael Thornton Date: Sun, 20 Sep 2026 17:56:20 -0500 Subject: [PATCH 5/5] more changes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 92d3ad4..af6c574 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ All location-aware tools accept optional `latitude` and `longitude` parameters. 1. **Explicit `latitude`/`longitude` params**. The AI can pass coordinates for any location 2. **Tempest station location** (opt-in). Set `USE_TEMPEST_STATION_GEOLOCATION=true` with a configured station to use its coordinates 3. **`PRIMARY_LATITUDE`/`PRIMARY_LONGITUDE` env vars**. These are precise and recommended for your home location -4. **macOS CoreLocation** (opt-in). Set `ENABLE_CORELOCATION=true` to use it. It requires Xcode Command Line Tools, has ~100m WiFi-based accuracy, and prompts for location permission on first use. It compiles a small Swift helper into `~/Library/Application Support/stormscope/` +4. **macOS CoreLocation** (opt-in). Set `ENABLE_CORELOCATION=true` to use it. It requires Xcode Command Line Tools, has ~100m WiFi-based accuracy, and prompts for location permission on first use. Compiles a small Swift helper into `~/Library/Application Support/stormscope/` 5. **IP geolocation** via [ipinfo.io](https://ipinfo.io). This is automatic, with city-level accuracy and one request per session Setting `DISABLE_AUTO_GEOLOCATION=true` disables both CoreLocation and IP geolocation (tiers 4 and 5). With auto-geolocation disabled and no env vars or explicit params, tools return an error.