Skip to content
Conduit

mcp server

nws-weather-mcp-server

Get US weather forecasts, active alerts, and current observations via the National Weather Service API. STDIO or Streamable HTTP.

cyanheads/nws-weather-mcp-servercommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • Node.js 20 or newer
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "nws-weather-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "@cyanheads/nws-weather-mcp-server"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 17, 2026

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://nws.caseyjhand.com/mcp


Overview

Real-time US weather from the National Weather Service: forecasts, active alerts, current conditions, and forecaster discussions for any point in the 50 states and US territories, plus zone forecasts, coastal and marine alerts, and a week of station history. No API key required.

Tools

ToolDescription
nws_get_forecast7-day or hourly forecast for coordinates. Resolves NWS grid internally.
nws_search_alertsActive weather alerts filtered by area, point, zone, event, severity, urgency, certainty, and status.
nws_get_alertOne alert message by ID, current or superseded (~7-day retention).
nws_get_alert_countsActive alert counts nationwide, per state/territory or marine area, and per marine region.
nws_get_observationsCurrent conditions by coordinates (nearest station) or station ID.
nws_get_observation_historyA station's recent observations, newest first, paged back through the ~7 days NWS keeps.
nws_find_stationsNearby observation stations sorted by distance with bearing.
nws_list_alert_typesAll valid alert event type names for filter discovery.
nws_get_office_discussionLatest narrative product (AFD, HWO, ZFP, SPS) from a Weather Forecast Office; a product too large to inline comes back as a section outline.
nws_get_zone_forecastText forecast periods for an NWS forecast zone.

Resources

ResourceDescription
nws://alert-typesStatic list of all valid NWS alert event type names.

Also reachable via the nws_list_alert_types tool, for MCP clients that don't support resources.

Capability reference

nws_get_forecast tool

  • latitude + longitude; returns 14 named 12-hour periods (~7 days) by default, or with hourly: true one-hour periods with dewpoint and humidity, 48 per page of the ~156 upstream
  • Returns the forecastZone and county zone codes for chaining into nws_search_alerts
  • Marine coordinates fail with marine_forecast_unsupported, and land points NWS serves no forecast grid for fail with no_forecast_grid

nws_search_alerts tool

  • At most one location filter (area, point, zone, region_type, or region), or none for a national search; event matches case-insensitively and partially; status defaults to Actual (also Exercise, System, Test, Draft)
  • limit (default 25) is capped at 25; a larger limit is served as 25 and reported through requestedLimit/effectiveLimit
  • Each affectedZones entry carries its zone type (forecast/county/fire); references lists superseded messages newest first by sent; a point outside NWS coverage fails with invalid_point

nws_get_alert tool

  • alert_id: an alert id from nws_search_alerts, or a references[].identifier from any alert; returns { alert } in the same shape as nws_search_alerts, including superseded messages
  • A malformed ID, an unknown one, and one past NWS's ~7-day retention all fail with alert_not_found

nws_get_alert_counts tool

  • No input; returns national totalAlerts (landAlerts + marineAlerts), plus areas counts keyed by state/territory or marine area code and regions counts keyed by marine region (AL, AT, GL, GM, PA, PI), each listing only codes with an active alert
  • Counts cover every message status, Test and Exercise included, so totalAlerts can exceed a national nws_search_alerts totalCount (status: Actual by default); an alert counts once in each area its zones fall in, so areas can sum past totalAlerts

nws_get_observations tool

  • Look up by coordinates (resolves nearest station) or station_id directly
  • Dual-unit display on every measurement (F/C, mph/km/h, inHg/hPa, mi/km); observations older than 2 hours carry a staleness notice, and a separate warning flags a station with most measurements unavailable

nws_get_observation_history tool

  • station_id (from nws_find_stations); optional start (inclusive) and end (exclusive) as ISO 8601 date-times with seconds and an offset; newest first, back through the ~7 days NWS keeps
  • limit (default 24) is capped at 100; a larger limit is served as 100 and reported through requestedLimit/effectiveLimit
  • Each observation carries the nws_get_observations measurement fields, null where the station reported nothing; an unknown station fails with station_not_found, and a malformed window or a start not before end with invalid_time_window
  • nextCursor appears only when older observations remain; there is no totalCount, since NWS reports none for a window

