@cyanheads/noaa-marine-mcp-server 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/AGENTS.md +7 -4
  2. package/CLAUDE.md +7 -4
  3. package/README.md +35 -16
  4. package/changelog/0.4.x/0.4.0.md +31 -0
  5. package/changelog/0.5.x/0.5.0.md +37 -0
  6. package/dist/index.js +1 -12
  7. package/dist/index.js.map +1 -1
  8. package/dist/mcp-server/resources/definitions/noaa-marine-station.resource.d.ts +12 -1
  9. package/dist/mcp-server/resources/definitions/noaa-marine-station.resource.d.ts.map +1 -1
  10. package/dist/mcp-server/resources/definitions/noaa-marine-station.resource.js +73 -21
  11. package/dist/mcp-server/resources/definitions/noaa-marine-station.resource.js.map +1 -1
  12. package/dist/mcp-server/tools/definitions/noaa-marine-find-stations.tool.d.ts +38 -6
  13. package/dist/mcp-server/tools/definitions/noaa-marine-find-stations.tool.d.ts.map +1 -1
  14. package/dist/mcp-server/tools/definitions/noaa-marine-find-stations.tool.js +337 -40
  15. package/dist/mcp-server/tools/definitions/noaa-marine-find-stations.tool.js.map +1 -1
  16. package/dist/mcp-server/tools/definitions/noaa-marine-get-conditions.tool.d.ts +6 -3
  17. package/dist/mcp-server/tools/definitions/noaa-marine-get-conditions.tool.d.ts.map +1 -1
  18. package/dist/mcp-server/tools/definitions/noaa-marine-get-conditions.tool.js +53 -16
  19. package/dist/mcp-server/tools/definitions/noaa-marine-get-conditions.tool.js.map +1 -1
  20. package/dist/mcp-server/tools/definitions/noaa-marine-get-current-profile.tool.d.ts.map +1 -1
  21. package/dist/mcp-server/tools/definitions/noaa-marine-get-current-profile.tool.js +4 -9
  22. package/dist/mcp-server/tools/definitions/noaa-marine-get-current-profile.tool.js.map +1 -1
  23. package/dist/mcp-server/tools/definitions/noaa-marine-get-currents.tool.d.ts +31 -4
  24. package/dist/mcp-server/tools/definitions/noaa-marine-get-currents.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/noaa-marine-get-currents.tool.js +232 -62
  26. package/dist/mcp-server/tools/definitions/noaa-marine-get-currents.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/definitions/noaa-marine-get-ocean-observations.tool.d.ts +2 -2
  28. package/dist/mcp-server/tools/definitions/noaa-marine-get-ocean-observations.tool.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/definitions/noaa-marine-get-ocean-observations.tool.js +8 -19
  30. package/dist/mcp-server/tools/definitions/noaa-marine-get-ocean-observations.tool.js.map +1 -1
  31. package/dist/mcp-server/tools/definitions/noaa-marine-get-tide-predictions.tool.d.ts +23 -2
  32. package/dist/mcp-server/tools/definitions/noaa-marine-get-tide-predictions.tool.d.ts.map +1 -1
  33. package/dist/mcp-server/tools/definitions/noaa-marine-get-tide-predictions.tool.js +126 -25
  34. package/dist/mcp-server/tools/definitions/noaa-marine-get-tide-predictions.tool.js.map +1 -1
  35. package/dist/mcp-server/tools/definitions/noaa-marine-get-water-level.tool.d.ts +57 -5
  36. package/dist/mcp-server/tools/definitions/noaa-marine-get-water-level.tool.d.ts.map +1 -1
  37. package/dist/mcp-server/tools/definitions/noaa-marine-get-water-level.tool.js +327 -61
  38. package/dist/mcp-server/tools/definitions/noaa-marine-get-water-level.tool.js.map +1 -1
  39. package/dist/services/coops/coops-service.d.ts +53 -11
  40. package/dist/services/coops/coops-service.d.ts.map +1 -1
  41. package/dist/services/coops/coops-service.js +173 -36
  42. package/dist/services/coops/coops-service.js.map +1 -1
  43. package/dist/services/coops/prediction-class.d.ts +29 -0
  44. package/dist/services/coops/prediction-class.d.ts.map +1 -0
  45. package/dist/services/coops/prediction-class.js +46 -0
  46. package/dist/services/coops/prediction-class.js.map +1 -0
  47. package/dist/services/coops/row-page.d.ts +94 -0
  48. package/dist/services/coops/row-page.d.ts.map +1 -0
  49. package/dist/services/coops/row-page.js +170 -0
  50. package/dist/services/coops/row-page.js.map +1 -0
  51. package/dist/services/coops/types.d.ts +72 -20
  52. package/dist/services/coops/types.d.ts.map +1 -1
  53. package/dist/services/ndbc/ndbc-service.d.ts +9 -0
  54. package/dist/services/ndbc/ndbc-service.d.ts.map +1 -1
  55. package/dist/services/ndbc/ndbc-service.js +249 -110
  56. package/dist/services/ndbc/ndbc-service.js.map +1 -1
  57. package/dist/services/ndbc/types.d.ts +55 -15
  58. package/dist/services/ndbc/types.d.ts.map +1 -1
  59. package/package.json +4 -4
  60. package/server.json +3 -3
package/AGENTS.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** noaa-marine-mcp-server
4
- **Version:** 0.3.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.2`
4
+ **Version:** 0.5.0
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.3`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
8
- **Zod:** ^4.6.4
8
+ **Zod:** ^4.6.5
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -227,7 +227,10 @@ src/
227
227
  server-config.ts # NOAA_APPLICATION_ID env var (optional, defaults to server name)
228
228
  services/
229
229
  coops/
230
- coops-service.ts # CO-OPS Tides & Currents API (station cache, data fetch)
230
+ coops-service.ts # CO-OPS Tides & Currents API (station cache, data fetch, message classifier)
231
+ date-range.ts # YYYYMMDD calendar validation and span, shared by the date-ranged tools
232
+ prediction-class.ts # Decodes the catalog `type` letter into a prediction class
233
+ row-page.ts # Byte-bounded row paging shared by the time-series tools
231
234
  types.ts # CO-OPS domain types
