nws-weather-mcp-server

v0.9.0 pre-1.0

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

nws.caseyjhand.com/mcp
claude mcp add --transport http nws-weather-mcp-server https://nws.caseyjhand.com/mcp
codex mcp add nws-weather-mcp-server --url https://nws.caseyjhand.com/mcp
{
  "mcpServers": {
    "nws-weather-mcp-server": {
      "url": "https://nws.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http nws-weather-mcp-server https://nws.caseyjhand.com/mcp
{
  "mcpServers": {
    "nws-weather-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://nws.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "nws-weather-mcp-server": {
      "type": "http",
      "url": "https://nws.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://nws.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "MCP-Protocol-Version: 2025-11-25" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

7

nws_get_forecast

Get the weather forecast for a US location. Returns either named 12-hour periods (default) or hourly breakdowns.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_get_forecast",
    "arguments": {
      "latitude": "<latitude>",
      "longitude": "<longitude>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "latitude": {
      "type": "number",
      "minimum": -90,
      "maximum": 90,
      "description": "Latitude in decimal degrees (e.g., 47.6062)."
    },
    "longitude": {
      "type": "number",
      "minimum": -180,
      "maximum": 180,
      "description": "Longitude in decimal degrees (e.g., -122.3321)."
    },
    "hourly": {
      "default": false,
      "description": "If true, returns hourly forecast (48 one-hour periods per page, ~156 available) instead of 12-hour named periods (14 periods). Hourly includes dewpoint and relative humidity.",
      "type": "boolean"
    },
    "cursor": {
      "description": "Opaque continuation token from a previous response's nextCursor, to retrieve the next 48 periods. Omit for the first page. Every call re-fetches the forecast, so consecutive periods are contiguous within one response; NWS reissues forecasts through the day, so a later call can window a regenerated period array.",
      "type": "string"
    }
  },
  "required": [
    "latitude",
    "longitude",
    "hourly"
  ],
  "additionalProperties": false
}
view source ↗

nws_search_alerts

Search active weather alerts (watches, warnings, advisories) across the US. Filter by state, coordinates, zone, land/marine region, event type, severity, urgency, or certainty. area, point, zone, region_type, and region are mutually exclusive — provide at most one. Omit all filters for a national search.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_search_alerts",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "area": {
      "description": "US state/territory code (e.g., \"WA\", \"OK\", \"PR\") or marine area code (e.g., \"GM\"). Mutually exclusive with point and zone.",
      "type": "string"
    },
    "point": {
      "description": "Coordinates as \"lat,lon\" (e.g., \"47.6,-122.3\"). Returns alerts whose geometry contains this point. Mutually exclusive with area and zone.",
      "type": "string"
    },
    "zone": {
      "description": "NWS forecast zone (e.g., \"WAZ558\") or county zone (e.g., \"WAC033\"). Mutually exclusive with area and point.",
      "type": "string"
    },
    "region_type": {
      "description": "Restrict to land-based or marine alerts. Mutually exclusive with area, point, zone, and region.",
      "type": "string",
      "enum": [
        "Land",
        "Marine"
      ]
    },
    "region": {
      "description": "Restrict to NWS marine region groups: \"AL\" (Alaska waters), \"AT\" (Atlantic Ocean), \"GL\" (Great Lakes), \"GM\" (Gulf of Mexico), \"PA\" (Eastern Pacific and US West Coast), \"PI\" (Central and Western Pacific). Marine alerts only — a land alert never matches. Mutually exclusive with area, point, zone, and region_type.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "AL",
          "AT",
          "GL",
          "GM",
          "PA",
          "PI"
        ]
      }
    },
    "event": {
      "description": "Filter to specific event types (e.g., [\"Tornado Warning\"]). Matches are case-insensitive and partial, so \"tornado\" matches both \"Tornado Warning\" and \"Tornado Watch\". Use nws_list_alert_types to discover valid names.",
      "type": "array",
      "items": {
        "type": "string"
      }
    },
    "severity": {
      "description": "Filter by severity level.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "Extreme",
          "Severe",
          "Moderate",
          "Minor",
          "Unknown"
        ]
      }
    },
    "urgency": {
      "description": "Filter by urgency level.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "Immediate",
          "Expected",
          "Future",
          "Past"
        ]
      }
    },
    "certainty": {
      "description": "Filter by certainty level.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "Observed",
          "Likely",
          "Possible",
          "Unlikely",
          "Unknown"
        ]
      }
    },
    "status": {
      "default": "Actual",
      "description": "Alert status filter. Default \"Actual\". Use a different value only when you specifically need non-live alerts.",
      "type": "string",
      "enum": [
        "Actual",
        "Exercise",
        "System",
        "Test",
        "Draft"
      ]
    },
    "limit": {
      "default": 25,
      "description": "Maximum number of alerts to include in this page (1-25, default 25). totalCount still reports the full number of distinct matches, so a small limit returns a digest of broad or national searches without dropping the total; pass the returned nextCursor as cursor to reach the rest.",
      "type": "integer",
      "minimum": 1,
      "maximum": 25
    },
    "cursor": {
      "description": "Opaque continuation token from a previous response's nextCursor. Omit for the first page. The token carries its own page size, so limit applies to the first page only. Every call re-fetches /alerts/active, so alerts are contiguous within one response but not across calls — the active set changes continuously as alerts are issued and expire, so a continued page covers the collection as it stands at that moment.",
      "type": "string"
    }
  },
  "required": [
    "status",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

nws_get_observations

Get current weather observations (actual measured conditions). Accepts coordinates (resolves nearest station automatically) or a station ID directly (e.g., "KSEA").

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_get_observations",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "latitude": {
      "description": "Latitude for automatic station resolution. Use with longitude. Ignored if station_id is provided.",
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "longitude": {
      "description": "Longitude for automatic station resolution. Use with latitude. Ignored if station_id is provided.",
      "type": "number",
      "minimum": -180,
      "maximum": 180
    },
    "station_id": {
      "description": "Station identifier directly (e.g., \"KSEA\", \"KORD\"). Use nws_find_stations to discover station IDs.",
      "type": "string"
    }
  },
  "additionalProperties": false
}
view source ↗

