@cyanheads/wsdot-mcp-server 0.2.6 → 0.4.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 (66) hide show
  1. package/AGENTS.md +1 -1
  2. package/CLAUDE.md +1 -1
  3. package/README.md +32 -23
  4. package/changelog/0.3.x/0.3.0.md +30 -0
  5. package/changelog/0.4.x/0.4.0.md +26 -0
  6. package/dist/index.js +1 -1
  7. package/dist/index.js.map +1 -1
  8. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.d.ts +9 -2
  9. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.d.ts.map +1 -1
  10. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.js +40 -5
  11. package/dist/mcp-server/tools/definitions/get-ferry-routes.tool.js.map +1 -1
  12. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.d.ts +10 -3
  13. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.d.ts.map +1 -1
  14. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.js +96 -20
  15. package/dist/mcp-server/tools/definitions/get-ferry-schedule.tool.js.map +1 -1
  16. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.d.ts +2 -2
  17. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.d.ts.map +1 -1
  18. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.js +12 -5
  19. package/dist/mcp-server/tools/definitions/get-ferry-terminals.tool.js.map +1 -1
  20. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.d.ts +2 -2
  21. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.d.ts.map +1 -1
  22. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.js +9 -4
  23. package/dist/mcp-server/tools/definitions/get-mountain-passes.tool.js.map +1 -1
  24. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.d.ts.map +1 -1
  25. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.js +2 -0
  26. package/dist/mcp-server/tools/definitions/get-terminal-space.tool.js.map +1 -1
  27. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.d.ts +4 -0
  28. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.d.ts.map +1 -1
  29. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.js +123 -79
  30. package/dist/mcp-server/tools/definitions/get-toll-rates.tool.js.map +1 -1
  31. package/dist/mcp-server/tools/definitions/get-travel-times.tool.d.ts.map +1 -1
  32. package/dist/mcp-server/tools/definitions/get-travel-times.tool.js +103 -101
  33. package/dist/mcp-server/tools/definitions/get-travel-times.tool.js.map +1 -1
  34. package/dist/mcp-server/tools/definitions/search-alerts.tool.d.ts +10 -0
  35. package/dist/mcp-server/tools/definitions/search-alerts.tool.d.ts.map +1 -1
  36. package/dist/mcp-server/tools/definitions/search-alerts.tool.js +152 -130
  37. package/dist/mcp-server/tools/definitions/search-alerts.tool.js.map +1 -1
  38. package/dist/mcp-server/tools/definitions/search-cameras.tool.d.ts +12 -0
  39. package/dist/mcp-server/tools/definitions/search-cameras.tool.d.ts.map +1 -1
  40. package/dist/mcp-server/tools/definitions/search-cameras.tool.js +118 -67
  41. package/dist/mcp-server/tools/definitions/search-cameras.tool.js.map +1 -1
  42. package/dist/mcp-server/tools/page-budget.d.ts +56 -0
  43. package/dist/mcp-server/tools/page-budget.d.ts.map +1 -0
  44. package/dist/mcp-server/tools/page-budget.js +76 -0
  45. package/dist/mcp-server/tools/page-budget.js.map +1 -0
  46. package/dist/services/ferry/ferry-service.d.ts +20 -0
  47. package/dist/services/ferry/ferry-service.d.ts.map +1 -1
  48. package/dist/services/ferry/ferry-service.js +186 -49
  49. package/dist/services/ferry/ferry-service.js.map +1 -1
  50. package/dist/services/ferry/types.d.ts +52 -4
  51. package/dist/services/ferry/types.d.ts.map +1 -1
  52. package/dist/services/text-field.d.ts +31 -0
  53. package/dist/services/text-field.d.ts.map +1 -0
  54. package/dist/services/text-field.js +41 -0
  55. package/dist/services/text-field.js.map +1 -0
  56. package/dist/services/traffic/traffic-service.d.ts.map +1 -1
  57. package/dist/services/traffic/traffic-service.js +66 -86
  58. package/dist/services/traffic/traffic-service.js.map +1 -1
  59. package/dist/services/traffic/types.d.ts +3 -3
  60. package/dist/services/traffic/types.d.ts.map +1 -1
  61. package/dist/services/wcf-date.d.ts +6 -4
  62. package/dist/services/wcf-date.d.ts.map +1 -1
  63. package/dist/services/wcf-date.js +8 -4
  64. package/dist/services/wcf-date.js.map +1 -1
  65. package/package.json +2 -2
  66. package/server.json +3 -3
@@ -5,29 +5,65 @@
5
5
  import { tool, z } from '@cyanheads/mcp-ts-core';
6
6
  import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