nws_find_stations tool

  • latitude + longitude; optional limit (default 10) is capped at 50; a larger limit is served as 50 and reported through requestedLimit/effectiveLimit
  • Nearest first; each result carries the station ID for nws_get_observations, distance (km), bearing, zone codes, elevation, and time zone

nws_list_alert_types tool

  • Returns the full set of event types the NWS API recognizes (e.g., "Tornado Warning", "Heat Advisory")
  • Use to discover valid values for the event filter in nws_search_alerts

nws_get_office_discussion tool

  • office: usually the 3-letter WFO code (e.g., "SEW" for Seattle) returned as the office field by nws_get_forecast; product_type: AFD (default), HWO, ZFP, or SPS
  • Returns productText plus issuanceTime, issuingOffice, productName, productCode, wmoCollectiveId; an unknown office, or one with no current product of the requested type, fails with no_products
  • A product too large to inline (most ZFPs) returns an outline of its sections instead of productText; pass sections (AFD section names, or zone codes for ZFP/HWO/SPS) to get the matching sections, and an unknown name fails with unknown_section

nws_get_zone_forecast tool

  • zone_id: forecast zone code (e.g., "WAZ315") — returned by nws_get_forecast (forecastZone), nws_find_stations (forecastZone column), and nws_search_alerts (the code of an affectedZones entry with type: "forecast")
  • Returns named periods (e.g., "Today", "Tonight", "Monday") with narrative text from local forecasters
  • County (XXC###), fire, and unknown zone codes fail with zone_not_found; marine zones with no text forecast fail with marine_forecast_unsupported, and land zones with none with zone_forecast_unavailable

nws://alert-types resource

  • Static list of all valid NWS alert event type names, returned as application/json
  • No parameters; cached publicly for 1 hour

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.

NWS-specific:

  • Sends the required User-Agent header automatically (configurable via NWS_USER_AGENT) — NWS returns 403 without one
  • Automatic coordinate-to-grid resolution via /points, cached for 1h since grid cells rarely change
  • Request timeouts plus retry/backoff for transient NWS API failures
  • Zero-auth access — no API keys required
  • Paged results — pass the returned nextCursor back as cursor for the next page (omitted on the last page)

Agent-friendly output:

  • Provenance — responses echo office codes, time zones, and zone codes so agents can chain into nws_get_office_discussion, nws_get_zone_forecast, and nws_search_alerts
  • Guidance over silence — empty, truncated, or cursor-past-end results carry a notice naming the cause and the next step
  • Typed error reasons (invalid_area_code, no_products, zone_not_found, …) so callers branch on data, not string parsing
  • Dual-unit measurements (F/C, mph/km/h, inHg/hPa, mi/km), rounded to match the text output

Getting started

Public Hosted Instance

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

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

Self-Hosted / Local

Add the following to your MCP client configuration file.

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

Or with npx (no Bun required):

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

Or with Docker:

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

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

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

Prerequisites

Installation

  1. Clone the repository:
git clone https://github.com/cyanheads/nws-weather-mcp-server.git
  1. Navigate into the directory:
cd nws-weather-mcp-server
  1. Install dependencies:
bun install

Configuration

VariableDescriptionDefault
NWS_USER_AGENTUser-Agent for NWS API requests. The API requires this header.(nws-weather-mcp-server, ...)
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_SESSION_MODEHTTP session mode: stateful, stateless, or auto.stateless
MCP_LOG_LEVELLog level: debug, info, notice, warning, error.info

See .env.example for the full list including auth, storage, and OpenTelemetry options.

Running the server

Local development

  • Build and run the production version:

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

    bun run devcheck     # Lints, formats, type-checks
    bun run test         # Runs test suite
    

Project structure

DirectoryPurpose
src/index.tscreateApp() entry point — registers tools and the resource.
src/mcp-server/tools/definitions/Tool definitions (*.tool.ts).
src/mcp-server/resources/definitions/Resource definitions (*.resource.ts).
src/services/nws/NWS API client and response types.
src/config/Environment variable parsing and validation with Zod.
tests/Unit and integration tests mirroring src/.

Development guide

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

  • Handlers throw, framework catches — no try/catch in tool logic
  • Use ctx.log for domain-specific logging, ctx.state for storage
  • Add new tools/resources to the barrel exports and the createApp() arrays in src/index.ts
  • Wrap NWS API calls: validate raw JSON → normalize to domain types → return the output schema; never fabricate missing fields

Contributing

Issues are welcome. Run checks before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

↑↓ navigate openesc close