nws_find_stations

Find weather observation stations near a location. Returns stations sorted by proximity with distance and bearing. Use to discover station IDs for nws_get_observations.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_find_stations",
    "arguments": {
      "latitude": "<latitude>",
      "longitude": "<longitude>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "latitude": {
      "type": "number",
      "minimum": -90,
      "maximum": 90,
      "description": "Center latitude for proximity search."
    },
    "longitude": {
      "type": "number",
      "minimum": -180,
      "maximum": 180,
      "description": "Center longitude for proximity search."
    },
    "limit": {
      "default": 10,
      "description": "Max stations per page (1-50). totalCount still reports every station near the point, so pass the returned nextCursor as cursor to reach the rest.",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    },
    "cursor": {
      "description": "Opaque continuation token from a previous response's nextCursor. Omit for the first page. The token carries its own page size, so limit applies to the first page only. Every call re-fetches the station list, so pages are contiguous within one response; the registry changes rarely, but a later call can window an updated list.",
      "type": "string"
    }
  },
  "required": [
    "latitude",
    "longitude",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

nws_list_alert_types

List all valid NWS alert event type names. Use to discover valid values for the event filter in nws_search_alerts, or to browse alert categories. No parameters required.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_list_alert_types",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
view source ↗

nws_get_office_discussion

Get the latest narrative forecast product from a Weather Forecast Office (WFO). The default product is AFD (Area Forecast Discussion), which explains the meteorological reasoning behind the forecast — synoptic setup, model guidance, and forecaster confidence. Other types: HWO (Hazardous Weather Outlook, 1-7 day severe/flood/winter outlook), ZFP (Zone Forecast Product, zone-by-zone text), SPS (Special Weather Statement, short-fuse advisory). The office code is the 3-letter WFO identifier returned as the "office" field by nws_get_forecast.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_get_office_discussion",
    "arguments": {
      "office": "<office>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "office": {
      "type": "string",
      "minLength": 1,
      "description": "Three-letter Weather Forecast Office (WFO) code (e.g., \"SEW\" for Seattle, \"LOX\" for Los Angeles). Returned as the \"office\" field in nws_get_forecast output."
    },
    "product_type": {
      "default": "AFD",
      "description": "Product type code. AFD (Area Forecast Discussion) — meteorological reasoning, model analysis, forecaster confidence. HWO (Hazardous Weather Outlook) — 1-7 day outlook for severe weather, flooding, winter weather. ZFP (Zone Forecast Product) — detailed zone-by-zone text forecast. SPS (Special Weather Statement) — short-fuse advisory for notable non-warning weather.",
      "type": "string",
      "enum": [
        "AFD",
        "HWO",
        "ZFP",
        "SPS"
      ]
    }
  },
  "required": [
    "office",
    "product_type"
  ],
  "additionalProperties": false
}
view source ↗

nws_get_zone_forecast

Get the text forecast for a public NWS forecast zone. Returns named forecast periods (e.g., "Today", "Tonight", "Monday") with detailed narrative text — the human-readable, zone-level forecast written by local forecasters. Completes the alert-to-forecast chain: nws_search_alerts returns each affected zone in "affectedZones" as a code plus a type, and nws_find_stations returns codes in the "forecastZone" column. Only affectedZones entries with type "forecast" work here; entries typed "county" or "fire" have no text forecast upstream and will not resolve. Zone codes follow the pattern XXZ### (e.g., "WAZ315" for Western Washington lowlands).

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "nws_get_zone_forecast",
    "arguments": {
      "zone_id": "<zone_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "zone_id": {
      "type": "string",
      "minLength": 1,
      "description": "NWS public forecast zone code (e.g., \"WAZ315\" for the Western Washington lowlands including Seattle). Returned as \"forecastZone\" by nws_get_forecast and nws_find_stations, or as the \"code\" of an \"affectedZones\" entry with type \"forecast\" in nws_search_alerts. Format: two-letter state + \"Z\" + three-digit number."
    }
  },
  "required": [
    "zone_id"
  ],
  "additionalProperties": false
}
view source ↗

Resources

1

Static list of all valid NWS alert event type names. Useful reference when constructing event filters for nws_search_alerts.

uri nws://alert-types mime application/json