@mapbox/mcp-server 0.2.1-dev.3 → 0.2.2

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 (74) hide show
  1. package/README.md +85 -4
  2. package/dist/index.js +2 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/tools/directions-tool/DirectionsTool.d.ts +7 -32
  5. package/dist/tools/directions-tool/DirectionsTool.d.ts.map +1 -1
  6. package/dist/tools/directions-tool/DirectionsTool.js +41 -66
  7. package/dist/tools/directions-tool/DirectionsTool.js.map +1 -1
  8. package/dist/tools/directions-tool/DirectionsTool.test.js +208 -257
  9. package/dist/tools/directions-tool/DirectionsTool.test.js.map +1 -1
  10. package/dist/tools/directions-tool/cleanResponseData.d.ts +11 -0
  11. package/dist/tools/directions-tool/cleanResponseData.d.ts.map +1 -0
  12. package/dist/tools/directions-tool/cleanResponseData.js +175 -0
  13. package/dist/tools/directions-tool/cleanResponseData.js.map +1 -0
  14. package/dist/tools/directions-tool/cleanResponseData.test.d.ts +2 -0
  15. package/dist/tools/directions-tool/cleanResponseData.test.d.ts.map +1 -0
  16. package/dist/tools/directions-tool/cleanResponseData.test.js +295 -0
  17. package/dist/tools/directions-tool/cleanResponseData.test.js.map +1 -0
  18. package/dist/tools/directions-tool/formatIsoDateTime.d.ts +8 -0
  19. package/dist/tools/directions-tool/formatIsoDateTime.d.ts.map +1 -0
  20. package/dist/tools/directions-tool/formatIsoDateTime.js +17 -0
  21. package/dist/tools/directions-tool/formatIsoDateTime.js.map +1 -0
  22. package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts +2 -0
  23. package/dist/tools/directions-tool/formatIsoDateTime.test.d.ts.map +1 -0
  24. package/dist/tools/directions-tool/formatIsoDateTime.test.js +26 -0
  25. package/dist/tools/directions-tool/formatIsoDateTime.test.js.map +1 -0
  26. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts +3 -3
  27. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.d.ts.map +1 -1
  28. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js +11 -6
  29. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.js.map +1 -1
  30. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js +57 -1
  31. package/dist/tools/forward-geocode-tool/ForwardGeocodeTool.test.js.map +1 -1
  32. package/dist/tools/poi-search-tool/PoiSearchTool.d.ts +3 -0
  33. package/dist/tools/poi-search-tool/PoiSearchTool.d.ts.map +1 -1
  34. package/dist/tools/poi-search-tool/PoiSearchTool.js +13 -3
  35. package/dist/tools/poi-search-tool/PoiSearchTool.js.map +1 -1
  36. package/dist/tools/poi-search-tool/PoiSearchTool.test.js +56 -0
  37. package/dist/tools/poi-search-tool/PoiSearchTool.test.js.map +1 -1
  38. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts +3 -0
  39. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.d.ts.map +1 -1
  40. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js +13 -3
  41. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.js.map +1 -1
  42. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js +58 -0
  43. package/dist/tools/reverse-geocode-tool/ReverseGeocodeTool.test.js.map +1 -1
  44. package/dist/tools/schema-validation.test.d.ts +2 -0
  45. package/dist/tools/schema-validation.test.d.ts.map +1 -0
  46. package/dist/tools/schema-validation.test.js +81 -0
  47. package/dist/tools/schema-validation.test.js.map +1 -0
  48. package/dist/tools/version-tool/VersionTool.d.ts +18 -0
  49. package/dist/tools/version-tool/VersionTool.d.ts.map +1 -0
  50. package/dist/tools/version-tool/VersionTool.js +50 -0
  51. package/dist/tools/version-tool/VersionTool.js.map +1 -0
  52. package/dist/tools/version-tool/VersionTool.test.d.ts +2 -0
  53. package/dist/tools/version-tool/VersionTool.test.d.ts.map +1 -0
  54. package/dist/tools/version-tool/VersionTool.test.js +49 -0
  55. package/dist/tools/version-tool/VersionTool.test.js.map +1 -0
  56. package/dist/utils/requestUtils.d.ts.map +1 -1
  57. package/dist/utils/requestUtils.js +33 -2
  58. package/dist/utils/requestUtils.js.map +1 -1
  59. package/dist/utils/requestUtils.test-helpers.d.ts.map +1 -1
  60. package/dist/utils/requestUtils.test-helpers.js +5 -1
  61. package/dist/utils/requestUtils.test-helpers.js.map +1 -1
  62. package/dist/utils/requestUtils.test.d.ts +2 -0
  63. package/dist/utils/requestUtils.test.d.ts.map +1 -0
  64. package/dist/utils/requestUtils.test.js +115 -0
  65. package/dist/utils/requestUtils.test.js.map +1 -0
  66. package/dist/utils/schemaUtils.d.ts +9 -0
  67. package/dist/utils/schemaUtils.d.ts.map +1 -0
  68. package/dist/utils/schemaUtils.js +25 -0
  69. package/dist/utils/schemaUtils.js.map +1 -0
  70. package/dist/utils/versionUtils.d.ts.map +1 -1
  71. package/dist/utils/versionUtils.js +21 -5
  72. package/dist/utils/versionUtils.js.map +1 -1
  73. package/dist/version.json +4 -4
  74. package/package.json +2 -2