232
235
  ndbc/
233
236
  ndbc-service.ts # NDBC buoy service (active stations XML, realtime text)
package/CLAUDE.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Server:** noaa-marine-mcp-server
4
- **Version:** 0.3.2
5
- **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.2`
4
+ **Version:** 0.5.0
5
+ **Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) `^0.13.3`
6
6
  **Engines:** Bun ≥1.4.0, Node ≥24.0.0
7
7
  **MCP SDK:** `@modelcontextprotocol/server` ^2.0.0 (protocol revisions 2026-07-28 and 2025-*)
8
- **Zod:** ^4.6.4
8
+ **Zod:** ^4.6.5
9
9
 
10
10
  > **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
11
11
 
@@ -227,7 +227,10 @@ src/
227
227
  server-config.ts # NOAA_APPLICATION_ID env var (optional, defaults to server name)
228
228
  services/
229
229
  coops/
230
- coops-service.ts # CO-OPS Tides & Currents API (station cache, data fetch)
230
+ coops-service.ts # CO-OPS Tides & Currents API (station cache, data fetch, message classifier)
231
+ date-range.ts # YYYYMMDD calendar validation and span, shared by the date-ranged tools
232
+ prediction-class.ts # Decodes the catalog `type` letter into a prediction class
233
+ row-page.ts # Byte-bounded row paging shared by the time-series tools
231
234
  types.ts # CO-OPS domain types
232
235
  ndbc/
233
236
  ndbc-service.ts # NDBC buoy service (active stations XML, realtime text)
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.3.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/noaa-marine-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/noaa-marine-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/noaa-marine-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.5.0-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Docker](https://img.shields.io/badge/Docker-ghcr.io-2496ED?style=flat-square&logo=docker&logoColor=white)](https://github.com/users/cyanheads/packages/container/package/noaa-marine-mcp-server) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^2.0.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![npm](https://img.shields.io/npm/v/@cyanheads/noaa-marine-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/noaa-marine-mcp-server) [![TypeScript](https://img.shields.io/badge/TypeScript-^7.0.2-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.4.0-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -37,7 +37,7 @@ US tide, current, and buoy data from NOAA CO-OPS and NDBC. Find tide, water-leve
37
37
  |:-----|:------------|
38
38
  | `noaa_marine_find_stations` | Find CO-OPS tide/water-level/current stations and NDBC buoys by location, name, state, or data capability. |
39
39
  | `noaa_marine_get_tide_predictions` | High/low tide predictions or a 6-minute curve for a CO-OPS tide station. |
40
- | `noaa_marine_get_water_level` | Observed water level paired with predictions for a CO-OPS station, with a storm-surge residual summary. |
40
+ | `noaa_marine_get_water_level` | Observed water level at a 6-minute, hourly, high/low, or daily-mean cadence, paired with predictions and a storm-surge residual summary. |
41
41
  | `noaa_marine_get_currents` | CO-OPS tidal current predictions — max flood/ebb/slack events or a 6-minute curve. |
42
42
  | `noaa_marine_get_conditions` | Live NDBC buoy conditions: waves, wind, sea-surface and air temperature, pressure. |
43
43
  | `noaa_marine_get_current_profile` | Observed ocean-current depth profile from an NDBC ADCP buoy. |
@@ -55,38 +55,55 @@ All resource data is also reachable via tools — use `noaa_marine_find_stations
55
55
 
56
56
  ### `noaa_marine_find_stations` <sub>tool</sub>
57
57
 
58
- - Filter by proximity (`latitude`/`longitude` + `radius_km`, default 100 km, max 1000 km), name/ID substring, US state/territory (CO-OPS only), source (`coops`/`ndbc`/`all`), or `types`: data capabilities (`tide`, `current`, `water_level`, `met`, `current_profile`) or NDBC platform class (`buoy`)
58
+ - Filter by proximity (`latitude`/`longitude` + `radius_km`, default 100 km, max 1000 km), name/ID substring (matched against both sources; an exact ID match sorts first), US state/territory (CO-OPS only), source (`coops`/`ndbc`/`all`), or `types`: data capabilities (`tide`, `current`, `water_level`, `met`, `current_profile`, `water_quality`) or NDBC platform class (`buoy`)
59
59
  - Returns up to `limit` (default 20, max 200) unified stations with source, coordinates, distance, data capabilities, and — for NDBC — physical platform class (buoy, fixed, oilrig, dart, tao, usv, other)
60
+ - CO-OPS prediction stations also carry `prediction_class`, a third axis beside capability and platform: a tide station is `reference` (serving `hilo` and the 6-minute curve) or `subordinate` (`hilo` only, with `reference_id` naming where its offsets come from), while a current station reports its class per depth bin in `bins[]` alongside each bin's number and catalog depth in feet — the bin numbers `noaa_marine_get_currents` takes as `bin`
60
61
  - `total_found` and `truncated` report the full match count before the limit is applied
62
+ - Zero matches is a success with `total_found: 0`, carrying a notice derived from the filters that were applied and an echo of the applied search
63
+ - A catalog that fails to load is reported as an unread source alongside the results; when every needed catalog fails, that is a typed `sources_unavailable` error rather than an empty search
61
64
  - Station lists are cached in-memory with a 6-hour TTL — first call after startup may be slightly slower
62
- - Typed `incomplete_coordinates` error when only one of latitude/longitude is supplied; `no_results` when nothing matches
65
+ - Typed `incomplete_coordinates` error when only one of latitude/longitude is supplied
63
66
 
64
67
  ---
65
68
 
66
69
  ### `noaa_marine_get_tide_predictions` <sub>tool</sub>
67
70
 
68
71
  - `hilo` (default, high/low events) or `6min` continuous curve; up to 1 year per request
