noaa-marine-mcp-server

v0.3.0 pre-1.0

Find NOAA tide stations and NDBC buoys, fetch tide predictions, water levels, tidal currents, and live buoy conditions via MCP. STDIO or Streamable HTTP.

noaa-marine.caseyjhand.com/mcp
claude mcp add --transport http noaa-marine-mcp-server https://noaa-marine.caseyjhand.com/mcp
codex mcp add noaa-marine-mcp-server --url https://noaa-marine.caseyjhand.com/mcp
{
  "mcpServers": {
    "noaa-marine-mcp-server": {
      "url": "https://noaa-marine.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http noaa-marine-mcp-server https://noaa-marine.caseyjhand.com/mcp
{
  "mcpServers": {
    "noaa-marine-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://noaa-marine.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "noaa-marine-mcp-server": {
      "type": "http",
      "url": "https://noaa-marine.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://noaa-marine.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

noaa_marine_find_stations

open-world

Find CO-OPS tide/water-level/current stations and NDBC buoys near a location or by name/state. Returns a unified station list with source, data capabilities, coordinates, and — for NDBC — the physical platform class. This is the required first step to resolve place names or coordinates to station IDs before calling data tools. CO-OPS station IDs are numeric (e.g. 9447130 for Seattle); current station IDs are alphanumeric (e.g. ACT4176). NDBC buoy IDs are 5-character alphanumeric codes (e.g. 46041). Two axes are reported separately: `capabilities`/`type` describe the data products a station serves (tide, current, water_level, met, current_profile), while `platform` is the NDBC physical classification (buoy, fixed, oilrig, dart, tao, usv, other). CO-OPS stations carry no platform class. Provide latitude and longitude together for proximity search, or query/state for name-based search — both may be combined. Note: CO-OPS current stations are cataloged by monitoring capability, not prediction availability. If noaa_marine_get_currents returns no_predictions for a station, try the next nearest current station.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_find_stations",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "latitude": {
      "description": "Center latitude in decimal degrees for proximity search. Required together with longitude — supplying only one is rejected rather than silently ignored. Optionally pair with radius_km.",
      "type": "number",
      "minimum": -90,
      "maximum": 90
    },
    "longitude": {
      "description": "Center longitude in decimal degrees for proximity search. Required together with latitude — supplying only one is rejected rather than silently ignored. Optionally pair with radius_km.",
      "type": "number",
      "minimum": -180,
      "maximum": 180
    },
    "radius_km": {
      "default": 100,
      "description": "Search radius in kilometers when latitude/longitude are provided. Defaults to 100 km.",
      "type": "number",
      "minimum": 1,
      "maximum": 1000
    },
    "query": {
      "description": "Station name substring to match, case-insensitive. E.g. \"seattle\", \"puget sound\". NDBC rows also match on station ID. Blank or whitespace-only values are treated as omitted.",
      "type": "string"
    },
    "state": {
      "description": "Filter by 2-letter US state or territory code. Applies to CO-OPS stations only — providing it restricts results to CO-OPS and excludes NDBC buoys (which carry no state). E.g. \"WA\", \"CA\", \"PR\".",
      "type": "string",
      "enum": [
        "AL",
        "AK",
        "AZ",
        "AR",
        "CA",
        "CO",
        "CT",
        "DE",
        "FL",
        "GA",
        "HI",
        "ID",
        "IL",
        "IN",
        "IA",
        "KS",
        "KY",
        "LA",
        "ME",
        "MD",
        "MA",
        "MI",
        "MN",
        "MS",
        "MO",
        "MT",
        "NE",
        "NV",
        "NH",
        "NJ",
        "NM",
        "NY",
        "NC",
        "ND",
        "OH",
        "OK",
        "OR",
        "PA",
        "RI",
        "SC",
        "SD",
        "TN",
        "TX",
        "UT",
        "VT",
        "VA",
        "WA",
        "WV",
        "WI",
        "WY",
        "DC",
        "PR",
        "VI",
        "GU",
        "AS",
        "MP"
      ]
    },
    "source": {
      "default": "all",
      "description": "Data source to search: coops (tide/water-level/current stations), ndbc (buoys), or all (default).",
      "type": "string",
      "enum": [
        "coops",
        "ndbc",
        "all"
      ]
    },
    "types": {
      "description": "Filter by data capability or NDBC platform class. Every returned station matches at least one requested value — a capability value against its capabilities list, or buoy against its platform class. Omit to return all stations.",
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "tide",
          "current",
          "water_level",
          "met",
          "current_profile",
          "buoy"
        ],
        "description": "Filter value. Five are data capabilities, matched against a station's capabilities list: tide (CO-OPS tide predictions → noaa_marine_get_tide_predictions), current (CO-OPS tidal-current predictions → noaa_marine_get_currents), water_level (CO-OPS observed water levels → noaa_marine_get_water_level), met (NDBC meteorological → noaa_marine_get_conditions), current_profile (NDBC observed ocean-current depth profile → noaa_marine_get_current_profile; note this is a different data product and source than CO-OPS `current`). The sixth, buoy, is a physical-platform filter (NDBC platform class equals buoy), not a data capability — use it to select buoy-class platforms regardless of what data they serve."
      }
    },
    "limit": {
      "default": 20,
      "description": "Maximum number of stations to return. Defaults to 20.",
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    }
  },
  "required": [
    "radius_km",
    "source",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_tide_predictions

open-world

High/low tide predictions for a CO-OPS tide station over a date range. Returns time, height, and tide type (H=high, L=low) for each event when using the default hilo interval, or 6-minute interval predictions for a detailed tide curve. Datum defaults to MLLW (mean lower low water — standard for US nautical charts). Date range is limited to 1 year per request; split longer ranges across multiple calls. Use noaa_marine_find_stations first to resolve a station name or location to a numeric station ID.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_tide_predictions",
    "arguments": {
      "station_id": "<station_id>",
      "begin_date": "<begin_date>",
      "end_date": "<end_date>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "CO-OPS tide station ID (numeric, e.g. \"9447130\" for Seattle). Obtain from noaa_marine_find_stations with types=[\"tide\"]."
    },
    "begin_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "Start date in YYYYMMDD format, e.g. \"20240601\"."
    },
    "end_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "End date in YYYYMMDD format (inclusive), e.g. \"20240607\"."
    },
    "datum": {
      "default": "MLLW",
      "description": "Tidal datum reference plane. MLLW (default) is the US nautical chart datum. MSL = mean sea level; MHHW = mean higher high water (flooding reference).",
      "type": "string",
      "enum": [
        "MLLW",
        "MHHW",
        "MSL",
        "MTL",
        "MHW",
        "MLW",
        "CD",
        "STND"
      ]
    },
    "time_zone": {
      "default": "lst_ldt",
      "description": "Time zone for returned timestamps. lst_ldt = local standard/daylight time (default); gmt = UTC; lst = local standard time year-round.",
      "type": "string",
      "enum": [
        "lst_ldt",
        "gmt",
        "lst"
      ]
    },
    "units": {
      "default": "english",
      "description": "Unit system for heights: english = feet; metric = meters.",
      "type": "string",
      "enum": [
        "english",
        "metric"
      ]
    },
    "interval": {
      "default": "hilo",
      "description": "Prediction interval: hilo (default) returns only high and low tide events; 6min returns a continuous prediction curve at 6-minute intervals.",
      "type": "string",
      "enum": [
        "hilo",
        "6min"
      ]
    }
  },
  "required": [
    "station_id",
    "begin_date",
    "end_date",
    "datum",
    "time_zone",
    "units",
    "interval"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_water_level

open-world

Observed water level (real-time or historical) for a CO-OPS water-level station, with paired predictions for comparison. The difference (residual = observed − predicted) indicates storm surge (positive) or anomalous drawdown (negative). Returns 6-minute observations alongside 6-minute predictions. Date range is limited to 31 days per request; split longer ranges into multiple calls. Use noaa_marine_find_stations first to resolve a station name or location to a valid station ID.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_water_level",
    "arguments": {
      "station_id": "<station_id>",
      "begin_date": "<begin_date>",
      "end_date": "<end_date>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "CO-OPS water-level station ID (numeric, e.g. \"9447130\" for Seattle). Obtain from noaa_marine_find_stations with types=[\"water_level\"]."
    },
    "begin_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "Start date in YYYYMMDD format, e.g. \"20240601\"."
    },
    "end_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "End date in YYYYMMDD format (inclusive), e.g. \"20240601\"."
    },
    "datum": {
      "default": "MLLW",
      "description": "Tidal datum reference plane. MLLW (default) is the US nautical chart datum. MSL = mean sea level; MHHW = mean higher high water (flooding reference).",
      "type": "string",
      "enum": [
        "MLLW",
        "MHHW",
        "MSL",
        "MTL",
        "MHW",
        "MLW",
        "CD",
        "STND"
      ]
    },
    "time_zone": {
      "default": "lst_ldt",
      "description": "Time zone for returned timestamps. lst_ldt = local standard/daylight time (default); gmt = UTC; lst = local standard time year-round.",
      "type": "string",
      "enum": [
        "lst_ldt",
        "gmt",
        "lst"
      ]
    },
    "units": {
      "default": "english",
      "description": "Unit system: english = feet; metric = meters.",
      "type": "string",
      "enum": [
        "english",
        "metric"
      ]
    }
  },
  "required": [
    "station_id",
    "begin_date",
    "end_date",
    "datum",
    "time_zone",
    "units"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_currents

open-world

Tidal current predictions for a CO-OPS current station: max flood/ebb speeds, slack times, and directions. These are forecast tidal-current predictions from CO-OPS — distinct from noaa_marine_get_current_profile, which returns NDBC observed ocean-current measurements binned by depth. Defaults to MAX_SLACK interval — the practical planning view showing when currents peak and when slack water occurs. Optionally returns 6-minute continuous predictions for detailed analysis. Current station IDs use alphanumeric format (e.g. ACT4176), distinct from numeric tide/water-level IDs. Date range is limited to 1 year per request. Use noaa_marine_find_stations with types=["current"] to obtain valid current station IDs.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_currents",
    "arguments": {
      "station_id": "<station_id>",
      "begin_date": "<begin_date>",
      "end_date": "<end_date>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "CO-OPS current station ID (alphanumeric, e.g. \"ACT4176\"). Obtain from noaa_marine_find_stations with types=[\"current\"]."
    },
    "begin_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "Start date in YYYYMMDD format, e.g. \"20240601\"."
    },
    "end_date": {
      "type": "string",
      "pattern": "^\\d{8}$",
      "description": "End date in YYYYMMDD format (inclusive), e.g. \"20240607\"."
    },
    "time_zone": {
      "default": "lst_ldt",
      "description": "Time zone for returned timestamps. lst_ldt = local standard/daylight time (default); gmt = UTC; lst = local standard time year-round.",
      "type": "string",
      "enum": [
        "lst_ldt",
        "gmt",
        "lst"
      ]
    },
    "units": {
      "default": "english",
      "description": "Unit system: english = knots; metric = m/s.",
      "type": "string",
      "enum": [
        "english",
        "metric"
      ]
    },
    "interval": {
      "default": "MAX_SLACK",
      "description": "Prediction interval: MAX_SLACK (default) returns max flood, max ebb, and slack water events — ideal for passage planning. 6min returns a continuous current curve.",
      "type": "string",
      "enum": [
        "MAX_SLACK",
        "6min"
      ]
    }
  },
  "required": [
    "station_id",
    "begin_date",
    "end_date",
    "time_zone",
    "units",
    "interval"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_conditions

open-world

Live marine conditions from an NDBC buoy: wave height/period/direction, wind speed/gust/direction, sea-surface temperature, air temperature, barometric pressure, and dew point. All values are SI units — wind in m/s, wave height in m, pressure in hPa, temperatures in °C. Exceptions: TIDE is in feet and VIS is in nautical miles (rarely populated at offshore buoys). Numeric fields are null when the buoy sensor did not report a value — this is normal for offshore buoys. Observations are updated approximately every 10 minutes; data may be 10–20 minutes old. Use noaa_marine_find_stations with source="ndbc" and types=["met"] to find station IDs near a location — met-flagged stations are the ones most likely to serve live conditions. Roughly a third of active NDBC stations report neither meteorological nor current data, and most of those have no observation file, so omitting the types filter will surface station IDs this tool cannot read.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_conditions",
    "arguments": {
      "station_id": "<station_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "NDBC buoy station ID (5-character alphanumeric, e.g. \"46041\" for Cape Elizabeth). Obtain from noaa_marine_find_stations with source=\"ndbc\" and types=[\"met\"]."
    }
  },
  "required": [
    "station_id"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_current_profile

open-world

Observed ocean-current depth profile from an NDBC ADCP buoy: the most recent measurement of current speed and direction at each depth bin. Returns depth in meters, direction in degrees true (the direction the current flows toward), and speed in cm/s. Distinct from noaa_marine_get_currents, which returns CO-OPS tidal-current predictions (forecast max flood/ebb/slack) rather than these observed acoustic-Doppler measurements. A depth bin is reported whenever NDBC gives it a depth; its direction or speed is null when the sensor did not report that component. Use noaa_marine_find_stations with source="ndbc" and types=["current_profile"] to find station IDs — most NDBC stations serve no ADCP profile, so an unfiltered search returns IDs this tool cannot read.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_current_profile",
    "arguments": {
      "station_id": "<station_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "NDBC station ID (5-character alphanumeric, e.g. \"44033\"). Obtain from noaa_marine_find_stations with source=\"ndbc\" and types=[\"current_profile\"]."
    }
  },
  "required": [
    "station_id"
  ],
  "additionalProperties": false
}
view source ↗

noaa_marine_get_ocean_observations

open-world

Live sub-surface oceanographic observations from an NDBC station's water-quality sensors: at each reported depth, water temperature, conductivity, salinity, dissolved oxygen (both saturation percent and concentration in ppm), chlorophyll, turbidity, pH, and redox potential. This is the water-column counterpart to noaa_marine_get_conditions, which returns surface meteorological and wave data (wind, waves, sea-surface temperature) — use this tool for what the water is doing below the surface, that one for weather and sea state at the buoy. Returns the most recent observation as one reading per reported depth; most stations report a single depth, but some report several at the same time. Sensor coverage is sparse — most stations populate only water temperature and salinity — and any value the station did not report comes back null rather than a fabricated zero. Latitude and longitude are null when the station is absent from the NDBC active-stations list. Sub-surface sensors are on only a subset of NDBC stations and are not marked by any station-catalog flag, so no capability filter guarantees coverage: call this on candidate NDBC station IDs from noaa_marine_find_stations with source="ndbc", and expect the observations_not_found error on the many stations that serve no .ocean file.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "noaa_marine_get_ocean_observations",
    "arguments": {
      "station_id": "<station_id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "station_id": {
      "type": "string",
      "pattern": "^[A-Za-z0-9_-]{1,20}$",
      "description": "NDBC station ID (5-character alphanumeric, e.g. \"44033\" or \"TIBC1\"). Obtain candidate IDs from noaa_marine_find_stations with source=\"ndbc\" — ocean-sensor coverage is not flagged in the catalog, so this is a best-effort call on any NDBC station."
    }
  },
  "required": [
    "station_id"
  ],
  "additionalProperties": false
}
view source ↗

Resources

1

Metadata for a CO-OPS or NDBC station by ID: name, coordinates, source, data capabilities, and — for NDBC — the physical platform class. `type` is the primary data capability (same meaning as in noaa_marine_find_stations), omitted when the station reports no data capability; `platform` is the NDBC platform class (buoy, fixed, oilrig, dart, tao, usv, other) and is a separate axis, absent for CO-OPS. CO-OPS station IDs are numeric (tide/water-level) or alphanumeric (current stations). NDBC station IDs are 5-character alphanumeric codes. Use noaa_marine_find_stations to discover station IDs.

uri noaa-marine://station/{station_id} mime application/json