@cyanheads/wsdot-mcp-server 0.2.5 → 0.3.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 (64) hide show
  1. package/AGENTS.md +45 -18
  2. package/CLAUDE.md +45 -18
  3. package/README.md +77 -81
  4. package/changelog/0.2.x/0.2.6.md +29 -0
  5. package/changelog/0.3.x/0.3.0.md +30 -0
  6. package/changelog/template.md +9 -26
  7. package/dist/index.js +4 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/mcp-server/tools/definitions/get-border-waits.tool.d.ts +2 -0
  10. package/dist/mcp-server/tools/definitions/get-border-waits.tool.d.ts.map +1 -1
  11. package/dist/mcp-server/tools/definitions/get-border-waits.tool.js +3 -1
  12. package/dist/mcp-server/tools/definitions/get-border-waits.tool.js.map +1 -1
  13. package/dist/mcp-server/tools/definitions/get-ferry-alerts.tool.d.ts +2 -0
  14. package/dist/mcp-server/tools/definitions/get-ferry-alerts.tool.d.ts.map +1 -1
  15. package/dist/mcp-server/tools/definitions/get-ferry-alerts.tool.js +2 -0
  16. package/dist/mcp-server/tools/definitions/get-ferry-alerts.tool.js.map +1 -1
  17. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.d.ts +2 -0
  18. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.js +3 -1
  20. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.js.map +1 -1
  21. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.d.ts +2 -0
  22. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.d.ts.map +1 -1
  23. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.js +11 -7
  24. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.js.map +1 -1
  25. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.d.ts +2 -0
  26. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.js +3 -1
  28. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.js.map +1 -1
  29. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.d.ts +2 -0
  30. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.d.ts.map +1 -1
  31. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.js +3 -1
  32. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.js.map +1 -1
  33. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.d.ts +2 -0
  34. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.d.ts.map +1 -1
  35. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.js +4 -0
  36. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.js.map +1 -1
  37. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.d.ts +6 -0
  38. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.d.ts.map +1 -1
  39. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.js +126 -80
  40. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.js.map +1 -1
  41. package/dist/mcp-server/tools/definitions/get-travel-times.tool.d.ts +2 -0
  42. package/dist/mcp-server/tools/definitions/get-travel-times.tool.d.ts.map +1 -1
  43. package/dist/mcp-server/tools/definitions/get-travel-times.tool.js +105 -101
  44. package/dist/mcp-server/tools/definitions/get-travel-times.tool.js.map +1 -1
  45. package/dist/mcp-server/tools/definitions/get-vessel-locations.tool.d.ts +2 -0
  46. package/dist/mcp-server/tools/definitions/get-vessel-locations.tool.d.ts.map +1 -1
  47. package/dist/mcp-server/tools/definitions/get-vessel-locations.tool.js +3 -1
  48. package/dist/mcp-server/tools/definitions/get-vessel-locations.tool.js.map +1 -1
  49. package/dist/mcp-server/tools/definitions/search-alerts.tool.d.ts +12 -0
  50. package/dist/mcp-server/tools/definitions/search-alerts.tool.d.ts.map +1 -1
  51. package/dist/mcp-server/tools/definitions/search-alerts.tool.js +155 -131
  52. package/dist/mcp-server/tools/definitions/search-alerts.tool.js.map +1 -1
  53. package/dist/mcp-server/tools/definitions/search-cameras.tool.d.ts +14 -0
  54. package/dist/mcp-server/tools/definitions/search-cameras.tool.d.ts.map +1 -1
  55. package/dist/mcp-server/tools/definitions/search-cameras.tool.js +121 -68
  56. package/dist/mcp-server/tools/definitions/search-cameras.tool.js.map +1 -1
  57. package/dist/mcp-server/tools/page-budget.d.ts +56 -0
  58. package/dist/mcp-server/tools/page-budget.d.ts.map +1 -0
  59. package/dist/mcp-server/tools/page-budget.js +76 -0
  60. package/dist/mcp-server/tools/page-budget.js.map +1 -0
  61. package/dist/services/ferry/ferry-service.js +3 -3
  62. package/dist/services/traffic/traffic-service.js +3 -3
  63. package/package.json +10 -9
  64. package/server.json +3 -3
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.2.5-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/wsdot-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/wsdot-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/wsdot-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.3.0+-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-0.3.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/wsdot-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/wsdot-mcp-server?style=flat-square&logo=npm&logoColor=white)](https://www.npmjs.com/package/@cyanheads/wsdot-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%2B-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
@@ -23,18 +23,20 @@
23
23
 
24
24
  ---
25
25
 
26
- ## Tools
26
+ ## Overview
27
27
 
28
- 12 tools split across two domains — traffic (WSDOT Traveler API) and ferries (WSF Ferry API):
28
+ Washington State transportation data from the WSDOT Traveler API and the WSF Ferry API. Query mountain pass and highway conditions, search alerts and cameras, and track ferry schedules, vessel locations, and terminal space from any MCP client. Runs as a stdio process, a local Streamable HTTP server, or the public hosted endpoint above.
29
+
30
+ ### Tools
29
31
 
30
32
  | Tool | Description |
31
33
  |:---|:---|
32
34
  | `wsdot_get_mountain_passes` | Current conditions for all WA mountain passes: status, road condition, traction laws, temperature, elevation. |
33
35
  | `wsdot_search_alerts` | Active highway alerts — incidents, construction, closures — filterable by state route, WSDOT region, and milepost range. |
34
36
  | `wsdot_get_travel_times` | Current vs. average travel times for named WA highway corridors (I-5, I-90, SR 520, etc.) with congestion delay. |
35
- | `wsdot_get_toll_rates` | Dynamic toll rates for WA express lanes and tolled facilities: SR 99, SR 167 HOT, I-405 Express, SR 509, SR 520. |
37
+ | `wsdot_get_toll_rates` | Dynamic toll rates for WA express lanes and tolled facilities — SR 99, SR 167 HOT, I-405 Express, SR 509, SR 520 — filterable by route. |
36
38
  | `wsdot_get_border_waits` | Current vehicle wait times at all WA/Canada land border crossings. |
37
- | `wsdot_search_cameras` | Highway camera metadata and image URLs, filterable by state route, region, and milepost range. |
39
+ | `wsdot_search_cameras` | Highway camera metadata and image URLs, filterable by state route, region, milepost range, and title words. |
38
40
  | `wsdot_get_ferry_terminals` | All WSF ferry terminals with numeric IDs needed for schedule and space lookups. |
39
41
  | `wsdot_get_ferry_routes` | WSF routes operating on a given date — route ID, abbreviation, and description for each, for route discovery and ferry-alert cross-reference. |
40
42
  | `wsdot_get_ferry_schedule` | Departure times for a specific WSF route — today-remaining or full-day future mode. |
@@ -42,112 +44,101 @@
42
44
  | `wsdot_get_terminal_space` | Drive-up and reservable vehicle space available at WSF terminals for upcoming sailings. |
43
45
  | `wsdot_get_ferry_alerts` | Active WSF service disruptions and bulletins with impacted route IDs. |
44
46
 
45
- ### `wsdot_get_mountain_passes`
47
+ ## Capability reference
46
48
 
47
- Current road conditions for all WA mountain passes.
49
+ ### `wsdot_get_mountain_passes` <sub>tool</sub>
48
50
 
49
- - Covers all 16 passes: Snoqualmie, Stevens, White, Blewett, Cayuse, and others
50
- - Fields include status (Open/Closed/Caution), road surface, active traction law, temperature, and elevation
51
- - Use for "is the pass open?", traction law checks, or winter driving planning
51
+ - No input parameters — returns current conditions for all 16 WA mountain passes (Snoqualmie, Stevens, White, Blewett, Cayuse, and others) in one call
52
+ - Fields include road condition, weather, temperature, elevation, and up to two directional traction/travel restrictions
53
+ - Use for "is the pass open?", traction-law checks, or winter driving planning
52
54
 
53
55
  ---
54
56
 
55
- ### `wsdot_search_alerts`
56
-
57
- Active WA highway alerts — incidents, construction, closures, restrictions.
57
+ ### `wsdot_search_alerts` <sub>tool</sub>
58
58
 
59
59
  - Filter by state route — natural forms all work: `"I-90"`, `"90"`, `"090"`, or `"SR 520"` / `"520"`
60
- - Filter by WSDOT region: Northwest, Olympic, Southwest, South Central, North Central, Eastern
61
- - Filter by milepost range to scope to a corridor — an alert matches when its extent overlaps the range, so a closure that spans the boundary is returned
62
- - Omit all filters to return all current statewide alerts
63
- - Descriptions are plain text — upstream authors them with markup, and a link is rendered inline as `link text (url)` so the destination survives
64
- - Results are ordered by `alertId` and paged (default 50, max 500) — pass `offset`/`limit` to page through the full statewide set; the notice reports the next offset. Upstream returns the same alert set in more than one row order, so the ordering is imposed here to keep a given offset reproducible
60
+ - Filter by WSDOT region name: Northwest, Olympic, Southwest, South Central, North Central, Eastern (case-insensitive; any other value is rejected with `invalid_region`)
61
+ - Filter by milepost range to scope to a corridor — an alert matches when its extent overlaps the range, so a closure that spans the boundary is returned. Either bound may be given alone; a start above the end is rejected with `invalid_milepost_range`
62
+ - Omit all filters to return all current statewide alerts; `stateRoute` and `region` accept at most 200 characters
63
+ - Descriptions are normalized to plain text; a link renders inline as `link text (url)`
64
+ - Results ordered by `alertId` and paged (default 20, max 500) — pass `offset`/`limit`; a page also ends early at a 24,000-byte response budget, and the notice reports the next offset
65
65
 
66
66
  ---
67
67
 
68
- ### `wsdot_get_travel_times`
69
-
70
- Current vs. average travel times for named WA highway corridors.
68
+ ### `wsdot_get_travel_times` <sub>tool</sub>
71
69
 
72
70
  - Covers I-5, I-90, SR 520, SR 99, I-405, SR 167, and others
73
- - Filter by route (`"I-5"`, `"5"`, `"SR 520"`) to get every corridor measured on it, or by any text to match corridor names (`"Everett"`)
71
+ - Filter by route (`"I-5"`, `"5"`, `"SR 520"`) to get every corridor measured on it, or by any text to match corridor names (`"Everett"`); `route` accepts at most 200 characters
74
72
  - When current time exceeds average, the corridor is congested; the delta is the delay
75
73
  - Reversible express-lane corridors report no travel time while closed in the queried direction — those figures are omitted rather than reported as zero minutes
76
- - Results are paged (default 50, max 500) — pass `offset`/`limit` to page through the full statewide set; the notice reports the next offset
74
+ - Results are paged (default 50, max 500) — pass `offset`/`limit`; a page also ends early at a 24,000-byte response budget, and the notice reports the next offset
77
75
 
78
76
  ---
79
77
 
80
- ### `wsdot_get_toll_rates`
81
-
82
- Current dynamic toll rates for WA tolled facilities.
78
+ ### `wsdot_get_toll_rates` <sub>tool</sub>
83
79
 
84
- - SR 99 (WSDOT Tunnel), SR 167 HOT Lanes, I-405 Express Lanes, the SR 509 tolled segment, and the SR 520 Bridge
80
+ - Covers SR 99 (WSDOT Tunnel), SR 167 HOT Lanes, I-405 Express Lanes, the SR 509 tolled segment, and the SR 520 Bridge
85
81
  - Rates are time-banded and change dynamically based on traffic conditions
86
- - `stateRoute` is a bare, zero-padded route number (`"099"`, `"405"`) with no route type; the rendered text resolves the posted designation, so I-405 reads as `I-405` rather than `SR 405`
82
+ - Filter to one facility with `stateRoute` — `"SR 520"`, `"520"`, `"0520"`, `"I-405"`, and `"405"` all work, matched against the posted designation, so `"SR 405"` matches nothing. A route with no tolled facility returns an empty page whose notice names the tolled routes; the filter (at most 200 characters) is applied before paging and echoed in `appliedFilters`
83
+ - Each row's `stateRoute` is the bare, zero-padded route number the feed carries (`"099"`, `"405"`) with no route type; the rendered text resolves the posted designation, so I-405 reads as `I-405` rather than `SR 405`
84
+ - `travelDirection` is the feed's code, not the direction of travel: SR 99, SR 509, and SR 520 carry one fixed code per facility although trips run both ways — read direction from the segment's start and end
87
85
  - Each entry leads with its readable `startLocationName → endLocationName` segment; the opaque upstream trip key stays available as `tripName`
88
- - Results are paged (default 50, max 500) — pass `offset`/`limit` to page through the full statewide set; the notice reports the next offset
86
+ - Results are paged (default 50, max 500) — pass `offset`/`limit`; a page also ends early at a 24,000-byte response budget, and the notice reports the next offset
89
87
 
90
88
  ---
91
89
 
92
- ### `wsdot_get_border_waits`
90
+ ### `wsdot_get_border_waits` <sub>tool</sub>
93
91
 
94
- Current vehicle wait times at WA/Canada land border crossings.
95
-
96
- - Covers I-5 (Peace Arch, Blaine), SR 543 (Pacific Highway, Blaine), SR 539 (Lynden), and SR 9 (Sumas)
92
+ - No input parameters — covers I-5 (Peace Arch, Blaine), SR 543 (Pacific Highway, Blaine), SR 539 (Lynden), and SR 9 (Sumas)
97
93
  - Each crossing reports a general-purpose lane and a Nexus lane; SR 539 adds a truck lane and SR 543 adds truck and FAST truck lanes — eleven entries in `crossings[]`, one per lane
98
94
  - `crossingName` is a route code (e.g. `I5`, `SR543Trucks`); `location.description` holds the readable name
99
95
  - Wait times in minutes; `updateTime` is ISO 8601. A crossing reporting no current data is still returned — only `waitTimeInMinutes` is omitted, and the rendered text reads `Not available`
100
96
 
101
97
  ---
102
98
 
103
- ### `wsdot_search_cameras`
104
-
105
- WSDOT highway camera metadata and image URLs.
99
+ ### `wsdot_search_cameras` <sub>tool</sub>
106
100
 
107
- - Filter by state route (`"I-90"`, `"90"`, `"SR 520"`, or `"520"` all work), WSDOT region, or milepost range
101
+ - Filter by state route (`"I-90"`, `"90"`, `"SR 520"`, or `"520"` all work), WSDOT region code, milepost range, or words in the camera title; `stateRoute`, `region`, and `titleContains` accept at most 200 characters
108
102
  - Camera road names carry a route-type prefix, so `"SR 26"` excludes US 26 and `"US 97"` excludes US 97A; a bare `"26"` returns both
103
+ - Region codes: `NW`, `SW`, `OL`, `ER`, `SC`, `NC`, `OS` (Oregon — the TripCheck cameras around Portland), and `WA` (airport cameras plus a few ferry-terminal cameras — most ferry-terminal cameras sit in `NW` and `OL`). Case-insensitive; any other value is rejected with `invalid_region`
104
+ - `titleContains` matches the title as WSDOT wrote it — case-insensitive, every word must appear in any order — so `"Snoqualmie"` returns Snoqualmie Summit and East Snoqualmie Summit but not Hyak. Titles lead with route and milepost, so filter a route with `stateRoute`
105
+ - Either milepost bound may be given alone; a start above the end is rejected with `invalid_milepost_range`
109
106
  - Returns metadata and image URLs — camera images are copyright WSDOT, not fetched as bytes
110
- - Results are ordered by `cameraId` and paged (default 50, max 500) — pass `offset`/`limit` to page through the full statewide set; the notice reports the next offset. Upstream returns the same camera set in more than one row order, so the ordering is imposed here to keep a given offset reproducible
107
+ - Results are ordered by `cameraId` and paged (default 50, max 500) — pass `offset`/`limit`; a page also ends early at a 24,000-byte response budget, and the notice reports the next offset
111
108
 
112
109
  ---
113
110
 
114
- ### `wsdot_get_ferry_terminals`
115
-
116
- All WSF ferry terminals with numeric IDs.
111
+ ### `wsdot_get_ferry_terminals` <sub>tool</sub>
117
112
 
118
- - 20 terminals; the list rarely changes
113
+ - No input parameters — returns all 20 WSF ferry terminals; the list rarely changes
119
114
  - Call this first to resolve human-readable names (e.g. "Bainbridge Island", "Seattle", "Kingston") to the numeric IDs required by `wsdot_get_ferry_schedule` and `wsdot_get_terminal_space`
115
+ - Each terminal also carries an abbreviation and coordinates when reported
120
116
 
121
117
  ---
122
118
 
123
- ### `wsdot_get_ferry_routes`
124
-
125
- WSF ferry routes operating on a given date.
119
+ ### `wsdot_get_ferry_routes` <sub>tool</sub>
126
120
 
121
+ - Optional `tripDate` (ISO 8601 `YYYY-MM-DD`); defaults to today
127
122
  - Returns each route's ID, abbreviation, and description
128
123
  - Route IDs correspond to `impactedRouteIds` in `wsdot_get_ferry_alerts` — use this tool to resolve alert route IDs to route names
129
124
  - Use to discover which routes are running; for the numeric terminal IDs that schedule and space lookups need, call `wsdot_get_ferry_terminals`
130
125
 
131
126
  ---
132
127
 
133
- ### `wsdot_get_ferry_schedule`
134
-
135
- Departure times for a specific WSF ferry route.
128
+ ### `wsdot_get_ferry_schedule` <sub>tool</sub>
136
129
 
137
- - Requires numeric terminal IDs — use `wsdot_get_ferry_terminals` first
138
- - `remainingOnly: true` returns only future departures for today (useful for "next ferry" queries)
139
- - For future dates, all sailings for that day are returned
130
+ - Requires `departingTerminalId` and `arrivingTerminalId`, both positive integers — use `wsdot_get_ferry_terminals` first
131
+ - Optional `tripDate` (defaults to today) and `remainingOnly: true` (only future departures for today; ignored for future dates)
140
132
  - `departureTime` and `arrivalTime` are ISO 8601 **UTC**, while `tripDate` is the Pacific service day — an evening sailing therefore carries the following UTC calendar date and will not match `tripDate`. Convert to `America/Los_Angeles` before quoting a clock time
141
133
  - `arrivalTime` is populated on some routes and absent on others
142
134
  - No cancellation status — WSF drops a cancelled sailing from the schedule rather than flagging it, so a listed sailing is not confirmation it will run; check `wsdot_get_ferry_alerts`, which reports disruptions at route level
135
+ - An invalid or non-through terminal pair returns a typed `invalid_terminal_pair` error rather than an empty schedule
143
136
 
144
137
  ---
145
138
 
146
- ### `wsdot_get_vessel_locations`
139
+ ### `wsdot_get_vessel_locations` <sub>tool</sub>
147
140
 
148
- Real-time AIS positions for all active WSF vessels.
149
-
150
- - Fields include position, speed, heading, ETA, and dock status
141
+ - No input parameters — fields include position, speed, heading, ETA, and dock status for every active WSF vessel
151
142
  - Use for "where is the ferry now?" or checking if a specific vessel is in service
152
143
  - Position data may lag 30–60 seconds; many fields are null for vessels not currently operating
153
144
  - Coordinates render at full upstream AIS precision — no rounding, so both response surfaces report the same position
@@ -155,55 +146,60 @@ Real-time AIS positions for all active WSF vessels.
155
146
 
156
147
  ---
157
148
 
158
- ### `wsdot_get_terminal_space`
159
-
160
- Real-time vehicle space availability at WSF terminals for upcoming sailings.
149
+ ### `wsdot_get_terminal_space` <sub>tool</sub>
161
150
 
151
+ - Filter to a specific terminal by ID (from `wsdot_get_ferry_terminals`); omit for all terminals
162
152
  - `driveUpSpaceCount` is the key field — zero means the drive-up lane is full. Oversubscribed sailings report a negative count upstream; it is floored to zero so the value never reads as available space
163
153
  - `arrivingTerminalIds` lists the terminals a sailing serves and chains straight into `wsdot_get_ferry_schedule`; `itineraryLabel` is a display string that may name several stops, not a single destination
164
- - Filter to a specific terminal by ID (from `wsdot_get_ferry_terminals`)
165
- - Use for "will I make the ferry?" or "how full is the next sailing?" queries
166
154
  - Results are paged by terminal (default 5, max 20) — `offset`/`limit` select whole terminals and `totalCount` counts matching terminals, not sailings; every sailing of a returned terminal is included, so page size varies with how many departures each terminal carries
167
155
 
168
156
  ---
169
157
 
170
- ### `wsdot_get_ferry_alerts`
171
-
172
- Active WSF ferry service disruptions, delays, and bulletins.
158
+ ### `wsdot_get_ferry_alerts` <sub>tool</sub>
173
159
 
160
+ - No input parameters — active WSF ferry service disruptions, delays, and bulletins
174
161
  - Each alert carries the bulletin's `alertTitle`, its one-line `alertDescription`, and the full `bulletinText` — detail such as a replacement sailing appears only in the body
175
162
  - `bulletinText` is plain text: upstream authors it as HTML, and a link is rendered inline as `link text (url)`
176
163
  - Each alert includes `impactedRouteIds` — cross-reference with `wsdot_get_ferry_routes` to map route IDs to names
177
164
  - `affectsAllRoutes: true` marks a fleet-wide alert, which need not enumerate routes — an empty `impactedRouteIds` then means every route rather than none
178
165
 
179
- ---
180
-
181
166
  ## Features
182
167
 
183
- Built on [`@cyanheads/mcp-ts-core`](https://www.npmjs.com/package/@cyanheads/mcp-ts-core):
184
-
185
- - Declarative tool definitions — single file per tool, framework handles registration and validation
186
- - Unified error handling across all tools
187
- - Pluggable auth (`none`, `jwt`, `oauth`)
188
- - Swappable storage backends: `in-memory`, `filesystem`, `Supabase`, `Cloudflare KV/R2/D1`
189
- - Structured logging with optional OpenTelemetry tracing
190
- - STDIO and Streamable HTTP transports
168
+ Built on [`@cyanheads/mcp-ts-core`](https://github.com/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.
191
169
 
192
170
  WSDOT-specific:
193
171
 
194
- - Dual API integration — WSDOT Traffic API and WSF Ferry API from a single access code
195
- - Retry, timeout, and HTML-detection guards on all upstream requests
196
- - Normalized response shapes across both APIs — sparse upstream fields surfaced as optional rather than omitted
172
+ - Dual API integration — WSDOT Traffic API and WSF Ferry API share a single `WSDOT_ACCESS_CODE`
173
+ - Cross-tool linking built into tool descriptions — ferry tools point to `wsdot_get_ferry_terminals` / `wsdot_get_ferry_routes` for ID resolution before a lookup
174
+ - Normalized response shapes across both APIs — sparse upstream fields surface as optional rather than omitted or defaulted
175
+ - Stable pagination — the alert and camera feeds return the same set in more than one row order upstream, so results are sorted by ID to keep a given offset reproducible
197
176
 
198
177
  Agent-friendly output:
199
178
 
200
- - Cross-tool linking built into descriptions — ferry tools document which tool to call first for terminal and route ID resolution
201
- - `driveUpSpaceCount: 0` and congestion delta fields give agents actionable signal without string parsing
202
- - Partial data preserved — sparse upstream payloads surface `null`/`undefined` rather than synthetic defaults
179
+ - Typed failure — `invalid_access_code` and `api_unavailable` errors carry an explicit recovery hint distinguishing configuration faults from transient upstream ones
180
+ - `driveUpSpaceCount: 0` and congestion delta fields (`delayInMinutes`) give agents actionable signal without string parsing
181
+ - Partial data preserved — sparse upstream payloads surface `null`/`undefined` rather than synthetic defaults (e.g. an omitted `waitTimeInMinutes`, an absent `arrivalTime`)
203
182
  - `content[]` and `structuredContent` carry the same values, not just the same fields — a `false` flag, an empty list, and one populated half of a coordinate pair all render rather than dropping out of the markdown surface that some clients read
204
183
 
205
184
  ## Getting started
206
185
 
186
+ ### Public Hosted Instance
187
+
188
+ A public instance is available at `https://wsdot.caseyjhand.com/mcp` — no installation required. Point any MCP client at it via Streamable HTTP:
189
+
190
+ ```json
191
+ {
192
+ "mcpServers": {
193
+ "wsdot-mcp-server": {
194
+ "type": "streamable-http",
195
+ "url": "https://wsdot.caseyjhand.com/mcp"
196
+ }
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### Self-Hosted / Local
202
+
207
203
  Add the following to your MCP client configuration file. You'll need a WSDOT Traveler API access code — register at [wsdot.wa.gov/Traffic/api/](https://wsdot.wa.gov/Traffic/api/).
208
204
 
209
205
  ```json
@@ -270,7 +266,7 @@ MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 WSDOT_ACCESS_CODE=your-access-code bu
270
266
 
271
267
  ### Prerequisites
272
268
 
273
- - [Bun v1.3.0](https://bun.sh/) or higher (or Node.js v24+).
269
+ - [Bun v1.4.0](https://bun.sh/) or higher (or Node.js v24+).
274
270
  - A WSDOT Traveler API access code. Register at [wsdot.wa.gov/Traffic/api/](https://wsdot.wa.gov/Traffic/api/) — registration is free.
275
271
 
276
272
  ### Installation
@@ -376,7 +372,7 @@ See [`CLAUDE.md`](./CLAUDE.md) for development guidelines and architectural rule
376
372
 
377
373
  ## Contributing
378
374
 
379
- Issues and pull requests are welcome. Run checks and tests before submitting:
375
+ Issues are welcome. Run checks and tests before submitting:
380
376
 
381
377
  ```sh
382
378
  bun run devcheck
@@ -0,0 +1,29 @@
1
+ ---
2
+ summary: "mcp-ts-core 0.13.6 — invalid_date and invalid_terminal_pair recovery hints now reach the wire on the ferry route and schedule tools, matching their declared error contracts."
3
+ breaking: false
4
+ security: false
5
+ ---
6
+
7
+ # 0.2.6 — 2026-09-20
8
+
9
+ ## Changed
10
+
11
+ - **`sessionMode: 'stateless'`** is now declared explicitly in `src/index.ts` rather than left to `MCP_SESSION_MODE` — no tool calls `ctx.requestInput`.
12
+ - **A tool error carrying a `reason` or boolean `retryable`** now closes its `content[]` text with a `(reason … · not retryable)` trailer, and an argument outside a tool's schema is rejected as `InvalidParams` (-32602) with the same readable message plus a recovery line (mcp-ts-core 0.13.x).
13
+ - **Framework skill tree relocates from `skills/` to `framework-skills/`** so a plugin-shipping server doesn't leak development skills to installing agents; scripts, plugin manifests, and issue templates resync to match.
14
+
15
+ ## Fixed
16
+
17
+ - **`wsdot_get_ferry_routes` and `wsdot_get_ferry_schedule` forward their declared recovery hint** for a malformed `tripDate` — previously declared in the error contract but never reaching the client, it now appears in `structuredContent.error.data.recovery.hint` and as a `Recovery:` line in `content[0].text`.
18
+ - **`wsdot_get_ferry_schedule`'s `invalid_terminal_pair` hint** now comes from its declared error contract instead of a separately worded string in the handler, so the two can no longer drift; the wording the caller sees changes slightly.
19
+
20
+ ## Dependencies
21
+
22
+ - `@cyanheads/mcp-ts-core` `^0.12.3` → `^0.13.6`
23
+ - `zod` `^4.4.3` → `^4.6.5`
24
+ - `@biomejs/biome` `^2.5.10` → `^2.5.14` (dev)
25
+ - `@types/node` `^26.2.0` → `^26.6.1` (dev)
26
+ - `ignore` `^7.0.6` → `^7.0.9` (dev)
27
+ - `tsc-alias` `^1.9.2` → `^1.9.5` (dev)
28
+ - `vitest` `^4.1.11` → `^5.0.1` (dev)
29
+ - `engines.bun` floor rises to `>=1.4.0`
@@ -0,0 +1,30 @@
1
+ ---
2
+ summary: "Traffic tools reject invalid regions and reversed milepost ranges, toll rates gain a stateRoute filter and cameras a titleContains filter, and each traffic page now ends at a 24,000-byte budget per surface."
3
+ breaking: true
4
+ security: false
5
+ ---
6
+
7
+ # 0.3.0 — 2026-09-24
8
+
9
+ ## Added
10
+
11
+ - **`wsdot_get_toll_rates` `stateRoute` filter** ([#44](https://github.com/cyanheads/wsdot-mcp-server/issues/44)) — `"SR 520"`, `"520"`, `"0520"`, `"I-405"`, and `"405"` all work, matched against the posted designation before paging and echoed in a new `appliedFilters` enrichment. A route with no tolled facility returns an empty page whose notice names the tolled routes.
12
+ - **`wsdot_search_cameras` `titleContains` filter** ([#45](https://github.com/cyanheads/wsdot-mcp-server/issues/45)) — case-insensitive, every whitespace-separated word must appear in the camera title; composes with the other filters and is echoed in `appliedFilters`.
13
+ - **Page byte budget** ([#43](https://github.com/cyanheads/wsdot-mcp-server/issues/43)) — `wsdot_search_alerts`, `wsdot_search_cameras`, `wsdot_get_travel_times`, and `wsdot_get_toll_rates` end a page at `limit` or at 24,000 bytes per surface (`structuredContent` and `content[]`), whichever comes first; a budget-ended page says so in its notice.
14
+
15
+ ## Changed
16
+
17
+ - **Invalid traffic filters fail instead of returning an empty page** ([#39](https://github.com/cyanheads/wsdot-mcp-server/issues/39)) — on `wsdot_search_alerts` and `wsdot_search_cameras`, a `region` outside the tool's vocabulary (names on alerts, codes on cameras; case-insensitive) raises `invalid_region`, and `startMilepost > endMilepost` raises `invalid_milepost_range`. Blank filters are still treated as omitted.
18
+ - **Ferry terminal IDs must be positive integers** — `departingTerminalId` on `wsdot_get_terminal_space` and both IDs on `wsdot_get_ferry_schedule`; anything else is an `InvalidParams` rejection that never reaches the upstream.
19
+ - **Free-text traffic filters accept at most 200 characters** — `stateRoute`, `region`, `route`, and `titleContains`.
20
+ - **`wsdot_search_alerts` default `limit`** drops from 50 to 20; the other three paged traffic tools stay at 50.
21
+ - **Migration:** a region outside the tool's vocabulary, a reversed milepost range, a non-positive or fractional terminal ID, or a filter over 200 characters now errors instead of returning an empty page; an alerts page defaults to 20 rows; and any traffic page may end before `limit` at the byte budget, reported through `hasMore` / `nextOffset` and the notice.
22
+
23
+ ## Fixed
24
+
25
+ - **`wsdot_get_toll_rates` output descriptions** — `stateRoute` is stated as the bare, zero-padded feed value, and `travelDirection` as one fixed code per facility on SR 99, SR 509, and SR 520 rather than the direction of travel.
26
+ - **`wsdot_search_cameras` `region` description** — `OS` is the Oregon TripCheck cameras around Portland and `WA` the airport cameras plus a few ferry-terminal cameras, not "Olympic South" and "statewide".
27
+
28
+ ## Dependencies
29
+
30
+ - `@types/node` `^26.6.1` → `^26.6.2` (dev)
@@ -6,8 +6,8 @@
6
6
 
7
7
  # Required. One-line GitHub Release-style headline. 350 character cap — a
8
8
  # ceiling, not a target. Default short and scannable. Don't pad, don't stitch
9
- # unrelated changes with commas/semicolons into an inventory — pick the
10
- # headline, like a tag's theme line. Quotes required: unquoted YAML treats
9
+ # unrelated changes with commas/semicolons into an inventory — pick the one
10
+ # headline the release is about. Quotes required: unquoted YAML treats
11
11
  # `: ` inside the value as a key separator and fails GitHub's strict parser.
12
12
  summary: ""
13
13
 
@@ -117,30 +117,13 @@ security: false
117
117
  in that unrelated item's metadata.
118
118
 
119
119
  TAG ANNOTATIONS — the annotated tag body renders as the GitHub Release body
120
- via `gh release create --notes-from-tag`. The tag is a derivative of this
121
- changelog entry — a condensed, scannable version, not a copy. Format:
122
-
123
- <theme — omit version number, GitHub prepends it>
124
- ← blank line
125
- <1-2 sentence context: what this release does>
126
- ← blank line
127
- Dependency bumps: ← section header
128
- ← blank line
129
- - `@cyanheads/mcp-ts-core` ^0.9.1 → ^0.9.6 ← bullet
130
- ← blank line
131
- Changed: ← only sections with entries
132
- ← blank line
133
- - `format()` output includes `query` in text mode
134
- ← blank line
135
- Added:
136
- ← blank line
137
- - `manifest.json` scaffolded for MCPB bundle support
138
- - Install badges (Claude Desktop, Cursor, VS Code)
139
- ← blank line
140
- <N> tests pass; `bun run devcheck` clean. ← footer
141
-
142
- Never a flat comma-separated string. Always structured markdown with
143
- sections. The tag must scan well as a rendered GitHub Release page.
120
+ via `gh release create --notes-from-tag`. It is a condensed digest of this
121
+ entry, never a copy, and its format is owned by the `release-and-publish`
122
+ skill (step 4, "Create the annotated tag"): a short subject line without the
123
+ version, flat headline bullets — no Keep-a-Changelog section headers, no
124
+ gates line — at most one deps line, issue backlinks, and the changelog link
125
+ last. In release-PR mode the `git-wrapup` skill authors those bullets as the
126
+ PR body's `## Changes` and the tag copies them.
144
127
  -->
145
128
 
146
129
  ## Added
package/dist/index.js CHANGED
@@ -10,6 +10,10 @@ import { initTrafficApiService } from './services/traffic/traffic-service.js';
10
10
  await createApp({
11
11
  name: 'wsdot-mcp-server',
12
12
  title: 'wsdot-mcp-server',
13
+ // Every tool is a single-shot read against an upstream API and none calls ctx.requestInput,
14
+ // so no session has to survive between calls. A deployment's MCP_SESSION_MODE still wins
15
+ // when it carries a meaningful value.
16
+ sessionMode: 'stateless',
13
17
  // The tool surface is fixed at build time, so a 2026-07-28 client may hold discovery
14
18
  // results for a day. Nothing here is tenant- or caller-specific — hence `public`.
15
19
  cacheHints: {
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,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,aAAa,GACd,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,kBAAkB;IACzB,qFAAqF;IACrF,kFAAkF;IAClF,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QACzD,iBAAiB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;KAC/D;IACD,KAAK,EAAE;QACL,iBAAiB;QACjB,YAAY;QACZ,cAAc;QACd,YAAY;QACZ,cAAc;QACd,aAAa;QACb,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,gBAAgB;QAChB,cAAc;KACf;IACD,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE;IACX,YAAY,EACV,2aAA2a;IAC7a,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;IAC/B,KAAK,CAAC,IAAI;QACR,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,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,EACL,cAAc,EACd,cAAc,EACd,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,YAAY,EACZ,aAAa,GACd,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,uCAAuC,CAAC;AAE9E,MAAM,SAAS,CAAC;IACd,IAAI,EAAE,kBAAkB;IACxB,KAAK,EAAE,kBAAkB;IACzB,4FAA4F;IAC5F,yFAAyF;IACzF,sCAAsC;IACtC,WAAW,EAAE,WAAW;IACxB,qFAAqF;IACrF,kFAAkF;IAClF,UAAU,EAAE;QACV,YAAY,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;QACzD,iBAAiB,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE;KAC/D;IACD,KAAK,EAAE;QACL,iBAAiB;QACjB,YAAY;QACZ,cAAc;QACd,YAAY;QACZ,cAAc;QACd,aAAa;QACb,iBAAiB;QACjB,cAAc;QACd,gBAAgB;QAChB,kBAAkB;QAClB,gBAAgB;QAChB,cAAc;KACf;IACD,SAAS,EAAE,EAAE;IACb,OAAO,EAAE,EAAE;IACX,YAAY,EACV,2aAA2a;IAC7a,OAAO,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE;IAC/B,KAAK,CAAC,IAAI;QACR,qBAAqB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACjD,mBAAmB,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACjD,CAAC;CACF,CAAC,CAAC"}
@@ -24,12 +24,14 @@ export declare const getBorderWaits: import("@cyanheads/mcp-ts-core").ToolDefini
24
24
  readonly when: "WSDOT Traffic API is unreachable or returns a non-2xx response after retries.";
25
25
  readonly retryable: true;
26
26
  readonly recovery: "Retry in 30 seconds. If the issue persists, check wsdot.wa.gov for service status.";
27
+ readonly thrownBy: "service";
27
28
  }, {
28
29
  readonly reason: "invalid_access_code";
29
30
  readonly code: JsonRpcErrorCode.ConfigurationError;
30
31
  readonly when: "WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.";
31
32
  readonly retryable: false;
32
33
  readonly recovery: "Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.";
34
+ readonly thrownBy: "service";
33
35
  }], {
34
36
  readonly totalCount: z.ZodNumber;
35
37
  readonly notice: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"get-border-waits.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-border-waits.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgIzB,CAAC"}
1
+ {"version":3,"file":"get-border-waits.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-border-waits.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAIjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkIzB,CAAC"}
@@ -4,7 +4,7 @@
4
4
  */
5
5
  import { tool, z } from '@cyanheads/mcp-ts-core';
6
6
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
- import { coordinatePair } from '../../../mcp-server/tools/coordinate-pair.js';
7
+ import { coordinatePair } from '../coordinate-pair.js';
8
8
  import { getTrafficApiService } from '../../../services/traffic/traffic-service.js';
9
9
  export const getBorderWaits = tool('wsdot_get_border_waits', {
10
10
  title: 'Get Border Wait Times',
@@ -71,6 +71,7 @@ export const getBorderWaits = tool('wsdot_get_border_waits', {
71
71
  when: 'WSDOT Traffic API is unreachable or returns a non-2xx response after retries.',
72
72
  retryable: true,
73
73
  recovery: 'Retry in 30 seconds. If the issue persists, check wsdot.wa.gov for service status.',
74
+ thrownBy: 'service',
74
75
  },
75
76
  {
76
77
  reason: 'invalid_access_code',
@@ -78,6 +79,7 @@ export const getBorderWaits = tool('wsdot_get_border_waits', {
78
79
  when: 'WSDOT rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.',
79
80
  retryable: false,
80
81
  recovery: 'Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.',
82
+ thrownBy: 'service',
81
83
  },
82
84
  ],
83
85
  async handler(_input, ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"get-border-waits.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-border-waits.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-border-waits.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-border-waits.tool.ts"],"names":[],"mappings":"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"}
@@ -21,12 +21,14 @@ export declare const getFerryAlerts: import("@cyanheads/mcp-ts-core").ToolDefini
21
21
  readonly when: "WSF Ferry API is unreachable or returns a non-2xx response after retries.";
22
22
  readonly retryable: true;
23
23
  readonly recovery: "Retry in 30 seconds. If the issue persists, check wsdot.wa.gov/ferries for service status.";
24
+ readonly thrownBy: "service";
24
25
  }, {
25
26
  readonly reason: "invalid_access_code";
26
27
  readonly code: JsonRpcErrorCode.ConfigurationError;
27
28
  readonly when: "WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.";
28
29
  readonly retryable: false;
29
30
  readonly recovery: "Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.";
31
+ readonly thrownBy: "service";
30
32
  }], {
31
33
  readonly totalCount: z.ZodNumber;
32
34
  readonly notice: z.ZodOptional<z.ZodString>;
@@ -1 +1 @@
1
- {"version":3,"file":"get-ferry-alerts.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-alerts.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;EA8HzB,CAAC"}
1
+ {"version":3,"file":"get-ferry-alerts.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-alerts.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgIzB,CAAC"}
@@ -61,6 +61,7 @@ export const getFerryAlerts = tool('wsdot_get_ferry_alerts', {
61
61
  when: 'WSF Ferry API is unreachable or returns a non-2xx response after retries.',
62
62
  retryable: true,
63
63
  recovery: 'Retry in 30 seconds. If the issue persists, check wsdot.wa.gov/ferries for service status.',
64
+ thrownBy: 'service',
64
65
  },
65
66
  {
66
67
  reason: 'invalid_access_code',
@@ -68,6 +69,7 @@ export const getFerryAlerts = tool('wsdot_get_ferry_alerts', {
68
69
  when: 'WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.',
69
70
  retryable: false,
70
71
  recovery: 'Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.',
72
+ thrownBy: 'service',
71
73
  },
72
74
  ],
73
75
  async handler(_input, ctx) {
@@ -1 +1 @@
1
- {"version":3,"file":"get-ferry-alerts.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-alerts.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"get-ferry-alerts.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-alerts.tool.ts"],"names":[],"mappings":"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"}
@@ -18,12 +18,14 @@ export declare const getFerryRoutes: import("@cyanheads/mcp-ts-core").ToolDefini
18
18
  readonly when: "WSF Ferry API is unreachable or returns a non-2xx response after retries.";
19
19
  readonly retryable: true;
20
20
  readonly recovery: "Retry in 30 seconds. If the issue persists, check wsdot.wa.gov/ferries for service status.";
21
+ readonly thrownBy: "service";
21
22
  }, {
22
23
  readonly reason: "invalid_access_code";
23
24
  readonly code: JsonRpcErrorCode.ConfigurationError;
24
25
  readonly when: "WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.";
25
26
  readonly retryable: false;
26
27
  readonly recovery: "Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.";
28
+ readonly thrownBy: "service";
27
29
  }, {
28
30
  readonly reason: "invalid_date";
29
31
  readonly code: JsonRpcErrorCode.ValidationError;
@@ -1 +1 @@
1
- {"version":3,"file":"get-ferry-routes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-routes.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsHzB,CAAC"}
1
+ {"version":3,"file":"get-ferry-routes.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/get-ferry-routes.tool.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAGjE,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAyHzB,CAAC"}
@@ -54,6 +54,7 @@ export const getFerryRoutes = tool('wsdot_get_ferry_routes', {
54
54
  when: 'WSF Ferry API is unreachable or returns a non-2xx response after retries.',
55
55
  retryable: true,
56
56
  recovery: 'Retry in 30 seconds. If the issue persists, check wsdot.wa.gov/ferries for service status.',
57
+ thrownBy: 'service',
57
58
  },
58
59
  {
59
60
  reason: 'invalid_access_code',
@@ -61,6 +62,7 @@ export const getFerryRoutes = tool('wsdot_get_ferry_routes', {
61
62
  when: 'WSF rejected the request because WSDOT_ACCESS_CODE is missing, invalid, or not registered.',
62
63
  retryable: false,
63
64
  recovery: 'Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.',
65
+ thrownBy: 'service',
64
66
  },
65
67
  {
66
68
  reason: 'invalid_date',
@@ -77,7 +79,7 @@ export const getFerryRoutes = tool('wsdot_get_ferry_routes', {
77
79
  : FerryApiService.todayFerryDate();
78
80
  }
79
81
  catch {
80
- throw ctx.fail('invalid_date', `Invalid date: "${input.tripDate}". Expected YYYY-MM-DD format (e.g. 2026-05-23).`);
82
+ throw ctx.fail('invalid_date', `Invalid date: "${input.tripDate}". Expected YYYY-MM-DD format (e.g. 2026-05-23).`, { ...ctx.recoveryFor('invalid_date') });
81
83
  }
82
84
  const routes = await getFerryApiService().getRoutes(tripDate, ctx);
83
85
  ctx.log.info('Ferry routes fetched', { tripDate, count: routes.length });