69
- - Eight datums: MLLW (default, US nautical chart), MHHW, MSL, MTL, MHW, MLW, CD, STND
72
+ - A range whose rows fit the response budget returns whole; a longer one returns the leading rows as a page, with `rows_matched`, `rows_returned`, `page_offset`, and `next_offset` on both consumption surfaces. Walk it with `offset`; `limit` lowers a page and never raises it past the byte bound, and an `offset` past the last row is an empty page rather than an error
73
+ - `6min` is served by reference stations only — a subordinate station's high and low events are offsets from a reference station and it has no 6-minute curve, so the request is refused before the upstream call as a typed `subordinate_no_6min` naming `hilo` and that reference station
74
+ - Ten datums, matching what the CO-OPS predictions product accepts: MLLW (default, US nautical chart), MHHW, MHW, MTL, MSL, MLW, DTL, NAVD (NAVD88, where the station has a tie), STND (the station's own datum), CRD (Columbia River only)
75
+ - A datum the station does not carry is a typed `datum_unavailable` naming the planes it does, not a report that the station ID was wrong; a Great Lakes station, which publishes no prediction series at any datum, is `no_predictions` pointing at `noaa_marine_get_water_level`
70
76
  - Time zone (`lst_ldt` default, `gmt`, `lst`) and units (`english` default feet, `metric` meters)
71
- - Typed `date_range_exceeded`, `invalid_date_range`, `station_not_found`, and `no_predictions` errors
77
+ - Typed `date_range_exceeded`, `invalid_date_range`, `station_not_found`, `no_predictions`, `datum_unavailable`, and `subordinate_no_6min` errors
72
78
 
73
79
  ---
74
80
 
75
81
  ### `noaa_marine_get_water_level` <sub>tool</sub>
76
82
 
77
- - 6-minute observed water level with quality flags (`p` preliminary, `v` verified) and optional sensor `sigma`
78
- - Paired 6-minute tide predictions fetched in parallel — failure degrades gracefully, observed levels still return
79
- - `residual_summary` (max surge, max drawdown) only when both series are present
80
- - Up to 31 days per request; typed `date_range_exceeded`, `station_not_found`, and `no_data` errors
83
+ - `interval` selects the cadence: `6min` (default) the full curve, `hourly` hourly heights, `high_low` the observed high and low waters with their `H`/`HH`/`L`/`LL` classification, `daily_mean` the daily mean at Great Lakes stations only. The `interval` is echoed in the output
84
+ - Per-interval CO-OPS range ceilings, rejected locally before the call: 31 days for `6min`, 365 for `hourly` and `high_low`, 3,655 for `daily_mean`. A coarser cadence is not automatically a smaller response — a year of `hourly` rows outweighs a month of 6-minute ones — so the ceiling bounds the request and the response budget bounds the page
85
+ - Quality flags (`p` preliminary, `v` verified) on `6min` only: CO-OPS sends no flag with the coarser products, and `quality` is omitted rather than defaulted to preliminary, which would label verified data unverified. Sensor `sigma` on `6min` and `hourly`
86
+ - Thirteen datums, matching what the CO-OPS water-level product accepts: MLLW (default, US nautical chart), MHHW, MHW, MTL, MSL, MLW, NAVD (NAVD88, where the station has a tie), STND (the station's own datum), IGLD and LWD (Great Lakes only), CRD (Columbia River only), LWI and HWI (lunitidal intervals)
87
+ - A datum the station does not carry is a typed `datum_unavailable` whose recovery names the planes that do read it — `STND`, `IGLD`, `LWD` at a Great Lakes station, `MLLW`/`STND` where an NAVD88 tie is missing — rather than sending the caller back to re-verify an ID `noaa_marine_find_stations` just returned
88
+ - A sensor outage leaves slots with no reading; they are dropped and counted in `gaps_dropped`, so `rows_matched` always counts only the slots that carried a value and continuous coverage across the range is only implied when that count is absent
89
+ - Paired tide predictions at the interval matching the observed cadence, fetched in parallel — the observed series returns either way, and `predictions_status` says whether an empty prediction series means CO-OPS has none or the fetch failed. Not fetched at all on `daily_mean`, which has no paired series
90
+ - `residual_summary` (max surge, max drawdown) only when both series are present, computed from the finite observed/predicted pairs across the whole matched series rather than the returned page. Reported on `6min` and `hourly` only — observed high and low waters do not occur at the predicted extreme times, so a `high_low` join would rest on a small fraction of the events, and `daily_mean` has no paired series at all; the notice says which applies
91
+ - A range whose rows fit the response budget returns whole; a longer one returns the leading rows as a page, with `rows_matched`, `rows_returned`, `page_offset`, and `next_offset` on both consumption surfaces. Observations carry the `offset` and the paired predictions follow by time window, so a page's two series always describe one span even after gap rows shorten the observed one
92
+ - `daily_mean` is requested in local standard time whatever `time_zone` was passed — CO-OPS serves that product in LST only and silently shifts any other zone by a day
93
+ - Typed `date_range_exceeded`, `invalid_date_range`, `station_not_found`, `no_data`, `datum_unavailable`, `great_lakes_only` (`daily_mean` at a coastal station), and `verified_data_lag` errors — the last for a window CO-OPS has not verified yet, since it verifies the coarser products monthly for the prior month
81
94
 
82
95
  ---
83
96
 
84
97
  ### `noaa_marine_get_currents` <sub>tool</sub>
85
98
 
86
99
  - `MAX_SLACK` (default): max flood, max ebb, and slack events only — the actionable view for passage planning
87
- - `6min`: continuous current curve; units `english` (knots, default) or `metric` (m/s)
100
+ - `6min`: continuous current curve, each row carrying its own `flood`/`ebb`/`slack` sense plus the station mean flood or ebb bearing that sense implies (a station constant, not an instantaneous heading)
101
+ - Both intervals are bounded by response size: a range whose rows fit the response budget returns whole; a longer one returns the leading rows as a page, with `rows_matched`, `rows_returned`, `page_offset`, and `next_offset` on both surfaces. `offset` and `limit` walk whichever series the interval selects — the max/slack events or the 6-minute curve
102
+ - Units `english` (knots for speed, feet for the echoed depth, default) or `metric` (cm/s for speed, meters for depth) — CO-OPS publishes metric current speed in cm/s, the unit `noaa_marine_get_current_profile` also reports
103
+ - `bin` selects one of a station's depth bins; omit it for the CO-OPS default, the shallowest. The bin CO-OPS answered with and its depth are echoed on every response, and a bin the station does not publish is a typed `bin_unavailable` naming the bins it does
104
+ - A station whose currents CO-OPS will not predict as discrete events returns an empty list plus CO-OPS's own wording in the notice, not an error
88
105
  - Current station IDs are alphanumeric (e.g. `ACT4176`), distinct from numeric tide/water-level IDs
89
- - Up to 1 year per request; typed `date_range_exceeded`, `invalid_date_range`, `station_not_found`, and `no_predictions` errors
106
+ - Up to 1 year per request; typed `date_range_exceeded`, `invalid_date_range`, `station_not_found`, `no_predictions`, `predictions_unavailable`, and `bin_unavailable` errors
90
107
 
91
108
  ---
92
109
 
@@ -94,8 +111,9 @@ All resource data is also reachable via tools — use `noaa_marine_find_stations
94
111
 
95
112
  - Wave height/period/direction, wind speed/gust/direction, sea-surface and air temperature, dew point, barometric pressure
96
113
  - All values SI except `tide_ft` (feet) and `visibility_nmi` (nautical miles), both rarely populated at offshore buoys
97
- - Every sensor field is nullable — `null` when the buoy did not report, never a fabricated value
98
- - Updated roughly every 10 minutes; typed `buoy_not_found` and `no_sensor_data` errors
114
+ - Every sensor field is nullable — `null` when the buoy did not report, never a fabricated value. `latitude`/`longitude` are `null` for a station absent from the NDBC catalog, and `observed_at` is always a valid instant
115
+ - NDBC writes each block of columns on its own cycle, so a block resolves from the most recent row within 90 minutes that carried it: waves report their own `waves_observed_at`, and any other block read from an earlier row is named with its measurement time in the response notice. Row cadence runs 5–60 minutes depending on the station
116
+ - Typed `buoy_not_found` and `no_sensor_data` errors
99
117
 
100
118
  ---
101
119
 
@@ -113,14 +131,15 @@ All resource data is also reachable via tools — use `noaa_marine_find_stations
113
131
  - Water temperature, conductivity, salinity, dissolved oxygen (% and ppm), chlorophyll, turbidity, pH, and redox potential per depth
114
132
  - Water-column counterpart to `noaa_marine_get_conditions` (surface weather and sea state)
115
133
  - Sensor coverage is sparse — most stations report only temperature and salinity; unreported values are `null`, never a fabricated zero
116
- - No capability filter identifies ocean-sensor coverage — call on candidate `source="ndbc"` IDs and expect `observations_not_found` on stations with no `.ocean` file
134
+ - Find candidates with `find_stations` using `source="ndbc"` and `types: ["water_quality"]`, NDBC's own water-quality catalog flag — a strong hint, not a guarantee, so expect `observations_not_found` on a flagged station serving no `.ocean` file
117
135
 
118
136
  ---
119
137
 
120
138
  ### `noaa-marine://station/{station_id}` <sub>resource</sub>
121
139
 
122
- - Station record as `application/json` — name, coordinates, source, capabilities, state, and (NDBC) platform class
140
+ - Station record as `application/json` — name, coordinates, source, capabilities, state, the CO-OPS `prediction_class` (with `reference_id` or per-bin `bins[]`, exactly as on `noaa_marine_find_stations`), and (NDBC) platform class
123
141
  - `station_id` comes from `noaa_marine_find_stations`
142
+ - Typed `station_not_found` when both catalogs were read and neither carries the ID, and `source_unavailable` when a catalog could not be read — a station only the unread catalog carries is never reported as nonexistent
124
143
  - Cached with a 6-hour TTL (`cacheHint`)
125
144
 
126
145
  ## Features
@@ -0,0 +1,31 @@
1
+ ---
2
+ summary: "NDBC parser fixes, structured empty searches, water_quality station type"
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.4.0 — 2026-09-17
8
+
9
+ ## Added
10
+
11
+ - **`water_quality`** joins `noaa_marine_find_stations`' `types` filter, matching NDBC sub-surface water-column stations — 140 stations, 45 previously unreachable by any filter (#28)
12
+ - **`noaa_marine_find_stations`** matches CO-OPS rows by station ID, not just NDBC; an exact-ID match sorts first when no proximity center is given (#29)
13
+ - **`noaa_marine_find_stations`** returns a zero-match search as a success (`total_found: 0`) with a `notice` and an `applied_search` echo of the filters that emptied it, and adds a `sources` block naming any catalog that failed to answer (#31, #21)
14
+ - **`noaa_marine_get_conditions`** adds `waves_observed_at` and a staleness `notice` — NDBC writes each sensor block on its own cycle, so a block up to 90 minutes older than `observed_at` is now disclosed instead of silently blended in (#24)
15
+ - **`noaa_marine_get_water_level`** adds `predictions_status` and a notice disclosing rejected upstream prediction legs instead of dropping them silently (#21)
16
+ - **`noaa-marine-station` resource** returns a typed `errors[]` contract (`station_not_found`, `source_unavailable`) in place of an untyped failure (#21)
17
+
18
+ ## Changed
19
+
20
+ - **`noaa_marine_get_conditions`** `latitude`/`longitude` are nullable — a station absent from the NDBC catalog now reports unknown coordinates instead of a fabricated `0, 0` (#17)
21
+
22
+ ## Fixed
23
+
24
+ - **`noaa_marine_get_conditions`** wave fields no longer read `null` when the newest NDBC row is `MM`: each sensor block resolves from the most recent row inside a 90-minute look-back that actually carried it (#24)
25
+ - **NDBC parser** decodes XML entities in station names and owners (12 stations affected) and validates timestamps per row — a malformed row is skipped rather than producing a fabricated or unparseable observation time (#20)
26
+ - **`noaa_marine_find_stations`** no longer throws `no_results`; a zero-row multi-catalog fan-out raises `sources_unavailable` only when every catalog failed (#31, #21)
27
+
28
+ ## Dependencies
29
+
30
+ - `@cyanheads/mcp-ts-core` ^0.13.2 → ^0.13.3
31
+ - `zod` ^4.6.4 → ^4.6.5
@@ -0,0 +1,37 @@
1
+ ---
2
+ summary: "Paged CO-OPS series, coarser water levels, datum and class fixes"
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.5.0 — 2026-09-17
8
+
9
+ ## Added
10
+
11
+ - **`prediction_class`** (+ `reference_id` on tide rows, per-bin `bins[]` on current rows) on `noaa_marine_find_stations` and the station resource — a tide station is `reference` or `subordinate`, a current bin `harmonic`, `subordinate`, or `weak_and_variable` (#26, #27)
12
+ - **`noaa_marine_get_water_level`** gains `interval`: `6min` (default), `hourly`, `high_low`, and `daily_mean`, each with its own CO-OPS range ceiling and datum set (#30)
13
+ - **`noaa_marine_get_currents`** gains `bin` to select a depth bin; the answered bin and its depth are echoed on every response (#27)
14
+ - **Paging** — `noaa_marine_get_water_level`, `noaa_marine_get_tide_predictions`, and `noaa_marine_get_currents` accept `offset`/`limit` and report `rows_matched`, `rows_returned`, `page_offset`, and `next_offset` for a series too large for one response (#18)
15
+ - **`gaps_dropped`** on `noaa_marine_get_water_level` counts sensor slots CO-OPS returned with no reading (#22)
16
+ - **`subordinate_no_6min`** pre-flight on `noaa_marine_get_tide_predictions` rejects a 6-minute request for a subordinate station before the upstream call, naming its reference station (#26)
17
+ - **New typed errors**: `datum_unavailable`, `bin_unavailable`, `predictions_unavailable` (#25, #27, #26); `great_lakes_only` and `verified_data_lag` on `noaa_marine_get_water_level` (#30)
18
+
19
+ ## Changed
20
+
21
+ - **Datum enums** are per-tool now: `noaa_marine_get_tide_predictions` accepts MLLW, MHHW, MHW, MTL, MSL, MLW, DTL, NAVD, STND, CRD; `noaa_marine_get_water_level` additionally accepts IGLD, LWD, LWI, HWI (#25)
22
+ - **`noaa_marine_get_currents`** returns a success (empty events plus CO-OPS's own statement in the notice) for a weak-and-variable station instead of throwing `no_predictions` (#26)
23
+ - **`noaa_marine_get_water_level`**'s `predictions_status` reports `empty` for a series CO-OPS says it never publishes, distinct from `unavailable` for a failed fetch (#26)
24
+ - **`noaa_marine_get_tide_predictions`** reports `no_predictions` for a Great Lakes station instead of `station_not_found` (#26)
25
+
26
+ ## Removed
27
+
28
+ - **`CD`** dropped from the `noaa_marine_get_tide_predictions` and `noaa_marine_get_water_level` datum enums — CO-OPS never accepted it (#25)
29
+
30
+ ## Fixed
31
+
32
+ - **`noaa_marine_get_currents`** 6-minute rows report speed in cm/s under `metric`, not the previously mislabeled m/s, and each row now carries its own `flood`/`ebb`/`slack` type and the correct signed direction (#19)
33
+ - **`noaa_marine_get_currents`** MAX_SLACK events no longer drop a 0° mean bearing — the bearing fields were read as strings, so a numeric zero was silently treated as falsy
34
+
35
+ ## Dependencies
36
+
37
+ - `@types/node` ^26.2.0 → ^26.5.1
package/dist/index.js CHANGED
@@ -35,18 +35,7 @@ await createApp({
35
35
  'resources/list': { ttlMs: 86_400_000, cacheScope: 'public' },
36
36
  'resources/templates/list': { ttlMs: 86_400_000, cacheScope: 'public' },
37
37
  },
38
- instructions: 'US marine conditions via NOAA CO-OPS and NDBC. ' +
39
- 'Start with noaa_marine_find_stations to resolve a location or name to station IDs, ' +
40
- 'then call the appropriate data tool. ' +
41
- 'CO-OPS provides tide predictions (noaa_marine_get_tide_predictions), ' +
42
- 'observed water levels and storm surge (noaa_marine_get_water_level), ' +
43
- 'and tidal-current predictions (noaa_marine_get_currents). ' +
44
- 'NDBC provides live buoy conditions — waves, wind, sea-surface temp (noaa_marine_get_conditions), ' +
45
- 'observed ocean-current depth profiles (noaa_marine_get_current_profile), ' +
46
- 'and sub-surface water-column observations — temperature, salinity, dissolved oxygen and more (noaa_marine_get_ocean_observations). ' +
47
- 'The two current tools are distinct: get_currents is CO-OPS tidal-current predictions (forecast), ' +
48
- 'get_current_profile is NDBC observed depth-binned currents from an ADCP buoy. ' +
49
- 'All water height data is referenced to MLLW by default (US nautical chart datum).',
38
+ instructions: `US marine conditions from NOAA CO-OPS and NDBC: CO-OPS is coastal-gauge tide and tidal-current predictions plus observed water levels, NDBC is live buoy observation, and every water height is referenced to MLLW, the US nautical chart datum, unless another datum is requested. Start with noaa_marine_find_stations to resolve a place name, a coordinate pair, or a bare station number to a station ID — its types filter names what each station can serve, and an ID from one source never works on a tool that reads the other. That source split is also what separates the two current tools: noaa_marine_get_currents returns CO-OPS tidal-current predictions, noaa_marine_get_current_profile an observed NDBC ADCP measurement.`,
50
39
  setup(core) {
51
40
  const serverConfig = getServerConfig();
52
41
  initCoopsService(core.config, core.storage, serverConfig);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mEAAmE,CAAC;AAC5G,OAAO,EAAE,2BAA2B,EAAE,MAAM,wEAAwE,CAAC;AACrH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iEAAiE,CAAC;AACxG,OAAO,EAAE,8BAA8B,EAAE,MAAM,2EAA2E,CAAC;AAC3H,OAAO,EAAE,4BAA4B,EAAE,MAAM,yEAAyE,CAAC;AACvH,OAAO,EAAE,uBAAuB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,wBAAwB;IAC/B,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE;QACL,sBAAsB;QACtB,4BAA4B;QAC5B,uBAAuB;QACvB,qBAAqB;QACrB,uBAAuB;QACvB,2BAA2B;QAC3B,8BAA8B;KAC/B;IACD,SAAS,EAAE,CAAC,yBAAyB,CAAC;IACtC,OAAO,EAAE,EAAE;IACX,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QACzD,gBAAgB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC7D,0BAA0B,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;KACxE;IACD,YAAY,EACV,iDAAiD;QACjD,qFAAqF;QACrF,uCAAuC;QACvC,uEAAuE;QACvE,uEAAuE;QACvE,4DAA4D;QAC5D,mGAAmG;QACnG,2EAA2E;QAC3E,qIAAqI;QACrI,mGAAmG;QACnG,gFAAgF;QAChF,mFAAmF;IAErF,KAAK,CAAC,IAAI;QACR,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;QACvC,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC1D,eAAe,EAAE,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,oEAAoE,CAAC;AAC/G,OAAO,EAAE,sBAAsB,EAAE,MAAM,kEAAkE,CAAC;AAC1G,OAAO,EAAE,uBAAuB,EAAE,MAAM,mEAAmE,CAAC;AAC5G,OAAO,EAAE,2BAA2B,EAAE,MAAM,wEAAwE,CAAC;AACrH,OAAO,EAAE,qBAAqB,EAAE,MAAM,iEAAiE,CAAC;AACxG,OAAO,EAAE,8BAA8B,EAAE,MAAM,2EAA2E,CAAC;AAC3H,OAAO,EAAE,4BAA4B,EAAE,MAAM,yEAAyE,CAAC;AACvH,OAAO,EAAE,uBAAuB,EAAE,MAAM,oEAAoE,CAAC;AAC7G,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAElE,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,wBAAwB;IAC9B,KAAK,EAAE,wBAAwB;IAC/B,WAAW,EAAE,WAAW;IACxB,KAAK,EAAE;QACL,sBAAsB;QACtB,4BAA4B;QAC5B,uBAAuB;QACvB,qBAAqB;QACrB,uBAAuB;QACvB,2BAA2B;QAC3B,8BAA8B;KAC/B;IACD,SAAS,EAAE,CAAC,yBAAyB,CAAC;IACtC,OAAO,EAAE,EAAE;IACX,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QACzD,gBAAgB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QAC7D,0BAA0B,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;KACxE;IACD,YAAY,EAAE,itBAAitB;IAE/tB,KAAK,CAAC,IAAI;QACR,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;QACvC,gBAAgB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC1D,eAAe,EAAE,CAAC;IACpB,CAAC;CACF,CAAC,CAAC"}
@@ -3,7 +3,18 @@
3
3
  * @module mcp-server/resources/definitions/noaa-marine-station.resource
4
4
  */
5
5
  import { z } from '@cyanheads/mcp-ts-core';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
6
7
  export declare const noaaMarineStationResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{
7
8
  station_id: z.ZodString;
8
- }, z.core.$strip>, undefined, undefined>;
9
+ }, z.core.$strip>, undefined, readonly [{
10
+ readonly reason: "station_not_found";
11
+ readonly code: JsonRpcErrorCode.NotFound;
12
+ readonly when: "Both catalogs were read and neither carries this station ID.";
13
+ readonly recovery: "Use noaa_marine_find_stations to look the ID up — query matches station names and IDs on both sources.";
14
+ }, {
15
+ readonly reason: "source_unavailable";
16
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
17
+ readonly when: "A station catalog could not be read, and no catalog that was read carries this ID.";
18
+ readonly recovery: "Retry in a few moments — the station catalogs are cached for six hours once a fetch succeeds.";
19
+ }]>;
9
20
  //# sourceMappingURL=noaa-marine-station.resource.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"noaa-marine-station.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/noaa-marine-station.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAKrD,eAAO,MAAM,yBAAyB;;wCAqGpC,CAAC"}
1
+ {"version":3,"file":"noaa-marine-station.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/noaa-marine-station.resource.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAKjE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;GA2JpC,CAAC"}
@@ -3,18 +3,13 @@
3
3
  * @module mcp-server/resources/definitions/noaa-marine-station.resource
4
4
  */
5
5
  import { resource, z } from '@cyanheads/mcp-ts-core';
6
- import { notFound } from '@cyanheads/mcp-ts-core/errors';
6
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
7
  import { getCoopsService } from '../../../services/coops/coops-service.js';
8
+ import { currentPredictionClass, tidePredictionClass } from '../../../services/coops/prediction-class.js';
8
9
  import { getNdbcService } from '../../../services/ndbc/ndbc-service.js';
9
10
  export const noaaMarineStationResource = resource('noaa-marine://station/{station_id}', {
10
11
  name: 'noaa_marine_station',
11
- description: 'Metadata for a CO-OPS or NDBC station by ID: name, coordinates, source, data capabilities, and — for NDBC — ' +
12
- 'the physical platform class. `type` is the primary data capability (same meaning as in noaa_marine_find_stations), ' +
13
- 'omitted when the station reports no data capability; `platform` is the NDBC platform class ' +
14
- '(buoy, fixed, oilrig, dart, tao, usv, other) and is a separate axis, absent for CO-OPS. ' +
15
- 'CO-OPS station IDs are numeric (tide/water-level) or alphanumeric (current stations). ' +
16
- 'NDBC station IDs are 5-character alphanumeric codes. ' +
17
- 'Use noaa_marine_find_stations to discover station IDs.',
12
+ description: `Metadata for a CO-OPS or NDBC station by ID: name, coordinates, source, data capabilities, the CO-OPS prediction class, and — for NDBC — the physical platform class. The type field is the primary data capability, meaning the same thing here as in noaa_marine_find_stations, and is omitted when the station reports no data capability; platform is the NDBC platform class (buoy, fixed, oilrig, dart, tao, usv, other), a separate axis that CO-OPS stations do not carry. prediction_class is a third axis, again identical to the field of that name on noaa_marine_find_stations: a tide station is reference (serving both hilo and the 6-minute curve) or subordinate (hilo only, with reference_id naming the station its offsets come from), while a current station carries its class per depth bin in bins[], whose bin numbers are what noaa_marine_get_currents takes as bin. CO-OPS station IDs are numeric for tide and water-level stations and alphanumeric for current stations, while NDBC station IDs are 5-character alphanumeric codes — use noaa_marine_find_stations to discover them. A station ID that neither catalog carries is a station_not_found error, distinct from source_unavailable, which says a catalog could not be read and so was never searched.`,
18
13
  mimeType: 'application/json',
19
14
  cacheHint: { ttlMs: 21_600_000, cacheScope: 'public' },
20
15
  params: z.object({
@@ -23,6 +18,20 @@ export const noaaMarineStationResource = resource('noaa-marine://station/{statio
23
18
  .regex(/^[A-Za-z0-9_-]{1,20}$/)
24
19
  .describe('Station identifier. CO-OPS: numeric (e.g. 9447130) or alphanumeric (e.g. ACT4176). NDBC: e.g. 46041.'),
25
20
  }),
21
+ errors: [
22
+ {
23
+ reason: 'station_not_found',
24
+ code: JsonRpcErrorCode.NotFound,
25
+ when: 'Both catalogs were read and neither carries this station ID.',
26
+ recovery: 'Use noaa_marine_find_stations to look the ID up — query matches station names and IDs on both sources.',
27
+ },
28
+ {
29
+ reason: 'source_unavailable',
30
+ code: JsonRpcErrorCode.ServiceUnavailable,
31
+ when: 'A station catalog could not be read, and no catalog that was read carries this ID.',
32
+ recovery: 'Retry in a few moments — the station catalogs are cached for six hours once a fetch succeeds.',
33
+ },
34
+ ],
26
35
  async handler(params, ctx) {
27
36
  const coopsSvc = getCoopsService();
28
37
  const ndbcSvc = getNdbcService();
@@ -39,17 +48,21 @@ export const noaaMarineStationResource = resource('noaa-marine://station/{statio
39
48
  // Check CO-OPS
40
49
  if (coopsResult.status === 'fulfilled') {
41
50
  const [tide, current, waterLevel] = coopsResult.value;
42
- const match = tide.find((s) => s.id.toUpperCase() === id) ??
43
- current.find((s) => s.id.toUpperCase() === id) ??
44
- waterLevel.find((s) => s.id.toUpperCase() === id);
51
+ // Each list is read on its own, because a field's meaning depends on which catalog
52
+ // published it: the prediction class of a tide row is not the class of a current bin.
53
+ // `currentpredictions` carries one row per depth bin, so that one is a filter.
54
+ const tideRow = tide.find((s) => s.id.toUpperCase() === id);
55
+ const currentRows = current.filter((s) => s.id.toUpperCase() === id);
56
+ const waterLevelRow = waterLevel.find((s) => s.id.toUpperCase() === id);
57
+ const match = tideRow ?? currentRows[0] ?? waterLevelRow;
45
58
  if (match) {
46
59
  // A CO-OPS match came from one of the three lists, so at least one capability is present.
47
60
  const caps = [];
48
- if (tide.some((s) => s.id.toUpperCase() === id))
61
+ if (tideRow)
49
62
  caps.push('tide');
50
- if (current.some((s) => s.id.toUpperCase() === id))
63
+ if (currentRows.length > 0)
51
64
  caps.push('current');
52
- if (waterLevel.some((s) => s.id.toUpperCase() === id))
65
+ if (waterLevelRow)
53
66
  caps.push('water_level');
54
67
  const result = {
55
68
  station_id: match.id,
@@ -60,12 +73,32 @@ export const noaaMarineStationResource = resource('noaa-marine://station/{statio
60
73
  capabilities: caps,
61
74
  };
62
75
  // `type` is the primary data capability — the same axis find_stations reports. The CO-OPS
63
- // catalog `type` code (R/T/S reference classes) is a different, undocumented axis and is not
64
- // surfaced here; CO-OPS has no platform class.
76
+ // catalog prediction class is a third axis and reports under its own name, identically on
77
+ // both surfaces (#14): on the row for a tide station, and per bin for a current station,
78
+ // whose bins can mix classes. CO-OPS has no platform class.
65
79
  if (caps[0])
66
80
  result.type = caps[0];
67
81
  if (match.state)
68
82
  result.state = match.state;
83
+ const predictionClass = tidePredictionClass(tideRow?.type);
84
+ if (predictionClass)
85
+ result.prediction_class = predictionClass;
86
+ // A reference station's row carries `reference_id` as an empty string.
87
+ if (tideRow?.reference_id)
88
+ result.reference_id = tideRow.reference_id;
89
+ const bins = currentRows
90
+ .filter((s) => s.currbin !== undefined)
91
+ .map((s) => {
92
+ const bin = { bin: s.currbin, depth: s.depth ?? null };
93
+ if (s.depthType)
94
+ bin.depth_type = s.depthType;
95
+ const binClass = currentPredictionClass(s.type);
96
+ if (binClass)
97
+ bin.prediction_class = binClass;
98
+ return bin;
99
+ });
100
+ if (bins.length > 0)
101
+ result.bins = bins;
69
102
  return result;
70
103
  }
71
104
  }
@@ -73,13 +106,17 @@ export const noaaMarineStationResource = resource('noaa-marine://station/{statio
73
106
  if (ndbcResult.status === 'fulfilled') {
74
107
  const match = ndbcResult.value.find((s) => s.id.toUpperCase() === id);
75
108
  if (match) {
76
- // Data capabilities from the catalog flags only — no fabricated "buoy" when both are off (#13).
77
- // `current_profile` (NDBC observed ocean currents) is named apart from CO-OPS `current`.
109
+ // Data capabilities from the catalog flags only — no fabricated "buoy" when all are off (#13).
110
+ // `current_profile` (NDBC observed ocean currents) is named apart from CO-OPS `current`;
111
+ // `water_quality` is the sub-surface water-column flag. Same derivation as find_stations,
112
+ // so `type` means the same thing on both surfaces (#14).
78
113
  const caps = [];
79
114
  if (match.hasMet)
80
115
  caps.push('met');
81
116
  if (match.hasCurrents)
82
117
  caps.push('current_profile');
118
+ if (match.hasWaterQuality)
119
+ caps.push('water_quality');
83
120
  const result = {
84
121
  station_id: match.id,
85
122
  name: match.name,
@@ -99,9 +136,24 @@ export const noaaMarineStationResource = resource('noaa-marine://station/{statio
99
136
  return result;
100
137
  }
101
138
  }
102
- throw notFound(`Station ${params.station_id} not found in CO-OPS or NDBC. Use noaa_marine_find_stations to discover valid IDs.`, {
103
- station_id: params.station_id,
104
- });
139
+ // No catalog that answered carries the ID. Whether that means "this station does not exist"
140
+ // depends on whether every catalog was actually read — a rejected leg was never searched, so
141
+ // reporting NotFound for it would assert something the handler never checked.
142
+ const unread = [];
143
+ const answered = [];
144
+ (coopsResult.status === 'rejected' ? unread : answered).push('coops');
145
+ (ndbcResult.status === 'rejected' ? unread : answered).push('ndbc');
146
+ if (unread.length > 0) {
147
+ const searched = answered.length > 0
148
+ ? `it is not in the ${answered.join(' or ')} catalog`
149
+ : 'no catalog could be searched';
150
+ throw ctx.fail('source_unavailable', `Station ${params.station_id} could not be resolved: the ${unread.join(' and ')} ${unread.length > 1 ? 'catalogs' : 'catalog'} could not be read, and ${searched}.`, {
151
+ ...ctx.recoveryFor('source_unavailable'),
152
+ station_id: params.station_id,
153
+ unread_sources: unread,
154
+ });
155
+ }
156
+ throw ctx.fail('station_not_found', `Station ${params.station_id} not found in CO-OPS or NDBC. Use noaa_marine_find_stations to discover valid IDs.`, { ...ctx.recoveryFor('station_not_found'), station_id: params.station_id });
105
157
  },
106
158
  });
107
159
  //# sourceMappingURL=noaa-marine-station.resource.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"noaa-marine-station.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/noaa-marine-station.resource.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"noaa-marine-station.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/noaa-marine-station.resource.ts"],"names":[],"mappings":"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"}
@@ -79,6 +79,7 @@ export declare const noaaMarineFindStations: import("@cyanheads/mcp-ts-core").To
79
79
  met: "met";
80
80
  tide: "tide";
81
81
  water_level: "water_level";
82
+ water_quality: "water_quality";
82
83
  }>>>;
83
84
  limit: z.ZodDefault<z.ZodNumber>;
84
85
  }, z.core.$strip>, z.ZodObject<{
@@ -96,18 +97,49 @@ export declare const noaaMarineFindStations: import("@cyanheads/mcp-ts-core").To
96
97
  distance_km: z.ZodOptional<z.ZodNumber>;
97
98
  state: z.ZodOptional<z.ZodString>;
98
99
  capabilities: z.ZodArray<z.ZodString>;
100
+ prediction_class: z.ZodOptional<z.ZodString>;
101
+ reference_id: z.ZodOptional<z.ZodString>;
102
+ bins: z.ZodOptional<z.ZodArray<z.ZodObject<{
103
+ bin: z.ZodNumber;
104
+ depth: z.ZodNullable<z.ZodNumber>;
105
+ depth_type: z.ZodOptional<z.ZodString>;
106
+ prediction_class: z.ZodOptional<z.ZodString>;
107
+ }, z.core.$strip>>>;
99
108
  }, z.core.$strip>>;
100
109
  total_found: z.ZodNumber;
101
110
  truncated: z.ZodOptional<z.ZodBoolean>;
102
111
  }, z.core.$strip>, readonly [{
103
- readonly reason: "no_results";
104
- readonly code: JsonRpcErrorCode.NotFound;
105
- readonly when: "No stations match the query, location, or filters.";
106
- readonly recovery: "Widen the search by increasing radius_km, removing type filters, or using a broader query.";
107
- }, {
108
112
  readonly reason: "incomplete_coordinates";
109
113
  readonly code: JsonRpcErrorCode.InvalidParams;
110
114
  readonly when: "Only one of latitude/longitude was supplied — proximity search needs the pair.";
111
115
  readonly recovery: "Supply both latitude and longitude to search by proximity, or drop both and search by query or state instead.";
112
- }], undefined>;
116
+ }, {
117
+ readonly reason: "sources_unavailable";
118
+ readonly code: JsonRpcErrorCode.ServiceUnavailable;
119
+ readonly when: "Every station catalog this search needed failed to load, so no station list could be searched.";
120
+ readonly recovery: "Retry the search in a few moments — a catalog is cached for six hours once a fetch succeeds.";
121
+ }], {
122
+ readonly applied_search: z.ZodOptional<z.ZodObject<{
123
+ catalogs_read: z.ZodArray<z.ZodString>;
124
+ center: z.ZodOptional<z.ZodObject<{
125
+ latitude: z.ZodNumber;
126
+ longitude: z.ZodNumber;
127
+ }, z.core.$strip>>;
128
+ query: z.ZodOptional<z.ZodString>;
129
+ radius_km: z.ZodOptional<z.ZodNumber>;
130
+ source: z.ZodString;
131
+ state: z.ZodOptional<z.ZodString>;
132
+ types: z.ZodOptional<z.ZodArray<z.ZodString>>;
133
+ types_by_source: z.ZodOptional<z.ZodObject<{
134
+ coops: z.ZodArray<z.ZodString>;
135
+ ndbc: z.ZodArray<z.ZodString>;
136
+ }, z.core.$strip>>;
137
+ }, z.core.$strip>>;
138
+ readonly notice: z.ZodOptional<z.ZodString>;
139
+ readonly sources: z.ZodOptional<z.ZodObject<{
140
+ answered: z.ZodArray<z.ZodString>;
141
+ attempted: z.ZodArray<z.ZodString>;
142
+ failed: z.ZodArray<z.ZodString>;
143
+ }, z.core.$strip>>;
144
+ }>;
113
145
  //# sourceMappingURL=noaa-marine-find-stations.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"noaa-marine-find-stations.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/noaa-marine-find-stations.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA0EjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA0YjC,CAAC"}
1
+ {"version":3,"file":"noaa-marine-find-stations.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/noaa-marine-find-stations.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAmPjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+jBjC,CAAC"}