Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4

- uses: astral-sh/setup-uv@v5
with:
python-version: ${{ matrix.python-version }}
enable-cache: true

- run: uv sync --group dev

- run: uv run python -m pytest

build-mcpb:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "22"

- name: install mcpb cli
run: npm install -g @anthropic-ai/mcpb

- name: build mcpb bundle
run: mcpb pack . stormscope.mcpb

- name: extract changelog
id: changelog
run: |
# extract the first version section from CHANGELOG.md
changelog=$(awk '/^## /{if(found) exit; found=1; next} found{print}' CHANGELOG.md)
# write to file for gh release to consume
echo "$changelog" > release_notes.txt

- name: create github release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
stormscope.mcpb \
--title "StormScope ${{ github.ref_name }}" \
--notes-file release_notes.txt
17 changes: 17 additions & 0 deletions .mcpbignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
tests/
.venv/
__pycache__/
*.pyc
.pytest_cache/
.mypy_cache/
*.egg-info/
.github/
.git/
.cursor/
.claude/
coverage/
htmlcov/
*.md
LICENSE
stormscope-architecture.md
uv.lock
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ Most tools support a `detail` parameter: **standard** gives a clean summary, **f

## Installation

### Claude Desktop

[Download the latest StormScope extension](https://github.com/thornjad/stormscope/releases/latest/download/stormscope.mcpb), then double-click the file or drag it into the Claude Desktop window. A settings dialog will appear where you can enter your location coordinates and optional Tempest station configuration. No additional software required.

### Claude Code

Requires Python 3.11+ and [uv](https://docs.astral.sh/uv/).

```bash
Expand Down Expand Up @@ -64,9 +70,11 @@ 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** — 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/`
4. **macOS CoreLocation** (opt-in, macOS only) — 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

On Linux, tiers 1-3 and 5 work identically. CoreLocation is skipped automatically. For precise location on Linux, set `PRIMARY_LATITUDE`/`PRIMARY_LONGITUDE` or use a Tempest station.

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
Expand Down
11 changes: 11 additions & 0 deletions icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
135 changes: 135 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
{
"manifest_version": "0.4",
"name": "stormscope",
"display_name": "StormScope",
"version": "1.4.4",
"description": "Real-time US weather data: conditions, forecasts, alerts, severe weather outlooks, radar, upper-air analysis, and surface fronts",
"long_description": "StormScope brings real-time US weather intelligence to Claude. It aggregates data from NWS, NOAA Storm Prediction Center, Weather Prediction Center, Iowa Environmental Mesonet radar, and Open-Meteo upper-air model data into 9 tools that give Claude deep weather awareness.\n\nCapabilities include current conditions, multi-format forecasts (daily narrative, hourly, raw gridpoint), active weather alerts with severity filtering, SPC severe weather outlooks (categorical and probabilistic), national severe outlook with region descriptions, NEXRAD radar metadata, 500mb upper-air analysis with derived vorticity, surface frontal analysis with warm/cold sector detection, and a combined briefing that adapts to the situation.\n\nOptionally integrates with your WeatherFlow Tempest personal weather station for hyper-local sensor data: solar radiation, UV index, lightning strikes, air density, and wet bulb temperature.\n\nUS locations only. Covers all 50 states, DC, and US territories.",
"author": {
"name": "Jade Michael Thornton",
"url": "https://jmthornton.net"
},
"repository": {
"type": "git",
"url": "https://github.com/thornjad/stormscope.git"
},
"homepage": "https://github.com/thornjad/stormscope",
"support": "https://github.com/thornjad/stormscope/issues",
"icon": "icon.svg",
"license": "ISC",
"keywords": ["weather", "nws", "noaa", "spc", "radar", "forecast", "alerts", "severe-weather", "tempest"],
"server": {
"type": "uv",
"entry_point": "src/stormscope/server.py",
"mcp_config": {
"command": "uv",
"args": ["run", "--directory", "${__dirname}", "stormscope"],
"env": {
"PRIMARY_LATITUDE": "${user_config.primary_latitude}",
"PRIMARY_LONGITUDE": "${user_config.primary_longitude}",
"UNITS": "${user_config.units}",
"TEMPEST_TOKEN": "${user_config.tempest_token}",
"TEMPEST_STATION_ID": "${user_config.tempest_station_id}",
"TEMPEST_STATION_NAME": "${user_config.tempest_station_name}",
"USE_TEMPEST_STATION_GEOLOCATION": "${user_config.use_tempest_station_geolocation}",
"ENABLE_CORELOCATION": "${user_config.enable_corelocation}"
}
}
},
"tools": [
{
"name": "get_conditions",
"description": "Get current weather conditions: temperature, wind, humidity, sky, pressure"
},
{
"name": "get_forecast",
"description": "Get weather forecast in daily narrative, hourly, or raw gridpoint format"
},
{
"name": "get_alerts",
"description": "Get active weather alerts with severity filtering"
},
{
"name": "get_spc_outlook",
"description": "Check SPC severe weather outlook: categorical risk or probabilistic tornado/wind/hail"
},
{
"name": "get_national_outlook",
"description": "Get CONUS-wide SPC severe weather risk areas with region descriptions"
},
{
"name": "get_radar",
"description": "Get NEXRAD radar info with weather summary and imagery links"
},
{
"name": "get_upper_air",
"description": "Get 500mb upper-air analysis: heights, temperature, wind, and derived vorticity"
},
{
"name": "get_surface_analysis",
"description": "Get surface analysis: fronts, pressure centers, warm/cold sector detection"
},
{
"name": "get_briefing",
"description": "Get a comprehensive weather briefing combining conditions, forecast, alerts, and outlook"
}
],
"compatibility": {
"platforms": ["darwin", "linux"],
"runtimes": {
"python": ">=3.11"
}
},
"user_config": {
"primary_latitude": {
"type": "number",
"title": "Primary Latitude",
"description": "Default latitude for weather queries (e.g. 44.98 for Minneapolis)",
"required": true,
"min": -90,
"max": 90
},
"primary_longitude": {
"type": "number",
"title": "Primary Longitude",
"description": "Default longitude for weather queries (e.g. -93.27 for Minneapolis)",
"required": true,
"min": -180,
"max": 180
},
"units": {
"type": "string",
"title": "Units",
"description": "Unit system: 'us' for Fahrenheit/mph or 'si' for Celsius/km/h",
"default": "us"
},
"tempest_token": {
"type": "string",
"title": "Tempest Token",
"description": "WeatherFlow Tempest Personal Access Token (optional, enables hyper-local station data)",
"sensitive": true
},
"tempest_station_id": {
"type": "string",
"title": "Tempest Station ID",
"description": "Specific Tempest station ID to use (optional, auto-discovers nearest if omitted)"
},
"tempest_station_name": {
"type": "string",
"title": "Tempest Station Name",
"description": "Tempest station name to match instead of ID (optional)"
},
"use_tempest_station_geolocation": {
"type": "boolean",
"title": "Use Tempest Station Location",
"description": "Use your Tempest station's GPS coordinates as the default location",
"default": false
},
"enable_corelocation": {
"type": "boolean",
"title": "Enable macOS CoreLocation",
"description": "Use macOS WiFi-based location detection as fallback (macOS only, requires Xcode Command Line Tools)",
"default": false
}
}
}
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading