Back to Directory/Developer Tools

io.github.cyanheads/noaa-spaceweather-mcp-server

NOAA SWPC space weather: storm scales, Kp index, aurora forecasts, solar wind, activity, alerts.

Developer ToolsTypeScriptv0.3.1

@cyanheads/noaa-spaceweather-mcp-server

Query NOAA SWPC space weather: geomagnetic storm scales, Kp index, aurora forecasts, solar wind, solar activity, and alerts via MCP. STDIO or Streamable HTTP.

6 Tools

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework


Overview

Space weather from NOAA's Space Weather Prediction Center (SWPC) — geomagnetic storm scales, Kp index, aurora forecasts, solar wind, solar activity, and active alerts. Query current conditions, aurora visibility at a coordinate, or windowed plasma and magnetic-field time series from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.

Tools

ToolDescription
noaa_spaceweather_get_conditionsCurrent space-weather snapshot: NOAA R/S/G storm scales for yesterday, today, and the 3-day forecast, latest Kp, a plain-language status summary, and optionally SWPC's forecast discussion explaining the forecast
noaa_spaceweather_get_kp_indexPlanetary K-index (0–9) — recent observed 3-hour values with G-scale equivalents and aurora-latitude guidance, plus 3-day forecast
noaa_spaceweather_get_aurora_forecastOVATION model aurora forecast: global probability grid, optional local lookup by coordinates with a daylight-aware go/no-go verdict and a poleward horizon reading
noaa_spaceweather_get_solar_windReal-time solar wind from the active L1 spacecraft: speed, proton density, temperature, and the critical Bz component with the window's most southward reading — explains why current geomagnetic conditions exist
noaa_spaceweather_get_solar_activitySolar flare picture: discrete flare events with peak class and R-scale level, GOES X-ray flux, the daily F10.7 cm radio flux, 3-day flare-class probabilities, active solar regions with same-day flare counts and next-day probabilities, and solar radiation storm level
noaa_spaceweather_get_alertsActive SWPC alerts, watches, and warnings — structured records with product type, severity, issue time, validity window, and full message text

Capability reference

noaa_spaceweather_get_conditions tool

  • include_discussion (bool, default false) is the only input — otherwise a single call composing storm scales and current Kp into one snapshot
  • Returns today's observed R/S/G storm levels plus SWPC's 3-day forecast series, which starts with today
  • yesterday carries the R/S/G levels SWPC assessed for the previous UTC day, with its date and no time — the feed states only when it was generated. Null when the feed carries no previous-day period
  • Forecast days carry what SWPC issues: a G level, and for R and S a probability — R1–R2, R3 or greater, S1 or greater — with no level. A null level means SWPC forecasts none for that day, which is not the same as level 0
  • Current Kp with G-scale equivalent and aurora-visibility latitude guidance
  • With include_discussion, the forecaster-written Forecast Discussion split into its topic sections (Solar Activity, Energetic Particle, Solar Wind, Geospace), each with its 24-hour summary and 3-day forecast text
  • Data sourced from the noaa-scales.json + noaa-planetary-k-index.json feeds, plus the discussion.txt product when the discussion is requested

noaa_spaceweather_get_kp_index tool

  • window_days (1–7, default 1) bounds the observed series; the forecast series is always SWPC's full 3-day forecast
  • Each observed/forecast record carries Kp, G-scale equivalent, G-scale label, and aurora-latitude guidance
  • G levels follow SWPC's minus-third band floors — G1 starts at Kp 4.67 (5−), G4 runs through 8.67 (9−), and only Kp 9 is G5
  • Forecast excludes the feed's embedded historical "observed" entries — only forward-looking estimated/predicted rows
  • observedCount reports how many observed readings matched the window

noaa_spaceweather_get_aurora_forecast tool

  • Without coordinates: global metadata only — grid point count, global peak probability, peak region
  • With latitude/longitude (WGS84, required together): nearest 1°-grid lookup, the centered-dipole geomagnetic latitude those coordinates convert to, the minimum Kp and G level needed at that geomagnetic latitude, and a plain-language go/no-go verdict
  • Darkness gating: the sun's elevation at the coordinates at the forecast time (sunElevationDeg) and the sky state it implies (darkness: day, civil_twilight, nautical_twilight, dark). In daylight the verdict reports aurora as not visible whatever the model probability; in twilight it adds that only bright aurora will show
  • Horizon view: the strongest reading within 1000 km poleward and ±2° longitude (horizonMaxPercent, horizonMaxLatitude, horizonDistanceKm). When it reaches 10% and beats the overhead reading outside daylight, the verdict adds that aurora may be visible low on the poleward horizon
  • invalid_coordinates error when only one of the pair is supplied
  • OVATION model updates every ~5 minutes; forecast horizon is ~30–60 minutes ahead

noaa_spaceweather_get_solar_wind tool

  • window_hours (1–168, default 3) slices client-side from a feed that carries roughly the last 24 hours at ~1-minute cadence
  • resolution (summary, reduced default, or full) sets the series detail. reduced bounds each returned series to 200 records: the window is bucketed by record count and one real measurement is emitted per bucket — the bucket's fastest speed for plasma, its most southward Bz for mag — with the newest record in the window always last. A series already inside the bound comes back untouched, so a default 3-hour call is unaffected; full returns every record (~1,400 per series over 24 hours); summary returns both series empty and keeps every headline field, about 2 KB whatever the window
  • Plasma (speed, density, temperature) and magnetic field (Bx/By/Bz/Bt GSM) returned as separate oldest-first series
  • bzStatus surfaces southward Bz (the storm driver) as a plain-language field, and bzMinInWindow with its time tag reports the window's most southward reading
  • Window statistics: speedMaxInWindow with its time tag, densityMaxInWindow, btMaxInWindow, and bzSouthMinutesInWindow — the count of 1-minute records with Bz below 0, so a gap in the feed adds nothing. Every headline field is computed from the full window, before any reduction, at every resolution
  • latestFeedPlasmaTime/latestFeedMagTime/feedStalenessHours distinguish an empty window from a stale feed
  • Every record names its reporting spacecraft — no satellite is assumed as "the" active one

noaa_spaceweather_get_solar_activity tool

  • include_regions (default true) toggles per-region active-solar-region detail to control response size
  • flare_hours (1–168, default 24) bounds the discrete flare events returned, filtered on each flare's onset; the feed keeps a rolling 7 days, so 168 returns everything it carries
  • Flare events come with the classes SWPC publishes — onset, peak, and decay, each with magnitude — the peak flux, and the NOAA R-scale level (0–5) that flux implies. Decay time and class are null while a flare is still in progress, and an empty window names the newest flare the feed holds
  • GOES X-ray flux (0.1–0.8 nm) with flare-class letter (A/B/C/M/X), the class with magnitude (flareClassFull, derived by SWPC's truncation rule so it agrees with the published flare classes), and the unformatted flux alongside the display string; recent readings cover the past hour
  • Daily F10.7 cm solar radio flux in sfu with its 90-day mean, from the Noon Penticton report — the value SWPC reports for the day. It can be up to ~24 h old, so its observation time rides with it
  • 3-day C/M/X flare-class and proton-event probabilities under date-neutral names (cClassProbability, mClassProbability, xClassProbability, protonEventProbability); the deprecated *1Day names still carry the same values in structuredContent
  • Each active region carries the C/M/X flare counts SWPC attributed to it on its observation day — the flare events carry no region, so these name the region driving current activity — its sunspot area in millionths of the hemisphere, and when SWPC first recorded it. Its flare probabilities cover the following day. A spotless region (plage) reads as such, with a null area
  • Integral proton flux (≥10 MeV) drives the reported NOAA S-scale (0–5)
  • Data sourced from the goes/primary/xrays-6-hour.json, goes/primary/xray-flares-7-day.json, f107_cm_flux.json, solar_probabilities.json, goes/primary/integral-protons-plot-3-day.json, and solar_regions.json feeds

noaa_spaceweather_get_alerts tool

  • active_only (default true) — in-force Warnings/Watches/Alerts only. A product stays in force until the feed says otherwise, so this also drops any product a later cancellation names by serial, and all but the newest Watch carrying THIS SUPERSEDES ANY/ALL PRIOR WATCHES IN EFFECT — alongside cancellations, Summaries, and products whose validity end has passed
  • max_age_hours (1–720, default 48) bounds how far back to look for candidates; the SWPC feed itself has no expiry. Under active_only=true it does not cut off a product whose validity end is still ahead, so a multi-day Watch survives until the last day it forecasts a storm for ends; under active_only=false it is a literal age cutoff
  • Each record carries product type, NOAA scale + level (0 means "no scale stated," not zero severity), serial number, parsed validity window, and full message text
  • cancelled flags a record that cancels a prior product rather than being active; the product it cancels is a separate record, excluded by the serial link rather than by this flag
  • Under active_only=true the response echoes the applied window and counts what it excluded, by reason — so an empty result reads as "quiet" or "everything was filtered" without a second call

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

SWPC-specific:

  • All SWPC feeds are public and keyless — no API keys required
  • Single SpaceWeatherService wraps every NOAA SWPC feed — the JSON products and the plain-text forecast discussion — behind one fetchWithTimeout + withRetry funnel, so both paths classify an upstream failure the same way — and every retry ladder runs inside one 45-second budget, so a hung upstream still returns the classified error before a 60-second client timeout
  • Heterogeneous feed normalization: interleaved multi-spacecraft records (solar wind), keyed objects (storm scales), coordinate triples (OVATION), section-delimited text (forecast discussion)
  • NOAA scale interpretation: raw Kp 6 → "G2 moderate storm — aurora possible to ~55° geomagnetic latitude"
  • Feed freshness surfaced per-response: solar wind updates ~1 min, aurora ~5 min, Kp 3-hour intervals

Agent-friendly output:

  • Observed timestamps on every response so agents can reason about data freshness
  • Plain-language summaries and verdicts alongside raw values — agents can display or reason without re-interpreting indices
  • Bz component surfaced as a first-class field in solar wind output (southward Bz = primary storm driver)
  • Typed error contracts with recovery hints, split on whether retrying can help: a transient feed failure is feed_unavailable → "Retry in 30–60 s"; a feed path SWPC no longer serves is feed_moved → "Retrying will not help", raised on the first attempt

Getting started

Public Hosted Instance

A public instance is available at https://noaa-spaceweather.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "noaa-spaceweather-mcp-server": {
      "type": "streamable-http",
      "url": "https://noaa-spaceweather.caseyjhand.com/mcp"
    }
  }
}

