io.github.cyanheads/nws-weather-mcp-server

Official registry Maps, travel and weather

Get US weather forecasts, active alerts, and current observations.

What can you do with io.github.cyanheads/nws-weather-mcp-server?

  • 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)
  • 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

Install

Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).

Remote (streamable-http)
Claude Code
claude mcp add --transport http nws-weather-mcp-server 'https://nws.caseyjhand.com/mcp'
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "nws-weather-mcp-server": {
            "type": "http",
            "url": "https://nws.caseyjhand.com/mcp"
        }
    }
}
NPM package @cyanheads/nws-weather-mcp-server
Claude Code
claude mcp add nws-weather-mcp-server -e 'NWS_USER_AGENT=(nws-weather-mcp-server, github.com/cyanheads/nws-weather-mcp-server)' -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/nws-weather-mcp-server@0.11.2
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "nws-weather-mcp-server": {
            "command": "npx",
            "args": [
                "-y",
                "@cyanheads/nws-weather-mcp-server@0.11.2"
            ],
            "env": {
                "NWS_USER_AGENT": "(nws-weather-mcp-server, github.com/cyanheads/nws-weather-mcp-server)",
                "MCP_LOG_LEVEL": "info"
            }
        }
    }
}

Environment variables

  • NWS_USER_AGENT User-Agent header for NWS API requests. The API requires this header but a default is provided.
  • MCP_LOG_LEVEL Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').
NPM package @cyanheads/nws-weather-mcp-server
Claude Code
claude mcp add nws-weather-mcp-server -e 'MCP_TRANSPORT_TYPE=<MCP_TRANSPORT_TYPE>' -e 'NWS_USER_AGENT=(nws-weather-mcp-server, github.com/cyanheads/nws-weather-mcp-server)' -e 'MCP_HTTP_HOST=127.0.0.1' -e 'MCP_HTTP_PORT=3010' -e 'MCP_HTTP_ENDPOINT_PATH=/mcp' -e 'MCP_AUTH_MODE=none' -e 'MCP_LOG_LEVEL=info' -- npx -y @cyanheads/nws-weather-mcp-server@0.11.2
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "nws-weather-mcp-server": {
            "command": "npx",
            "args": [
                "-y",
                "@cyanheads/nws-weather-mcp-server@0.11.2"
            ],
            "env": {
                "MCP_TRANSPORT_TYPE": "<MCP_TRANSPORT_TYPE>",
                "NWS_USER_AGENT": "(nws-weather-mcp-server, github.com/cyanheads/nws-weather-mcp-server)",
                "MCP_HTTP_HOST": "127.0.0.1",
                "MCP_HTTP_PORT": "3010",
                "MCP_HTTP_ENDPOINT_PATH": "/mcp",
                "MCP_AUTH_MODE": "none",
                "MCP_LOG_LEVEL": "info"
            }
        }
    }
}

Environment variables

  • MCP_TRANSPORT_TYPE Selects the HTTP transport.
  • NWS_USER_AGENT User-Agent header for NWS API requests. The API requires this header but a default is provided.
  • MCP_HTTP_HOST The hostname for the HTTP server.
  • MCP_HTTP_PORT The port to run the HTTP server on.
  • MCP_HTTP_ENDPOINT_PATH The endpoint path for the MCP server.
  • MCP_AUTH_MODE Authentication mode to use: 'none', 'jwt', or 'oauth'.
  • MCP_LOG_LEVEL Sets the minimum log level for output (e.g., 'debug', 'info', 'warn').

Documentation

From the project's README on GitHub, refreshed weekly. Links open on GitHub.

Contents
  1. @cyanheads/nws-weather-mcp-server
  2. Overview
  3. Capability reference
  4. Features
  5. Getting started
  6. Configuration
  7. Running the server
  8. Project structure
  9. Development guide
  10. Contributing
  11. License

@cyanheads/nws-weather-mcp-server

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

10 Tools • 1 Resource

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, FWF) 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
  • nextCursor carries its mode, so an hourly walk continues hourly without resending hourly: true
  • include_amounts: true adds every native quantitativePrecipitation, snowfallAmount, and iceAccumulation interval as precipitationAmounts (layer, uom, values with validTime and value), plus the separate amountsUpdateTime. Default false; resend it on any cursor page that needs amounts. Interval strings, units, zeroes, and nulls stay unchanged. Missing layers and unavailable amounts are explained in notice; present empty layers carry values: []. Absent units or update time are null. An unavailable amount feed leaves the main forecast available.
  • Returns updateTime, when the grid's forecast data was last updated, beside generatedAt; a notice flags a grid not updated in more than 24 hours
  • 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
  • nextCursor carries the query's filters and page size, so pass it back as cursor on its own; filters sent with it are ignored
  • 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
  • Each alert carries office (the issuing office code for nws_get_office_discussion, e.g. RIW), raw vtec strings, the nwsHeadline, and hazard tags such as maxHailSize and maxWindGust, verbatim

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, in/mm), temperatures to one decimal; 1-, 3-, and 6-hour precipitation amounts from hourly reports, with 0 a trace and null no amount reported; 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, SPS, or FWF (Fire Weather Planning Forecast)
  • Returns productText plus issuanceTime, issuingOffice, productName, productCode, wmoCollectiveId; content[] carries the product text in a text code block, so fixed-width tables keep their columns; 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 and FWFs) returns an outline of its sections instead of productText; pass sections (AFD section names, or zone codes for ZFP/HWO/SPS/FWF) to get the matching sections, and an unknown name fails with unknown_section
  • An alert zone typed fire gets its forecast from the FWF: office from the alert's office field, product_type: "FWF", sections: [<zone code>]

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###) and unknown zone codes fail with zone_not_found, and so do most fire zone codes, whose forecast is their segment of the office FWF on nws_get_office_discussion; a fire code that is also a public zone code returns the public zone's forecast; 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, in/mm), 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. It serves Streamable HTTP; each client takes its own config shape.

For Claude Code:

claude mcp add --transport http nws-weather-mcp-server https://nws.caseyjhand.com/mcp

For Cline (cline_mcp_settings.json):

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

For Cursor (mcp.json):

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

Claude Desktop adds remote servers under Settings → Connectors.

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.

Frequently asked questions

What is io.github.cyanheads/nws-weather-mcp-server?

Get US weather forecasts, active alerts, and current observations.

How do I install io.github.cyanheads/nws-weather-mcp-server?

It runs as a remote server. In Claude Code: claude mcp add --transport http nws-weather-mcp-server 'https://nws.caseyjhand.com/mcp'. For other clients, paste the JSON configuration from this page into their MCP settings.

Does io.github.cyanheads/nws-weather-mcp-server need an API key?

Its registry entry lists no required key or secret. Some features may still need an account with the service it connects to.

Is io.github.cyanheads/nws-weather-mcp-server open source?

Yes. Its code is on GitHub under the Apache-2.0 license.

Who maintains io.github.cyanheads/nws-weather-mcp-server?

It is published by cyanheads. AI.tn lists it but does not maintain or endorse it.

From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.