7
7
  import { coordinatePair } from '../coordinate-pair.js';
8
+ import { continuationNotice, fitPageToBudget, MAX_FILTER_LENGTH, PAGE_BYTE_BUDGET, renderPage, } from '../page-budget.js';
8
9
  import { byIdThenContent } from '../../../services/traffic/stable-order.js';
9
10
  import { getTrafficApiService } from '../../../services/traffic/traffic-service.js';
10
11
  const DEFAULT_LIMIT = 50;
11
12
  const MAX_LIMIT = 500;
13
+ /** The region codes the camera feed carries in `Region`. */
14
+ const REGIONS = ['ER', 'NC', 'NW', 'OL', 'OS', 'SC', 'SW', 'WA'];
15
+ const CameraSchema = z
16
+ .object({
17
+ cameraId: z.number().optional().describe('Unique camera identifier.'),
18
+ title: z.string().optional().describe('Camera title or location description.'),
19
+ description: z.string().optional().describe('Additional description.'),
20
+ imageUrl: z
21
+ .string()
22
+ .optional()
23
+ .describe('URL of the WSDOT-hosted camera image (JPEG). WSDOT copyright applies.'),
24
+ imageWidth: z.number().optional().describe('Image width in pixels.'),
25
+ imageHeight: z.number().optional().describe('Image height in pixels.'),
26
+ roadName: z.string().optional().describe('Road the camera monitors.'),
27
+ direction: z
28
+ .string()
29
+ .optional()
30
+ .describe('Traffic-direction code monitored: N/S/E/W, B (both), NB/SB/EB/WB. Some sites use other location-specific markers.'),
31
+ milePost: z.number().optional().describe('Milepost location of the camera.'),
32
+ region: z.string().optional().describe('WSDOT region.'),
33
+ latitude: z.number().optional().describe('Camera latitude.'),
34
+ longitude: z.number().optional().describe('Camera longitude.'),
35
+ })
36
+ .describe('Camera metadata and image URL for one WSDOT highway camera.');
12
37
  export const searchCameras = tool('wsdot_search_cameras', {
13
38
  title: 'Search Highway Cameras',
14
39
  description: 'Returns WSDOT highway camera locations, descriptions, and image URLs. ' +
15
40
  'Camera images are copyright WSDOT — only metadata and image URLs are returned, not image bytes. ' +
16
- 'Filter by state route ("I-90", "90", "SR 520", or "520" all work), WSDOT region, or milepost range. ' +
17
- 'Results are ordered by cameraId and paged — pass offset/limit to page through the full set ' +
18
- '(the notice reports the next offset).',
41
+ 'Filter by state route ("I-90", "90", "SR 520", or "520" all work), WSDOT region, milepost range, ' +
42
+ 'or words in the camera title ("Snoqualmie"). ' +
43
+ 'Results are ordered by cameraId and paged — pass offset/limit to page through the full set. ' +
44
+ `A page ends at limit or at a ${PAGE_BYTE_BUDGET.toLocaleString('en-US')}-byte response budget, whichever comes first; the notice reports the next offset.`,
19
45
  annotations: { readOnlyHint: true },
20
46
  input: z.object({
21
47
  stateRoute: z
22
48
  .string()
49
+ .max(MAX_FILTER_LENGTH)
23
50
  .optional()
24
51
  .describe('State route to filter by. Accepts natural forms — "I-90", "90", "090", "SR 520", "520" — matched case- and space-insensitively to the route number. Camera road names carry a route-type prefix, which is compared when the filter carries one too: "SR 26" excludes US 26, while a bare "26" returns both. A lettered suffix is part of the route, so "US 97" excludes US 97A. Omit to include all routes.'),
25
52
  region: z
26
53
  .string()
54
+ .max(MAX_FILTER_LENGTH)
27
55
  .optional()
28
- .describe('WSDOT region code: NW (Northwest), SW (Southwest), OL (Olympic), ER (Eastern), SC (South Central), OS (Olympic South), NC (North Central), or WA (statewide). Matching is case-insensitive.'),
29
- startMilepost: z.number().optional().describe('Start of milepost range to filter cameras.'),
30
- endMilepost: z.number().optional().describe('End of milepost range to filter cameras.'),
56
+ .describe('WSDOT region code: NW (Northwest), SW (Southwest), OL (Olympic), ER (Eastern), SC (South Central), NC (North Central), OS (Oregon — the TripCheck cameras around Portland), or WA (airport cameras plus a few ferry-terminal cameras — most ferry-terminal cameras sit in NW and OL). Matching is case-insensitive; any other value is rejected. These are codes, not the region names wsdot_search_alerts takes.'),
57
+ startMilepost: z
58
+ .number()
59
+ .optional()
60
+ .describe('Start of the milepost range to filter cameras. Either bound may be given alone; when both are given, startMilepost must not exceed endMilepost. Cameras reporting no milepost are always included.'),
61
+ endMilepost: z.number().optional().describe('End of the milepost range to filter cameras.'),
62
+ titleContains: z
63
+ .string()
64
+ .max(MAX_FILTER_LENGTH)
65
+ .optional()
66
+ .describe('Words to find in the camera title, as WSDOT wrote it. Case-insensitive; every whitespace-separated word must appear, in any order — "Snoqualmie" returns "Snoqualmie Summit" and "East Snoqualmie Summit" but not a nearby camera titled "Hyak". Most titles lead with route and milepost ("I-90 at MP 52: …"), so filter a route with stateRoute rather than here. Combines with the other filters. Omit to include every title.'),
31
67
  offset: z
32
68
  .number()
33
69
  .int()
@@ -40,32 +76,11 @@ export const searchCameras = tool('wsdot_search_cameras', {
40
76
  .min(1)
41
77
  .max(MAX_LIMIT)
42
78
  .optional()
43
- .describe(`Maximum cameras to return in this page (1–${MAX_LIMIT}). Defaults to ${DEFAULT_LIMIT}.`),
79
+ .describe(`Maximum cameras to return in this page (1–${MAX_LIMIT}). Defaults to ${DEFAULT_LIMIT}. A large page ends sooner, at the ${PAGE_BYTE_BUDGET.toLocaleString('en-US')}-byte response budget.`),
44
80
  }),
45
81
  output: z.object({
46
82
  cameras: z
47
- .array(z
48
- .object({
49
- cameraId: z.number().optional().describe('Unique camera identifier.'),
50
- title: z.string().optional().describe('Camera title or location description.'),
51
- description: z.string().optional().describe('Additional description.'),
52
- imageUrl: z
53
- .string()
54
- .optional()
55
- .describe('URL of the WSDOT-hosted camera image (JPEG). WSDOT copyright applies.'),
56
- imageWidth: z.number().optional().describe('Image width in pixels.'),
57
- imageHeight: z.number().optional().describe('Image height in pixels.'),
58
- roadName: z.string().optional().describe('Road the camera monitors.'),
59
- direction: z
60
- .string()
61
- .optional()
62
- .describe('Traffic-direction code monitored: N/S/E/W, B (both), NB/SB/EB/WB. Some sites use other location-specific markers.'),
63
- milePost: z.number().optional().describe('Milepost location of the camera.'),
64
- region: z.string().optional().describe('WSDOT region.'),
65
- latitude: z.number().optional().describe('Camera latitude.'),
66
- longitude: z.number().optional().describe('Camera longitude.'),
67
- })
68
- .describe('Camera metadata and image URL for one WSDOT highway camera.'))
83
+ .array(CameraSchema)
69
84
  .describe('Camera metadata and image URLs. Images are copyright WSDOT.'),
70
85
  }),
71
86
  enrichment: {
@@ -83,6 +98,7 @@ export const searchCameras = tool('wsdot_search_cameras', {
83
98
  region: z.string().optional().describe('Region filter applied.'),
84
99
  startMilepost: z.number().optional().describe('Start milepost filter applied.'),
85
100
  endMilepost: z.number().optional().describe('End milepost filter applied.'),
101
+ titleContains: z.string().optional().describe('Title words filter applied.'),
86
102
  })
87
103
  .describe('Active filters applied to the camera search.'),
88
104
  notice: z
@@ -102,6 +118,8 @@ export const searchCameras = tool('wsdot_search_cameras', {
102
118
  parts.push(`- **Start MP:** ${filters.startMilepost}`);
103
119
  if (filters.endMilepost != null)
104
120
  parts.push(`- **End MP:** ${filters.endMilepost}`);
121
+ if (filters.titleContains)
122
+ parts.push(`- **Title contains:** ${filters.titleContains}`);
105
123
  return parts.length > 0
106
124
  ? `**Applied Filters:**\n${parts.join('\n')}`
107
125
  : '**Applied Filters:** none';
@@ -125,24 +143,54 @@ export const searchCameras = tool('wsdot_search_cameras', {
125
143
  recovery: 'Register an access code at https://wsdot.wa.gov/traffic/api/, set WSDOT_ACCESS_CODE on the server, and restart it.',
126
144
  thrownBy: 'service',
127
145
  },
146
+ {
147
+ reason: 'invalid_region',
148
+ code: JsonRpcErrorCode.ValidationError,
149
+ when: 'The region is not one of the region codes the camera feed carries.',
150
+ recovery: `Pass one of the region codes ${REGIONS.join(', ')} (case-insensitive), or omit region.`,
151
+ },
152
+ {
153
+ reason: 'invalid_milepost_range',
154
+ code: JsonRpcErrorCode.ValidationError,
155
+ when: 'startMilepost is greater than endMilepost.',
156
+ recovery: 'Pass startMilepost less than or equal to endMilepost, or give only one bound for an open-ended range.',
157
+ },
128
158
  ],
129
159
  async handler(input, ctx) {
130
160
  const stateRoute = input.stateRoute?.trim() || undefined;
131
161
  const region = input.region?.trim() || undefined;
162
+ const titleContains = input.titleContains?.trim() || undefined;
163
+ if (region && !REGIONS.includes(region.toUpperCase())) {
164
+ throw ctx.fail('invalid_region', `Unknown region "${region}" — wsdot_search_cameras takes a WSDOT region code.`, { ...ctx.recoveryFor('invalid_region') });
165
+ }
166
+ if (input.startMilepost != null &&
167
+ input.endMilepost != null &&
168
+ input.startMilepost > input.endMilepost) {
169
+ throw ctx.fail('invalid_milepost_range', `startMilepost ${input.startMilepost} is greater than endMilepost ${input.endMilepost}.`, { ...ctx.recoveryFor('invalid_milepost_range') });
170
+ }
132
171
  const fetched = await getTrafficApiService().searchCameras({
133
172
  ...(stateRoute && { stateRoute }),
134
173
  ...(region && { region }),
135
174
  ...(input.startMilepost != null && { startMilepost: input.startMilepost }),
136
175
  ...(input.endMilepost != null && { endMilepost: input.endMilepost }),
137
176
  }, ctx);
177
+ // Every word must appear somewhere in the title; a camera with no title cannot match.
178
+ const tokens = titleContains?.toLowerCase().split(/\s+/);
179
+ const matched = tokens
180
+ ? fetched.filter((c) => {
181
+ const title = c.title?.toLowerCase();
182
+ return title != null && tokens.every((t) => title.includes(t));
183
+ })
184
+ : fetched;
138
185
  // The camera feed serves one camera set in more than one row order, so a given offset is only
139
186
  // reproducible once the rows are ordered here. Cameras with no cameraId sort last.
140
- const allCameras = fetched.toSorted(byIdThenContent((c) => c.cameraId));
187
+ const allCameras = matched.toSorted(byIdThenContent((c) => c.cameraId));
141
188
  const appliedFilters = {
142
189
  ...(stateRoute && { stateRoute }),
143
190
  ...(region && { region }),
144
191
  ...(input.startMilepost != null && { startMilepost: input.startMilepost }),
145
192
  ...(input.endMilepost != null && { endMilepost: input.endMilepost }),
193
+ ...(titleContains && { titleContains }),
146
194
  };
147
195
  // Page the full filtered set so structuredContent and content[] carry the identical
148
196
  // page (the service stays filter-only; paging is a tool-handler concern). totalCount
@@ -150,7 +198,8 @@ export const searchCameras = tool('wsdot_search_cameras', {
150
198
  const totalCount = allCameras.length;
151
199
  const offset = input.offset ?? 0;
152
200
  const limit = input.limit ?? DEFAULT_LIMIT;
153
- const cameras = allCameras.slice(offset, offset + limit);
201
+ const requested = allCameras.slice(offset, offset + limit);
202
+ const cameras = fitPageToBudget(requested, renderCamera, appliedFilters);
154
203
  const hasMore = offset + cameras.length < totalCount;
155
204
  const nextOffset = hasMore ? offset + cameras.length : null;
156
205
  ctx.log.info('Cameras fetched', { totalCount, offset, limit, returned: cameras.length });
@@ -158,15 +207,17 @@ export const searchCameras = tool('wsdot_search_cameras', {
158
207
  if (totalCount === 0) {
159
208
  const hasFilters = Object.keys(appliedFilters).length > 0;
160
209
  ctx.enrich.notice(hasFilters
161
- ? 'No cameras matched the applied filters. Try removing the stateRoute, region, or milepost filters.'
210
+ ? 'No cameras matched the applied filters. Try removing the stateRoute, region, milepost, or titleContains filters.'
162
211
  : 'No camera data available statewide.');
163
212
  }
164
213
  else if (cameras.length === 0) {
165
214
  ctx.enrich.notice(`Offset ${offset} is past the end of ${totalCount} matching cameras. Use an offset between 0 and ${totalCount - 1}.`);
166
215
  }
167
216
  else {
168
- const window = `Showing cameras ${offset + 1}–${offset + cameras.length} of ${totalCount}. Camera images are copyright WSDOT.`;
169
- ctx.enrich.notice(hasMore ? `${window} Pass offset=${nextOffset} for the next page.` : window);
217
+ const shown = `Showing cameras ${offset + 1}–${offset + cameras.length} of ${totalCount}. Camera images are copyright WSDOT.`;
218
+ ctx.enrich.notice(nextOffset === null
219
+ ? shown
220
+ : `${shown} ${continuationNotice(nextOffset, cameras.length < requested.length)}`);
170
221
  }
171
222
  return { cameras };
172
223
  },
@@ -174,39 +225,39 @@ export const searchCameras = tool('wsdot_search_cameras', {
174
225
  if (result.cameras.length === 0) {
175
226
  return [{ type: 'text', text: 'No cameras found.' }];
176
227
  }
177
- const lines = [];
178
- for (const c of result.cameras) {
179
- lines.push(`### ${c.title ?? `Camera ${c.cameraId ?? ''}`}`);
180
- if (c.description)
181
- lines.push(c.description);
182
- // Direction and milepost stand on their own — gating the whole line on roadName drops
183
- // them from content[] for a camera that reports a position but no road name.
184
- const loc = [c.roadName, c.direction, c.milePost != null ? `MP ${c.milePost}` : undefined]
185
- .filter(Boolean)
186
- .join(' ');
187
- if (loc)
188
- lines.push(`**Location:** ${loc}`);
189
- if (c.region)
190
- lines.push(`**Region:** ${c.region}`);
191
- if (c.imageUrl)
192
- lines.push(`**Image:** ${c.imageUrl}`);
193
- if (c.imageWidth != null && c.imageHeight != null) {
194
- lines.push(`**Size:** ${c.imageWidth}×${c.imageHeight}px`);
195
- }
196
- else if (c.imageWidth != null) {
197
- lines.push(`**Size:** ${c.imageWidth}px wide (height not reported)`);
198
- }
199
- else if (c.imageHeight != null) {
200
- lines.push(`**Size:** ${c.imageHeight}px tall (width not reported)`);
201
- }
202
- const coords = coordinatePair(c.latitude, c.longitude);
203
- if (coords)
204
- lines.push(`**Coords:** ${coords}`);
205
- if (c.cameraId != null)
206
- lines.push(`**ID:** ${c.cameraId}`);
207
- lines.push('');
208
- }
209
- return [{ type: 'text', text: lines.join('\n') }];
228
+ return [{ type: 'text', text: renderPage(result.cameras, renderCamera) }];
210
229
  },
211
230
  });
231
+ /** One camera's `content[]` block — shared by `format()` and the page-budget charge. */
232
+ function renderCamera(c) {
233
+ const lines = [`### ${c.title ?? `Camera ${c.cameraId ?? ''}`}`];
234
+ if (c.description)
235
+ lines.push(c.description);
236
+ // Direction and milepost stand on their own — gating the whole line on roadName drops
237
+ // them from content[] for a camera that reports a position but no road name.
238
+ const loc = [c.roadName, c.direction, c.milePost != null ? `MP ${c.milePost}` : undefined]
239
+ .filter(Boolean)
240
+ .join(' ');
241
+ if (loc)
242
+ lines.push(`**Location:** ${loc}`);
243
+ if (c.region)
244
+ lines.push(`**Region:** ${c.region}`);
245
+ if (c.imageUrl)
246
+ lines.push(`**Image:** ${c.imageUrl}`);
247
+ if (c.imageWidth != null && c.imageHeight != null) {
248
+ lines.push(`**Size:** ${c.imageWidth}×${c.imageHeight}px`);
249
+ }
250
+ else if (c.imageWidth != null) {
251
+ lines.push(`**Size:** ${c.imageWidth}px wide (height not reported)`);
252
+ }
253
+ else if (c.imageHeight != null) {
254
+ lines.push(`**Size:** ${c.imageHeight}px tall (width not reported)`);
255
+ }
256
+ const coords = coordinatePair(c.latitude, c.longitude);
257
+ if (coords)
258
+ lines.push(`**Coords:** ${coords}`);
259
+ if (c.cameraId != null)
260
+ lines.push(`**ID:** ${c.cameraId}`);
261
+ return lines.join('\n');
262
+ }
212
263
  //# sourceMappingURL=search-cameras.tool.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"search-cameras.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-cameras.tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"search-cameras.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/search-cameras.tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * @fileoverview Per-surface byte budget for the paged traffic collection tools
3
+ * (`wsdot_search_alerts`, `wsdot_search_cameras`, `wsdot_get_travel_times`,
4
+ * `wsdot_get_toll_rates`). A page ends at `limit` or at the budget, whichever comes first, so
5
+ * one call stays within a bounded share of a model's context however large `limit` is or however
6
+ * long an upstream free-text field runs. Rows are rendered once here for both `format()` and the
7
+ * charge, so the bytes counted are the bytes sent.
8
+ * @module mcp-server/tools/page-budget
9
+ */
10
+ /**
11
+ * Ceiling on each surface of a page, in UTF-8 bytes: the serialized `structuredContent` and the
12
+ * joined `content[]` text, enrichment included on both.
13
+ */
14
+ export declare const PAGE_BYTE_BUDGET = 24000;
15
+ /**
16
+ * Bytes held back from the rows for what every page carries besides them: the output wrapper
17
+ * (`{"alerts":[…]}`), the enrichment counters and notice in `structuredContent`, and the
18
+ * `content[]` trailer that renders them with their labels. Caller-supplied filter values the
19
+ * enrichment echoes back are charged per call instead: capped at {@link MAX_FILTER_LENGTH}
20
+ * characters, one can still escape to about 1,200 JSON bytes (a control character serializes as a
21
+ * six-byte `\u` escape), and a camera search echoes two, which a fixed reserve would take from
22
+ * every page.
23
+ */
24
+ export declare const PAGE_OVERHEAD_RESERVE_BYTES = 1000;
25
+ /**
26
+ * Longest value, in characters, a traffic tool's free-text filter accepts (`stateRoute`, `route`,
27
+ * `titleContains`, `region`). Each filter is echoed back on both surfaces, so an unbounded one
28
+ * would let the caller's own input push a response past the budget. The longest live value a
29
+ * filter is matched against is a 73-character corridor name; camera titles run to 50.
30
+ */
31
+ export declare const MAX_FILTER_LENGTH = 200;
32
+ /**
33
+ * The `content[]` text of a page: each row's block, separated by a blank line, ending in a
34
+ * newline. `format()` renders through this so the text matches what {@link fitPageToBudget}
35
+ * charged.
36
+ */
37
+ export declare function renderPage<T>(rows: readonly T[], renderRow: (row: T) => string): string;
38
+ /**
39
+ * The leading rows of `window` (a page already sliced to `limit`) that fit the budget. Each row
40
+ * is charged at the larger of its JSON and its rendered block, plus a separator, so one running
41
+ * total bounds both surfaces. The page stops before the row that would cross the budget and
42
+ * always keeps the first row, so a row larger than the whole budget comes back alone rather than
43
+ * blocking the walk.
44
+ *
45
+ * @param window - Rows from `offset` up to `limit`, in page order.
46
+ * @param renderRow - The per-row renderer `format()` uses.
47
+ * @param echoed - Caller-supplied values the page's enrichment repeats (e.g. `appliedFilters`).
48
+ * @returns The rows to return; shorter than `window` exactly when the budget ended the page.
49
+ */
50
+ export declare function fitPageToBudget<T>(window: readonly T[], renderRow: (row: T) => string, echoed?: unknown): T[];
51
+ /**
52
+ * The continuation sentence of a page that has more rows after it. A page the budget ended says
53
+ * so, so a caller reads a short page as a size cut rather than the end of the set.
54
+ */
55
+ export declare function continuationNotice(nextOffset: number, budgetEnded: boolean): string;
56
+ //# sourceMappingURL=page-budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-budget.d.ts","sourceRoot":"","sources":["../../../src/mcp-server/tools/page-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAS,CAAC;AAEvC;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,OAAQ,CAAC;AAEjD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAOrC;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,GAAG,MAAM,CAEvF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAC/B,MAAM,EAAE,SAAS,CAAC,EAAE,EACpB,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,EAC7B,MAAM,CAAC,EAAE,OAAO,GACf,CAAC,EAAE,CAWL;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,MAAM,CAInF"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * @fileoverview Per-surface byte budget for the paged traffic collection tools
3
+ * (`wsdot_search_alerts`, `wsdot_search_cameras`, `wsdot_get_travel_times`,
4
+ * `wsdot_get_toll_rates`). A page ends at `limit` or at the budget, whichever comes first, so
5
+ * one call stays within a bounded share of a model's context however large `limit` is or however
6
+ * long an upstream free-text field runs. Rows are rendered once here for both `format()` and the
7
+ * charge, so the bytes counted are the bytes sent.
8
+ * @module mcp-server/tools/page-budget
9
+ */
10
+ /**
11
+ * Ceiling on each surface of a page, in UTF-8 bytes: the serialized `structuredContent` and the
12
+ * joined `content[]` text, enrichment included on both.
13
+ */
14
+ export const PAGE_BYTE_BUDGET = 24_000;
15
+ /**
16
+ * Bytes held back from the rows for what every page carries besides them: the output wrapper
17
+ * (`{"alerts":[…]}`), the enrichment counters and notice in `structuredContent`, and the
18
+ * `content[]` trailer that renders them with their labels. Caller-supplied filter values the
19
+ * enrichment echoes back are charged per call instead: capped at {@link MAX_FILTER_LENGTH}
20
+ * characters, one can still escape to about 1,200 JSON bytes (a control character serializes as a
21
+ * six-byte `\u` escape), and a camera search echoes two, which a fixed reserve would take from
22
+ * every page.
23
+ */
24
+ export const PAGE_OVERHEAD_RESERVE_BYTES = 1_000;
25
+ /**
26
+ * Longest value, in characters, a traffic tool's free-text filter accepts (`stateRoute`, `route`,
27
+ * `titleContains`, `region`). Each filter is echoed back on both surfaces, so an unbounded one
28
+ * would let the caller's own input push a response past the budget. The longest live value a
29
+ * filter is matched against is a 73-character corridor name; camera titles run to 50.
30
+ */
31
+ export const MAX_FILTER_LENGTH = 200;
32
+ /** Separates two rendered rows in `content[]`: one blank line. */
33
+ const ROW_SEPARATOR = '\n\n';
34
+ const utf8Bytes = (text) => Buffer.byteLength(text);
35
+ /**
36
+ * The `content[]` text of a page: each row's block, separated by a blank line, ending in a
37
+ * newline. `format()` renders through this so the text matches what {@link fitPageToBudget}
38
+ * charged.
39
+ */
40
+ export function renderPage(rows, renderRow) {
41
+ return `${rows.map(renderRow).join(ROW_SEPARATOR)}\n`;
42
+ }
43
+ /**
44
+ * The leading rows of `window` (a page already sliced to `limit`) that fit the budget. Each row
45
+ * is charged at the larger of its JSON and its rendered block, plus a separator, so one running
46
+ * total bounds both surfaces. The page stops before the row that would cross the budget and
47
+ * always keeps the first row, so a row larger than the whole budget comes back alone rather than
48
+ * blocking the walk.
49
+ *
50
+ * @param window - Rows from `offset` up to `limit`, in page order.
51
+ * @param renderRow - The per-row renderer `format()` uses.
52
+ * @param echoed - Caller-supplied values the page's enrichment repeats (e.g. `appliedFilters`).
53
+ * @returns The rows to return; shorter than `window` exactly when the budget ended the page.
54
+ */
55
+ export function fitPageToBudget(window, renderRow, echoed) {
56
+ let remaining = PAGE_BYTE_BUDGET -
57
+ PAGE_OVERHEAD_RESERVE_BYTES -
58
+ (echoed === undefined ? 0 : utf8Bytes(JSON.stringify(echoed)));
59
+ for (const [index, row] of window.entries()) {
60
+ remaining -=
61
+ Math.max(utf8Bytes(JSON.stringify(row)), utf8Bytes(renderRow(row))) + ROW_SEPARATOR.length;
62
+ if (remaining < 0)
63
+ return window.slice(0, Math.max(index, 1));
64
+ }
65
+ return [...window];
66
+ }
67
+ /**
68
+ * The continuation sentence of a page that has more rows after it. A page the budget ended says
69
+ * so, so a caller reads a short page as a size cut rather than the end of the set.
70
+ */
71
+ export function continuationNotice(nextOffset, budgetEnded) {
72
+ return budgetEnded
73
+ ? `The ${PAGE_BYTE_BUDGET.toLocaleString('en-US')}-byte response budget ended this page before limit — pass offset=${nextOffset} for the next page.`
74
+ : `Pass offset=${nextOffset} for the next page.`;
75
+ }
76
+ //# sourceMappingURL=page-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-budget.js","sourceRoot":"","sources":["../../../src/mcp-server/tools/page-budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEvC;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,CAAC;AAErC,kEAAkE;AAClE,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAE5D;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAI,IAAkB,EAAE,SAA6B;IAC7E,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;AACxD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAoB,EACpB,SAA6B,EAC7B,MAAgB;IAEhB,IAAI,SAAS,GACX,gBAAgB;QAChB,2BAA2B;QAC3B,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACjE,KAAK,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC;QAC5C,SAAS;YACP,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC;QAC7F,IAAI,SAAS,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,UAAkB,EAAE,WAAoB;IACzE,OAAO,WAAW;QAChB,CAAC,CAAC,OAAO,gBAAgB,CAAC,cAAc,CAAC,OAAO,CAAC,oEAAoE,UAAU,qBAAqB;QACpJ,CAAC,CAAC,eAAe,UAAU,qBAAqB,CAAC;AACrD,CAAC"}
@@ -8,6 +8,13 @@ import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
8
8
  import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
9
9
  import type { FerryAlert, FerryRoute, FerrySchedule, FerryTerminal, TerminalSailingSpace, VesselLocation } from './types.js';
10
10
  export declare class FerryApiService {
11
+ /**
12
+ * Terminal pairs keyed by `{tripDate}/{routeId}`. WSF lists the lookup as cacheable until its
13
+ * `cacheflushdate` stamp changes, so the entries hold only while {@link pairCacheStamp} matches it;
14
+ * a new stamp empties the map. Public upstream data, so it is shared across tenants.
15
+ */
16
+ private readonly pairCache;
17
+ private pairCacheStamp;
11
18
  constructor(_config: AppConfig, _storage: StorageService);
12
19
  private accessCode;
13
20
  private buildUrl;
@@ -26,7 +33,20 @@ export declare class FerryApiService {
26
33
  */
27
34
  static todayFerryDate(): string;
28
35
  getTerminals(ctx: Context): Promise<FerryTerminal[]>;
36
+ private fetchRoutes;
37
+ /**
38
+ * Whether WSF lists any route for the trip date. A date inside WSF's window whose season has no
39
+ * sailings loaded yet lists none — and WSF then rejects every terminal pair on it exactly as it
40
+ * rejects a pair that never has service, so this is what tells the two apart.
41
+ */
42
+ hasRoutes(tripDate: string, ctx: Context): Promise<boolean>;
29
43
  getRoutes(tripDate: string, ctx: Context): Promise<FerryRoute[]>;
44
+ /**
45
+ * The pairs each route serves on the trip date, from the cache when WSF's flush stamp still
46
+ * matches and otherwise one `terminalsandmatesbyroute` request per route. Any failed request fails
47
+ * the call — a route list with some routes' pairs missing would read as those routes serving none.
48
+ */
49
+ private terminalPairsByRoute;
30
50
  getSchedule(departingTerminalId: number, arrivingTerminalId: number, tripDate: string, remainingOnly: boolean, ctx: Context): Promise<FerrySchedule>;
31
51
  getVesselLocations(ctx: Context): Promise<VesselLocation[]>;
32
52
  getTerminalSailingSpace(ctx: Context): Promise<TerminalSailingSpace[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"ferry-service.d.ts","sourceRoot":"","sources":["../../../src/services/ferry/ferry-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAMrE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EAOb,oBAAoB,EACpB,cAAc,EACf,MAAM,YAAY,CAAC;AAMpB,qBAAa,eAAe;IAC1B,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAI;IAE5D,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAgCjB;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAc1C;IAED;;;;OAIG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM,CAE9B;IAEK,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAUzD;IAEK,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAQrE;IAEK,WAAW,CACf,mBAAmB,EAAE,MAAM,EAC3B,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,OAAO,EACtB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,aAAa,CAAC,CAqCxB;IAEK,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAsBhE;IAEK,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAmD3E;IAEK,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CA0BnD;CACF;AAMD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAEpF;AAED,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD"}
1
+ {"version":3,"file":"ferry-service.d.ts","sourceRoot":"","sources":["../../../src/services/ferry/ferry-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAMrE,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EASb,oBAAoB,EACpB,cAAc,EACf,MAAM,YAAY,CAAC;AAsEpB,qBAAa,eAAe;IAC1B;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,cAAc,CAAqB;IAE3C,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAI;IAE5D,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,SAAS;IAoCjB;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAc1C;IAED;;;;OAIG;IACH,MAAM,CAAC,cAAc,IAAI,MAAM,CAE9B;IAEK,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAYzD;YAEa,WAAW;IAMzB;;;;OAIG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAGhE;IAEK,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAWrE;IAED;;;;OAIG;YACW,oBAAoB;IAmD5B,WAAW,CACf,mBAAmB,EAAE,MAAM,EAC3B,kBAAkB,EAAE,MAAM,EAC1B,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,OAAO,EACtB,GAAG,EAAE,OAAO,GACX,OAAO,CAAC,aAAa,CAAC,CAqDxB;IAEK,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAsBhE;IAEK,uBAAuB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAmD3E;IAEK,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAuBnD;CACF;AAMD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAEpF;AAED,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD"}