@@ -1,9 +1,18 @@
1
- process.env.MAPBOX_ACCESS_TOKEN =
2
- 'eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0In0.signature';
1
+ process.env.MAPBOX_ACCESS_TOKEN = 'test.token.signature';
3
2
  import { cleanup } from '../../utils/requestUtils.js';
4
3
  import { setupFetch, assertHeadersSent } from '../../utils/requestUtils.test-helpers.js';
5
4
  import { DirectionsTool } from './DirectionsTool.js';
5
+ import * as cleanResponseModule from './cleanResponseData.js';
6
6
  describe('DirectionsTool', () => {
7
+ beforeEach(() => {
8
+ // Mock the cleanResponseData function to return data unchanged, this make testing much easier
9
+ // There should be separate test suits for `cleanResponseData`
10
+ jest
11
+ .spyOn(cleanResponseModule, 'cleanResponseData')
12
+ .mockImplementation((_, data) => data);
13
+ // Enable verbose errors for testing
14
+ process.env.VERBOSE_ERRORS = 'true';
15
+ });
7
16
  afterEach(() => {
8
17
  jest.restoreAllMocks();
9
18
  cleanup();
@@ -12,8 +21,8 @@ describe('DirectionsTool', () => {
12
21
  const mockFetch = setupFetch();
13
22
  await new DirectionsTool().run({
14
23
  coordinates: [
15
- { longitude: -74.102094, latitude: 40.692815 },
16
- { longitude: -74.1022094, latitude: 40.792815 }
24
+ [-74.102094, 40.692815],
25
+ [-74.1022094, 40.792815]
17
26
  ]
18
27
  });
19
28
  assertHeadersSent(mockFetch);
@@ -22,8 +31,8 @@ describe('DirectionsTool', () => {
22
31
  const mockFetch = setupFetch();
23
32
  await new DirectionsTool().run({
24
33
  coordinates: [
25
- { longitude: -73.989, latitude: 40.733 },
26
- { longitude: -73.979, latitude: 40.743 }
34
+ [-73.989, 40.733],
35
+ [-73.979, 40.743]
27
36
  ]
28
37
  });
29
38
  const calledUrl = mockFetch.mock.calls[0][0];
@@ -36,14 +45,13 @@ describe('DirectionsTool', () => {
36
45
  const mockFetch = setupFetch();
37
46
  await new DirectionsTool().run({
38
47
  coordinates: [
39
- { longitude: -122.42, latitude: 37.78 },
40
- { longitude: -122.4, latitude: 37.79 },
41
- { longitude: -122.39, latitude: 37.77 }
48
+ [-122.42, 37.78],
49
+ [-122.4, 37.79],
50
+ [-122.39, 37.77]
42
51
  ],
43
52
  routing_profile: 'walking',
44
53
  geometries: 'geojson',
45
54
  alternatives: true,
46
- annotations: ['distance', 'duration', 'speed'],
47
55
  exclude: 'ferry'
48
56
  });
49
57
  const calledUrl = mockFetch.mock.calls[0][0];
@@ -51,7 +59,7 @@ describe('DirectionsTool', () => {
51
59
  expect(calledUrl).toContain('-122.42%2C37.78%3B-122.4%2C37.79%3B-122.39%2C37.77');
52
60
  expect(calledUrl).toContain('geometries=geojson');
53
61
  expect(calledUrl).toContain('alternatives=true');
54
- expect(calledUrl).toContain('annotations=distance%2Cduration%2Cspeed');
62
+ expect(calledUrl).toContain('annotations=distance%2Cspeed');
55
63
  expect(calledUrl).toContain('overview=full');
56
64
  expect(calledUrl).toContain('exclude=ferry');
57
65
  assertHeadersSent(mockFetch);
@@ -60,15 +68,32 @@ describe('DirectionsTool', () => {
60
68
  const mockFetch = setupFetch();
61
69
  await new DirectionsTool().run({
62
70
  coordinates: [
63
- { longitude: -118.24, latitude: 34.05 },
64
- { longitude: -118.3, latitude: 34.02 }
71
+ [-118.24, 34.05],
72
+ [-118.3, 34.02]
65
73
  ]
66
74
  });
67
75
  const calledUrl = mockFetch.mock.calls[0][0];
68
76
  expect(calledUrl).toContain('directions/v5/mapbox/driving-traffic');
69
- expect(calledUrl).toContain('geometries=polyline');
77
+ expect(calledUrl).not.toContain('geometries=');
78
+ expect(calledUrl).toContain('alternatives=false');
79
+ expect(calledUrl).toContain('annotations=distance%2Ccongestion%2Cspeed');
80
+ expect(calledUrl).not.toContain('exclude=');
81
+ assertHeadersSent(mockFetch);
82
+ });
83
+ it('handles geometries=none', async () => {
84
+ const mockFetch = setupFetch();
85
+ await new DirectionsTool().run({
86
+ coordinates: [
87
+ [-118.24, 34.05],
88
+ [-118.3, 34.02]
89
+ ],
90
+ geometries: 'none'
91
+ });
92
+ const calledUrl = mockFetch.mock.calls[0][0];
93
+ expect(calledUrl).toContain('directions/v5/mapbox/driving-traffic');
94
+ expect(calledUrl).not.toContain('geometries=');
70
95
  expect(calledUrl).toContain('alternatives=false');
71
- expect(calledUrl).not.toContain('annotations=');
96
+ expect(calledUrl).toContain('annotations=distance%2Ccongestion%2Cspeed');
72
97
  expect(calledUrl).not.toContain('exclude=');
73
98
  assertHeadersSent(mockFetch);
74
99
  });
@@ -76,8 +101,8 @@ describe('DirectionsTool', () => {
76
101
  const mockFetch = setupFetch();
77
102
  await new DirectionsTool().run({
78
103
  coordinates: [
79
- { longitude: -74.0, latitude: 40.7 },
80
- { longitude: -73.9, latitude: 40.8 }
104
+ [-74.0, 40.7],
105
+ [-73.9, 40.8]
81
106
  ],
82
107
  exclude: 'toll,point(-73.95 40.75)'
83
108
  });
@@ -97,14 +122,14 @@ describe('DirectionsTool', () => {
97
122
  });
98
123
  const result = await new DirectionsTool().run({
99
124
  coordinates: [
100
- { longitude: -73.989, latitude: 40.733 },
101
- { longitude: -73.979, latitude: 40.743 }
125
+ [-73.989, 40.733],
126
+ [-73.979, 40.743]
102
127
  ]
103
128
  });
104
129
  expect(result.is_error).toBe(true);
105
130
  expect(result.content[0]).toMatchObject({
106
131
  type: 'text',
107
- text: 'Internal error has occurred.'
132
+ text: 'Request failed with status 404: Not Found'
108
133
  });
109
134
  assertHeadersSent(mockFetch);
110
135
  });
@@ -112,7 +137,7 @@ describe('DirectionsTool', () => {
112
137
  const tool = new DirectionsTool();
113
138
  // Test with only one coordinate (invalid)
114
139
  await expect(tool.run({
115
- coordinates: [{ longitude: -73.989, latitude: 40.733 }]
140
+ coordinates: [[-73.989, 40.733]]
116
141
  })).resolves.toMatchObject({
117
142
  is_error: true
118
143
  });
@@ -126,10 +151,7 @@ describe('DirectionsTool', () => {
126
151
  it('validates coordinates constraints - maximum allowed', async () => {
127
152
  const tool = new DirectionsTool();
128
153
  // Create an array of 26 coordinates (one more than allowed)
129
- const tooManyCoords = Array(26).fill({
130
- longitude: -73.989,
131
- latitude: 40.733
132
- });
154
+ const tooManyCoords = Array(26).fill([-73.989, 40.733]);
133
155
  await expect(tool.run({
134
156
  coordinates: tooManyCoords
135
157
  })).resolves.toMatchObject({
@@ -140,8 +162,8 @@ describe('DirectionsTool', () => {
140
162
  const mockFetch = setupFetch();
141
163
  await new DirectionsTool().run({
142
164
  coordinates: [
143
- { longitude: -73.989, latitude: 40.733 },
144
- { longitude: -73.979, latitude: 40.743 }
165
+ [-73.989, 40.733],
166
+ [-73.979, 40.743]
145
167
  ]
146
168
  });
147
169
  const calledUrl = mockFetch.mock.calls[0][0];
@@ -153,174 +175,20 @@ describe('DirectionsTool', () => {
153
175
  // Create an array of exactly 25 coordinates (maximum allowed)
154
176
  const maxCoords = Array(25)
155
177
  .fill(0)
156
- .map((_, i) => ({ longitude: -74 + i * 0.01, latitude: 40 + i * 0.01 }));
178
+ .map((_, i) => [-74 + i * 0.01, 40 + i * 0.01]);
157
179
  await new DirectionsTool().run({
158
180
  coordinates: maxCoords
159
181
  });
160
182
  const calledUrl = mockFetch.mock.calls[0][0];
161
183
  // Check that all coordinates are properly encoded
162
184
  for (let i = 0; i < maxCoords.length; i++) {
163
- const { longitude: lng, latitude: lat } = maxCoords[i];
185
+ const [lng, lat] = maxCoords[i];
164
186
  const semicolon = i < 24 ? '%3B' : '';
165
187
  const expectedCoord = `${lng}%2C${lat}` + semicolon;
166
188
  expect(calledUrl).toContain(expectedCoord);
167
189
  }
168
190
  assertHeadersSent(mockFetch);
169
191
  });
170
- describe('walking parameters validations', () => {
171
- it('accepts walking_speed with walking profile', async () => {
172
- const mockFetch = setupFetch();
173
- await new DirectionsTool().run({
174
- coordinates: [
175
- { longitude: -73.989, latitude: 40.733 },
176
- { longitude: -73.979, latitude: 40.743 }
177
- ],
178
- routing_profile: 'walking',
179
- walking_speed: 2.5
180
- });
181
- const calledUrl = mockFetch.mock.calls[0][0];
182
- expect(calledUrl).toContain('walking_speed=2.5');
183
- assertHeadersSent(mockFetch);
184
- });
185
- it('accepts walkway_bias with walking profile', async () => {
186
- const mockFetch = setupFetch();
187
- await new DirectionsTool().run({
188
- coordinates: [
189
- { longitude: -73.989, latitude: 40.733 },
190
- { longitude: -73.979, latitude: 40.743 }
191
- ],
192
- routing_profile: 'walking',
193
- walkway_bias: 0.8
194
- });
195
- const calledUrl = mockFetch.mock.calls[0][0];
196
- expect(calledUrl).toContain('walkway_bias=0.8');
197
- assertHeadersSent(mockFetch);
198
- });
199
- it('rejects walking_speed with non-walking profiles', async () => {
200
- const tool = new DirectionsTool();
201
- // Test with driving profile
202
- await expect(tool.run({
203
- coordinates: [
204
- { longitude: -73.989, latitude: 40.733 },
205
- { longitude: -73.979, latitude: 40.743 }
206
- ],
207
- routing_profile: 'driving',
208
- walking_speed: 2.0
209
- })).resolves.toMatchObject({
210
- is_error: true
211
- });
212
- // Test with cycling profile
213
- await expect(tool.run({
214
- coordinates: [
215
- { longitude: -73.989, latitude: 40.733 },
216
- { longitude: -73.979, latitude: 40.743 }
217
- ],
218
- routing_profile: 'cycling',
219
- walking_speed: 2.0
220
- })).resolves.toMatchObject({
221
- is_error: true
222
- });
223
- });
224
- it('rejects walkway_bias with non-walking profiles', async () => {
225
- const tool = new DirectionsTool();
226
- // Test with driving-traffic profile
227
- await expect(tool.run({
228
- coordinates: [
229
- { longitude: -73.989, latitude: 40.733 },
230
- { longitude: -73.979, latitude: 40.743 }
231
- ],
232
- routing_profile: 'driving-traffic',
233
- walkway_bias: 0.5
234
- })).resolves.toMatchObject({
235
- is_error: true
236
- });
237
- // Test with cycling profile
238
- await expect(tool.run({
239
- coordinates: [
240
- { longitude: -73.989, latitude: 40.733 },
241
- { longitude: -73.979, latitude: 40.743 }
242
- ],
243
- routing_profile: 'cycling',
244
- walkway_bias: -0.8
245
- })).resolves.toMatchObject({
246
- is_error: true
247
- });
248
- });
249
- it('validates walking_speed value ranges', async () => {
250
- const tool = new DirectionsTool();
251
- // Test with value below minimum (0.14 m/s)
252
- await expect(tool.run({
253
- coordinates: [
254
- { longitude: -73.989, latitude: 40.733 },
255
- { longitude: -73.979, latitude: 40.743 }
256
- ],
257
- routing_profile: 'walking',
258
- walking_speed: 0.1
259
- })).resolves.toMatchObject({
260
- is_error: true
261
- });
262
- // Test with value above maximum (6.94 m/s)
263
- await expect(tool.run({
264
- coordinates: [
265
- { longitude: -73.989, latitude: 40.733 },
266
- { longitude: -73.979, latitude: 40.743 }
267
- ],
268
- routing_profile: 'walking',
269
- walking_speed: 7.5
270
- })).resolves.toMatchObject({
271
- is_error: true
272
- });
273
- // Test with valid value
274
- const mockFetch = setupFetch();
275
- await tool.run({
276
- coordinates: [
277
- { longitude: -73.989, latitude: 40.733 },
278
- { longitude: -73.979, latitude: 40.743 }
279
- ],
280
- routing_profile: 'walking',
281
- walking_speed: 3.0
282
- });
283
- const calledUrl = mockFetch.mock.calls[0][0];
284
- expect(calledUrl).toContain('walking_speed=3');
285
- });
286
- it('validates walkway_bias value ranges', async () => {
287
- const tool = new DirectionsTool();
288
- // Test with value below minimum (-1)
289
- await expect(tool.run({
290
- coordinates: [
291
- { longitude: -73.989, latitude: 40.733 },
292
- { longitude: -73.979, latitude: 40.743 }
293
- ],
294
- routing_profile: 'walking',
295
- walkway_bias: -1.5
296
- })).resolves.toMatchObject({
297
- is_error: true
298
- });
299
- // Test with value above maximum (1)
300
- await expect(tool.run({
301
- coordinates: [
302
- { longitude: -73.989, latitude: 40.733 },
303
- { longitude: -73.979, latitude: 40.743 }
304
- ],
305
- routing_profile: 'walking',
306
- walkway_bias: 1.2
307
- })).resolves.toMatchObject({
308
- is_error: true
309
- });
310
- // Test with valid values
311
- const mockFetch = setupFetch();
312
- await tool.run({
313
- coordinates: [
314
- { longitude: -73.989, latitude: 40.733 },
315
- { longitude: -73.979, latitude: 40.743 }
316
- ],
317
- routing_profile: 'walking',
318
- walkway_bias: -0.5
319
- });
320
- const calledUrl = mockFetch.mock.calls[0][0];
321
- expect(calledUrl).toContain('walkway_bias=-0.5');
322
- });
323
- });
324
192
  describe('exclude parameter and routing profile validations', () => {
325
193
  it('accepts driving-specific exclusions with driving profiles', async () => {
326
194
  const mockFetch = setupFetch();
@@ -328,8 +196,8 @@ describe('DirectionsTool', () => {
328
196
  // Test with driving profile
329
197
  await expect(tool.run({
330
198
  coordinates: [
331
- { longitude: -73.989, latitude: 40.733 },
332
- { longitude: -73.979, latitude: 40.743 }
199
+ [-73.989, 40.733],
200
+ [-73.979, 40.743]
333
201
  ],
334
202
  routing_profile: 'driving',
335
203
  exclude: 'toll,motorway,unpaved'
@@ -339,8 +207,8 @@ describe('DirectionsTool', () => {
339
207
  // Test with driving-traffic profile
340
208
  await expect(tool.run({
341
209
  coordinates: [
342
- { longitude: -73.989, latitude: 40.733 },
343
- { longitude: -73.979, latitude: 40.743 }
210
+ [-73.989, 40.733],
211
+ [-73.979, 40.743]
344
212
  ],
345
213
  routing_profile: 'driving-traffic',
346
214
  exclude: 'tunnel,country_border,state_border'
@@ -353,8 +221,8 @@ describe('DirectionsTool', () => {
353
221
  // Test with walking profile
354
222
  await expect(tool.run({
355
223
  coordinates: [
356
- { longitude: -73.989, latitude: 40.733 },
357
- { longitude: -73.979, latitude: 40.743 }
224
+ [-73.989, 40.733],
225
+ [-73.979, 40.743]
358
226
  ],
359
227
  routing_profile: 'walking',
360
228
  exclude: 'toll'
@@ -364,8 +232,8 @@ describe('DirectionsTool', () => {
364
232
  // Test with cycling profile
365
233
  await expect(tool.run({
366
234
  coordinates: [
367
- { longitude: -73.989, latitude: 40.733 },
368
- { longitude: -73.979, latitude: 40.743 }
235
+ [-73.989, 40.733],
236
+ [-73.979, 40.743]
369
237
  ],
370
238
  routing_profile: 'cycling',
371
239
  exclude: 'motorway'
@@ -379,8 +247,8 @@ describe('DirectionsTool', () => {
379
247
  // Test with driving profile
380
248
  await expect(tool.run({
381
249
  coordinates: [
382
- { longitude: -73.989, latitude: 40.733 },
383
- { longitude: -73.979, latitude: 40.743 }
250
+ [-73.989, 40.733],
251
+ [-73.979, 40.743]
384
252
  ],
385
253
  routing_profile: 'driving',
386
254
  exclude: 'ferry'
@@ -390,8 +258,8 @@ describe('DirectionsTool', () => {
390
258
  // Test with walking profile
391
259
  await expect(tool.run({
392
260
  coordinates: [
393
- { longitude: -73.989, latitude: 40.733 },
394
- { longitude: -73.979, latitude: 40.743 }
261
+ [-73.989, 40.733],
262
+ [-73.979, 40.743]
395
263
  ],
396
264
  routing_profile: 'walking',
397
265
  exclude: 'ferry'
@@ -401,8 +269,8 @@ describe('DirectionsTool', () => {
401
269
  // Test with cycling profile
402
270
  await expect(tool.run({
403
271
  coordinates: [
404
- { longitude: -73.989, latitude: 40.733 },
405
- { longitude: -73.979, latitude: 40.743 }
272
+ [-73.989, 40.733],
273
+ [-73.979, 40.743]
406
274
  ],
407
275
  routing_profile: 'cycling',
408
276
  exclude: 'cash_only_tolls'
@@ -416,8 +284,8 @@ describe('DirectionsTool', () => {
416
284
  // Test with driving profile - should work
417
285
  await expect(tool.run({
418
286
  coordinates: [
419
- { longitude: -73.989, latitude: 40.733 },
420
- { longitude: -73.979, latitude: 40.743 }
287
+ [-73.989, 40.733],
288
+ [-73.979, 40.743]
421
289
  ],
422
290
  routing_profile: 'driving',
423
291
  exclude: 'point(-73.95 40.75)'
@@ -427,8 +295,8 @@ describe('DirectionsTool', () => {
427
295
  // Test with walking profile - should fail
428
296
  await expect(tool.run({
429
297
  coordinates: [
430
- { longitude: -73.989, latitude: 40.733 },
431
- { longitude: -73.979, latitude: 40.743 }
298
+ [-73.989, 40.733],
299
+ [-73.979, 40.743]
432
300
  ],
433
301
  routing_profile: 'walking',
434
302
  exclude: 'point(-73.95 40.75)'
@@ -438,8 +306,8 @@ describe('DirectionsTool', () => {
438
306
  // Test with cycling profile - should fail
439
307
  await expect(tool.run({
440
308
  coordinates: [
441
- { longitude: -73.989, latitude: 40.733 },
442
- { longitude: -73.979, latitude: 40.743 }
309
+ [-73.989, 40.733],
310
+ [-73.979, 40.743]
443
311
  ],
444
312
  routing_profile: 'cycling',
445
313
  exclude: 'point(-73.95 40.75)'
@@ -453,8 +321,8 @@ describe('DirectionsTool', () => {
453
321
  // All valid exclusions for driving profile
454
322
  await expect(tool.run({
455
323
  coordinates: [
456
- { longitude: -73.989, latitude: 40.733 },
457
- { longitude: -73.979, latitude: 40.743 }
324
+ [-73.989, 40.733],
325
+ [-73.979, 40.743]
458
326
  ],
459
327
  routing_profile: 'driving',
460
328
  exclude: 'toll,motorway,ferry,cash_only_tolls,point(-73.95 40.75)'
@@ -464,8 +332,8 @@ describe('DirectionsTool', () => {
464
332
  // Mixed valid and invalid exclusions (ferry is valid for walking, toll is not)
465
333
  await expect(tool.run({
466
334
  coordinates: [
467
- { longitude: -73.989, latitude: 40.733 },
468
- { longitude: -73.979, latitude: 40.743 }
335
+ [-73.989, 40.733],
336
+ [-73.979, 40.743]
469
337
  ],
470
338
  routing_profile: 'walking',
471
339
  exclude: 'ferry,toll'
@@ -475,8 +343,8 @@ describe('DirectionsTool', () => {
475
343
  // All valid exclusions for cycling profile
476
344
  await expect(tool.run({
477
345
  coordinates: [
478
- { longitude: -73.989, latitude: 40.733 },
479
- { longitude: -73.979, latitude: 40.743 }
346
+ [-73.989, 40.733],
347
+ [-73.979, 40.743]
480
348
  ],
481
349
  routing_profile: 'cycling',
482
350
  exclude: 'ferry,cash_only_tolls'
@@ -493,8 +361,8 @@ describe('DirectionsTool', () => {
493
361
  // Test with driving profile
494
362
  await expect(tool.run({
495
363
  coordinates: [
496
- { longitude: -73.989, latitude: 40.733 },
497
- { longitude: -73.979, latitude: 40.743 }
364
+ [-73.989, 40.733],
365
+ [-73.979, 40.743]
498
366
  ],
499
367
  routing_profile: 'driving',
500
368
  depart_at: validDateTime
@@ -506,8 +374,8 @@ describe('DirectionsTool', () => {
506
374
  // Test with driving-traffic profile
507
375
  await expect(tool.run({
508
376
  coordinates: [
509
- { longitude: -73.989, latitude: 40.733 },
510
- { longitude: -73.979, latitude: 40.743 }
377
+ [-73.989, 40.733],
378
+ [-73.979, 40.743]
511
379
  ],
512
380
  routing_profile: 'driving-traffic',
513
381
  depart_at: validDateTime
@@ -524,8 +392,8 @@ describe('DirectionsTool', () => {
524
392
  // Test with driving profile
525
393
  await expect(tool.run({
526
394
  coordinates: [
527
- { longitude: -73.989, latitude: 40.733 },
528
- { longitude: -73.979, latitude: 40.743 }
395
+ [-73.989, 40.733],
396
+ [-73.979, 40.743]
529
397
  ],
530
398
  routing_profile: 'driving',
531
399
  max_height: 4.5,
@@ -541,8 +409,8 @@ describe('DirectionsTool', () => {
541
409
  // Test with driving-traffic profile
542
410
  await expect(tool.run({
543
411
  coordinates: [
544
- { longitude: -73.989, latitude: 40.733 },
545
- { longitude: -73.979, latitude: 40.743 }
412
+ [-73.989, 40.733],
413
+ [-73.979, 40.743]
546
414
  ],
547
415
  routing_profile: 'driving-traffic',
548
416
  max_height: 3.2
@@ -557,8 +425,8 @@ describe('DirectionsTool', () => {
557
425
  // Test with walking profile
558
426
  await expect(tool.run({
559
427
  coordinates: [
560
- { longitude: -73.989, latitude: 40.733 },
561
- { longitude: -73.979, latitude: 40.743 }
428
+ [-73.989, 40.733],
429
+ [-73.979, 40.743]
562
430
  ],
563
431
  routing_profile: 'walking',
564
432
  max_height: 4.5
@@ -568,8 +436,8 @@ describe('DirectionsTool', () => {
568
436
  // Test with cycling profile
569
437
  await expect(tool.run({
570
438
  coordinates: [
571
- { longitude: -73.989, latitude: 40.733 },
572
- { longitude: -73.979, latitude: 40.743 }
439
+ [-73.989, 40.733],
440
+ [-73.979, 40.743]
573
441
  ],
574
442
  routing_profile: 'cycling',
575
443
  max_width: 2.0
@@ -582,8 +450,8 @@ describe('DirectionsTool', () => {
582
450
  // Test invalid height (too high)
583
451
  await expect(tool.run({
584
452
  coordinates: [
585
- { longitude: -73.989, latitude: 40.733 },
586
- { longitude: -73.979, latitude: 40.743 }
453
+ [-73.989, 40.733],
454
+ [-73.979, 40.743]
587
455
  ],
588
456
  routing_profile: 'driving',
589
457
  max_height: 15.0
@@ -593,8 +461,8 @@ describe('DirectionsTool', () => {
593
461
  // Test invalid width (negative)
594
462
  await expect(tool.run({
595
463
  coordinates: [
596
- { longitude: -73.989, latitude: 40.733 },
597
- { longitude: -73.979, latitude: 40.743 }
464
+ [-73.989, 40.733],
465
+ [-73.979, 40.743]
598
466
  ],
599
467
  routing_profile: 'driving',
600
468
  max_width: -1.0
@@ -604,8 +472,8 @@ describe('DirectionsTool', () => {
604
472
  // Test invalid weight (too heavy)
605
473
  await expect(tool.run({
606
474
  coordinates: [
607
- { longitude: -73.989, latitude: 40.733 },
608
- { longitude: -73.979, latitude: 40.743 }
475
+ [-73.989, 40.733],
476
+ [-73.979, 40.743]
609
477
  ],
610
478
  routing_profile: 'driving',
611
479
  max_weight: 150.0
@@ -620,8 +488,8 @@ describe('DirectionsTool', () => {
620
488
  // Test with walking profile
621
489
  await expect(tool.run({
622
490
  coordinates: [
623
- { longitude: -73.989, latitude: 40.733 },
624
- { longitude: -73.979, latitude: 40.743 }
491
+ [-73.989, 40.733],
492
+ [-73.979, 40.743]
625
493
  ],
626
494
  routing_profile: 'walking',
627
495
  depart_at: validDateTime
@@ -631,8 +499,8 @@ describe('DirectionsTool', () => {
631
499
  // Test with cycling profile
632
500
  await expect(tool.run({
633
501
  coordinates: [
634
- { longitude: -73.989, latitude: 40.733 },
635
- { longitude: -73.979, latitude: 40.743 }
502
+ [-73.989, 40.733],
503
+ [-73.979, 40.743]
636
504
  ],
637
505
  routing_profile: 'cycling',
638
506
  depart_at: validDateTime
@@ -644,8 +512,8 @@ describe('DirectionsTool', () => {
644
512
  const mockFetch = setupFetch();
645
513
  const tool = new DirectionsTool();
646
514
  const baseCoordinates = [
647
- { longitude: -73.989, latitude: 40.733 },
648
- { longitude: -73.979, latitude: 40.743 }
515
+ [-73.989, 40.733],
516
+ [-73.979, 40.743]
649
517
  ];
650
518
  // Format 1: YYYY-MM-DDThh:mm:ssZ
651
519
  await expect(tool.run({
@@ -672,8 +540,8 @@ describe('DirectionsTool', () => {
672
540
  it('rejects invalid date-time formats', async () => {
673
541
  const tool = new DirectionsTool();
674
542
  const baseCoordinates = [
675
- { longitude: -73.989, latitude: 40.733 },
676
- { longitude: -73.979, latitude: 40.743 }
543
+ [-73.989, 40.733],
544
+ [-73.979, 40.743]
677
545
  ];
678
546
  // Invalid format examples
679
547
  const invalidFormats = [
@@ -699,8 +567,8 @@ describe('DirectionsTool', () => {
699
567
  it('rejects dates with invalid components', async () => {
700
568
  const tool = new DirectionsTool();
701
569
  const baseCoordinates = [
702
- { longitude: -73.989, latitude: 40.733 },
703
- { longitude: -73.979, latitude: 40.743 }
570
+ [-73.989, 40.733],
571
+ [-73.979, 40.743]
704
572
  ];
705
573
  // Invalid time components
706
574
  const invalidDates = [
@@ -719,6 +587,45 @@ describe('DirectionsTool', () => {
719
587
  });
720
588
  }
721
589
  });
590
+ it('depart_at accepts and converts YYYY-MM-DDThh:mm:ss format (seconds but no timezone)', async () => {
591
+ const mockFetch = setupFetch();
592
+ const tool = new DirectionsTool();
593
+ const dateTimeWithSeconds = '2025-06-05T10:30:45';
594
+ const expectedConvertedDateTime = '2025-06-05T10:30'; // Without seconds
595
+ await expect(tool.run({
596
+ coordinates: [
597
+ [-73.989, 40.733],
598
+ [-73.979, 40.743]
599
+ ],
600
+ depart_at: dateTimeWithSeconds
601
+ })).resolves.not.toMatchObject({
602
+ is_error: true
603
+ });
604
+ // Verify the seconds were stripped in the API call
605
+ const calledUrl = mockFetch.mock.calls[0][0];
606
+ expect(calledUrl).toContain(`depart_at=${encodeURIComponent(expectedConvertedDateTime)}`);
607
+ expect(calledUrl).not.toContain(`depart_at=${encodeURIComponent(dateTimeWithSeconds)}`);
608
+ });
609
+ it('arrive_by accepts and converts YYYY-MM-DDThh:mm:ss format (seconds but no timezone)', async () => {
610
+ const mockFetch = setupFetch();
611
+ const tool = new DirectionsTool();
612
+ const dateTimeWithSeconds = '2025-06-05T10:30:45';
613
+ const expectedConvertedDateTime = '2025-06-05T10:30'; // Without seconds
614
+ await expect(tool.run({
615
+ coordinates: [
616
+ [-73.989, 40.733],
617
+ [-73.979, 40.743]
618
+ ],
619
+ routing_profile: 'driving',
620
+ arrive_by: dateTimeWithSeconds
621
+ })).resolves.not.toMatchObject({
622
+ is_error: true
623
+ });
624
+ // Verify the seconds were stripped in the API call
625
+ const calledUrl = mockFetch.mock.calls[0][0];
626
+ expect(calledUrl).toContain(`arrive_by=${encodeURIComponent(expectedConvertedDateTime)}`);
627
+ expect(calledUrl).not.toContain(`arrive_by=${encodeURIComponent(dateTimeWithSeconds)}`);
628
+ });
722
629
  });
723
630
  describe('arrive_by parameter validations', () => {
724
631
  it('accepts arrive_by with driving profile only', async () => {
@@ -727,8 +634,8 @@ describe('DirectionsTool', () => {
727
634
  // Test with driving profile - should work
728
635
  await new DirectionsTool().run({
729
636
  coordinates: [
730
- { longitude: -74.1, latitude: 40.7 },
731
- { longitude: -74.2, latitude: 40.8 }
637
+ [-74.1, 40.7],
638
+ [-74.2, 40.8]
732
639
  ],
733
640
  routing_profile: 'driving',
734
641
  arrive_by: validDateTime
@@ -742,8 +649,8 @@ describe('DirectionsTool', () => {
742
649
  // Test with driving-traffic profile
743
650
  const result1 = await new DirectionsTool().run({
744
651
  coordinates: [
745
- { longitude: -74.1, latitude: 40.7 },
746
- { longitude: -74.2, latitude: 40.8 }
652
+ [-74.1, 40.7],
653
+ [-74.2, 40.8]
747
654
  ],
748
655
  routing_profile: 'driving-traffic',
749
656
  arrive_by: validDateTime
@@ -752,8 +659,8 @@ describe('DirectionsTool', () => {
752
659
  // Test with walking profile
753
660
  const result2 = await new DirectionsTool().run({
754
661
  coordinates: [
755
- { longitude: -74.1, latitude: 40.7 },
756
- { longitude: -74.2, latitude: 40.8 }
662
+ [-74.1, 40.7],
663
+ [-74.2, 40.8]
757
664
  ],
758
665
  routing_profile: 'walking',
759
666
  arrive_by: validDateTime
@@ -762,8 +669,8 @@ describe('DirectionsTool', () => {
762
669
  // Test with cycling profile
763
670
  const result3 = await new DirectionsTool().run({
764
671
  coordinates: [
765
- { longitude: -74.1, latitude: 40.7 },
766
- { longitude: -74.2, latitude: 40.8 }
672
+ [-74.1, 40.7],
673
+ [-74.2, 40.8]
767
674
  ],
768
675
  routing_profile: 'cycling',
769
676
  arrive_by: validDateTime
@@ -773,8 +680,8 @@ describe('DirectionsTool', () => {
773
680
  it('rejects when both arrive_by and depart_at are provided', async () => {
774
681
  const result = await new DirectionsTool().run({
775
682
  coordinates: [
776
- { longitude: -74.1, latitude: 40.7 },
777
- { longitude: -74.2, latitude: 40.8 }
683
+ [-74.1, 40.7],
684
+ [-74.2, 40.8]
778
685
  ],
779
686
  routing_profile: 'driving',
780
687
  depart_at: '2025-06-05T09:30:00Z',
@@ -787,8 +694,8 @@ describe('DirectionsTool', () => {
787
694
  // Test with Z format
788
695
  await new DirectionsTool().run({
789
696
  coordinates: [
790
- { longitude: -74.1, latitude: 40.7 },
791
- { longitude: -74.2, latitude: 40.8 }
697
+ [-74.1, 40.7],
698
+ [-74.2, 40.8]
792
699
  ],
793
700
  routing_profile: 'driving',
794
701
  arrive_by: '2025-06-05T10:30:00Z'
@@ -798,8 +705,8 @@ describe('DirectionsTool', () => {
798
705
  // Test with timezone offset format
799
706
  await new DirectionsTool().run({
800
707
  coordinates: [
801
- { longitude: -74.1, latitude: 40.7 },
802
- { longitude: -74.2, latitude: 40.8 }
708
+ [-74.1, 40.7],
709
+ [-74.2, 40.8]
803
710
  ],
804
711
  routing_profile: 'driving',
805
712
  arrive_by: '2025-06-05T10:30:00+02:00'
@@ -809,8 +716,8 @@ describe('DirectionsTool', () => {
809
716
  // Test with simple time format (no seconds, no timezone)
810
717
  await new DirectionsTool().run({
811
718
  coordinates: [
812
- { longitude: -74.1, latitude: 40.7 },
813
- { longitude: -74.2, latitude: 40.8 }
719
+ [-74.1, 40.7],
720
+ [-74.2, 40.8]
814
721
  ],
815
722
  routing_profile: 'driving',
816
723
  arrive_by: '2025-06-05T10:30'
@@ -836,8 +743,8 @@ describe('DirectionsTool', () => {
836
743
  for (const format of invalidFormats) {
837
744
  const result = await new DirectionsTool().run({
838
745
  coordinates: [
839
- { longitude: -74.1, latitude: 40.7 },
840
- { longitude: -74.2, latitude: 40.8 }
746
+ [-74.1, 40.7],
747
+ [-74.2, 40.8]
841
748
  ],
842
749
  routing_profile: 'driving',
843
750
  arrive_by: format
@@ -857,8 +764,8 @@ describe('DirectionsTool', () => {
857
764
  for (const date of invalidDates) {
858
765
  const result = await new DirectionsTool().run({
859
766
  coordinates: [
860
- { longitude: -74.1, latitude: 40.7 },
861
- { longitude: -74.2, latitude: 40.8 }
767
+ [-74.1, 40.7],
768
+ [-74.2, 40.8]
862
769
  ],
863
770
  routing_profile: 'driving',
864
771
  arrive_by: date
@@ -867,5 +774,49 @@ describe('DirectionsTool', () => {
867
774
  }
868
775
  });
869
776
  });
777
+ it('validates geometries enum values', async () => {
778
+ const tool = new DirectionsTool();
779
+ // Valid values: 'none' and 'geojson'
780
+ await expect(tool.run({
781
+ coordinates: [
782
+ [-73.989, 40.733],
783
+ [-73.979, 40.743]
784
+ ],
785
+ geometries: 'none'
786
+ })).resolves.not.toMatchObject({
787
+ is_error: true
788
+ });
789
+ await expect(tool.run({
790
+ coordinates: [
791
+ [-73.989, 40.733],
792
+ [-73.979, 40.743]
793
+ ],
794
+ geometries: 'geojson'
795
+ })).resolves.not.toMatchObject({
796
+ is_error: true
797
+ });
798
+ // Invalid values: 'polyline' and 'polyline6' were removed
799
+ // Test with invalid string values (runtime validation)
800
+ await expect(tool.run({
801
+ coordinates: [
802
+ [-73.989, 40.733],
803
+ [-73.979, 40.743]
804
+ ],
805
+ // @ts-ignore - Testing with invalid value for runtime validation
806
+ geometries: 'polyline'
807
+ })).resolves.toMatchObject({
808
+ is_error: true
809
+ });
810
+ await expect(tool.run({
811
+ coordinates: [
812
+ [-73.989, 40.733],
813
+ [-73.979, 40.743]
814
+ ],
815
+ // @ts-ignore - Testing with invalid value for runtime validation
816
+ geometries: 'polyline6'
817
+ })).resolves.toMatchObject({
818
+ is_error: true
819
+ });
820
+ });
870
821
  });
871
822
  //# sourceMappingURL=DirectionsTool.test.js.map