Self-Hosted / Local

Add the following to your MCP client configuration file.

{
  "mcpServers": {
    "noaa-spaceweather": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/noaa-spaceweather-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "noaa-spaceweather": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/noaa-spaceweather-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "noaa-spaceweather": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "ghcr.io/cyanheads/noaa-spaceweather-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.3.0 or higher (or Node.js v24+).
  • No API keys required — all SWPC feeds are public.

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/noaa-spaceweather-mcp-server.git
  1. Navigate into the directory:
cd noaa-spaceweather-mcp-server
  1. Install dependencies:
bun install
  1. Configure environment:
cp .env.example .env
# edit .env if needed — all defaults work out of the box

Configuration

VariableDescriptionDefault
MCP_TRANSPORT_TYPETransport: stdio or http.stdio
MCP_HTTP_PORTPort for HTTP server.3010
MCP_HTTP_HOSTHostname for HTTP server.127.0.0.1
MCP_HTTP_ENDPOINT_PATHEndpoint path./mcp
MCP_SESSION_MODEHTTP session mode. This project explicitly uses stateless; auto resolves to stateful.stateless
MCP_AUTH_MODEAuth mode: none, jwt, or oauth.none
MCP_LOG_LEVELLog level (RFC 5424).info
LOGS_DIRDirectory for log files (Node.js only).<project-root>/logs
STORAGE_PROVIDER_TYPEStorage backend.in-memory
OTEL_ENABLEDEnable OpenTelemetry instrumentation.false

No domain-specific API keys are required. See .env.example for the full list of optional overrides.


Running the server

Local development

  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
    
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec
    

Docker

docker build -t noaa-spaceweather-mcp-server .
docker run --rm -p 3010:3010 noaa-spaceweather-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/noaa-spaceweather-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.


Project structure

PathPurpose
src/index.tscreateApp() entry point — registers tools and inits the service.
src/services/space-weather/SpaceWeatherService — fetches and normalizes all NOAA SWPC feeds.
src/mcp-server/tools/definitions/Tool definitions (*.tool.ts) — one file per tool.
tests/Unit and integration tests mirroring src/.
docs/Design doc and directory tree.

Development guide

See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage
  • Register new tools via the barrel in src/mcp-server/tools/definitions/index.ts
  • Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

Installation

Source-derived launch command. Check the maintainer’s required arguments and credentials before running:

bash
npx -y @cyanheads/noaa-spaceweather-mcp-server

Set up in your AI client

Merge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.

json
{
  "mcpServers": {
    "io-github-cyanheads-noaa-spaceweather-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@cyanheads/noaa-spaceweather-mcp-server"
      ]
    }
  }
}

Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.

Claude Desktop setup reference

Package

@cyanheads/noaa-spaceweather-mcp-servernpm

Compatible MCP Clients

io.github.cyanheads/noaa-spaceweather-mcp-server works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.

  • Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.
  • Cursor~/.cursor/mcp.jsonRestart Cursor for changes to take effect.
  • VS Code.vscode/mcp.jsonReload VS Code window for changes to take effect.
  • Windsurf~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect.
  • Claude Code.mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.

Learn More