diff --git a/src/services/RoutesService.ts b/src/services/RoutesService.ts index 6065e19..6f6721d 100644 --- a/src/services/RoutesService.ts +++ b/src/services/RoutesService.ts @@ -25,6 +25,7 @@ const COMPUTE_ROUTES_FIELD_MASK = [ "routes.legs.steps.staticDuration", "routes.legs.steps.startLocation", "routes.legs.steps.endLocation", + "routes.legs.steps.transitDetails", "routes.legs.polyline", "routes.optimizedIntermediateWaypointIndex", ].join(","); diff --git a/src/tools/maps/directions.ts b/src/tools/maps/directions.ts index 0550b57..9934f28 100644 --- a/src/tools/maps/directions.ts +++ b/src/tools/maps/directions.ts @@ -15,7 +15,10 @@ const SCHEMA = { .describe("Travel mode for directions"), departure_time: z.string().optional().describe("Departure time (ISO string format)"), arrival_time: z.string().optional().describe("Arrival time (ISO string format)"), - avoid_tolls: z.boolean().optional().describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), + avoid_tolls: z + .boolean() + .optional() + .describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), avoid_highways: z .boolean() .optional() diff --git a/src/tools/maps/distanceMatrix.ts b/src/tools/maps/distanceMatrix.ts index 7ce97a1..7819674 100644 --- a/src/tools/maps/distanceMatrix.ts +++ b/src/tools/maps/distanceMatrix.ts @@ -19,7 +19,10 @@ const SCHEMA = { .describe( "Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware duration estimates." ), - avoid_tolls: z.boolean().optional().describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), + avoid_tolls: z + .boolean() + .optional() + .describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), avoid_highways: z .boolean() .optional() diff --git a/src/tools/maps/planRoute.ts b/src/tools/maps/planRoute.ts index 7f8d106..10a2a92 100644 --- a/src/tools/maps/planRoute.ts +++ b/src/tools/maps/planRoute.ts @@ -19,7 +19,10 @@ const SCHEMA = { .string() .optional() .describe("Departure time in ISO 8601 format (e.g. 2026-03-21T09:00:00Z). Enables traffic-aware routing."), - avoid_tolls: z.boolean().optional().describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), + avoid_tolls: z + .boolean() + .optional() + .describe('Avoid toll roads where reasonable. Only supported with mode "driving".'), avoid_highways: z .boolean() .optional() diff --git a/tests/smoke.test.ts b/tests/smoke.test.ts index 5df0bc5..ce32e5a 100644 --- a/tests/smoke.test.ts +++ b/tests/smoke.test.ts @@ -1103,6 +1103,51 @@ async function testTransitErrorMessages(session: McpSession): Promise { } } +async function testTransitDetailsField(session: McpSession): Promise { + if (!API_KEY) { + console.log(" ā­ļø Skipped transitDetails test (no GOOGLE_MAPS_API_KEY)"); + return; + } + + console.log("\nšŸ” Testing transit step includes transitDetails (field mask)..."); + + // Dublin Airport → city centre: virtually always returns a bus step (issue #78 scope). + const result = await sendRequest(session, "tools/call", { + name: "maps_directions", + arguments: { + origin: "Dublin Airport, Ireland", + destination: "Trinity College Dublin, Ireland", + mode: "transit", + }, + }); + const content = result?.result?.content ?? []; + assert(content.length > 0, "Transit directions in Dublin returns content"); + if (content.length === 0) return; + + const text = content[0]?.text ?? ""; + const isError = result?.result?.isError === true; + assert(!isError, `Transit directions in Dublin should succeed, got error: ${text.slice(0, 200)}`); + if (isError) return; + + const parsed = JSON.parse(text); + const steps: any[] = parsed?.routes?.[0]?.legs?.flatMap((l: any) => l.steps ?? []) ?? []; + assert(steps.length > 0, "Transit response has at least one step"); + + const transitStep = steps.find((s: any) => s.transitDetails); + if (!transitStep) { + // Routes API may rarely return a walking-only itinerary; warn but don't flaky-fail. + console.log(" āš ļø No transit step in this itinerary — field mask correctness cannot be asserted this run"); + return; + } + + const td = transitStep.transitDetails; + assert( + td?.transitLine || td?.stopDetails, + "transitDetails contains structured transit metadata (transitLine or stopDetails)", + `got: ${JSON.stringify(td).slice(0, 200)}` + ); +} + // --------------- Main --------------- async function main() { @@ -1127,6 +1172,7 @@ async function main() { await testToolCalls(session); await testPlaceDetailsPhotos(session); await testTransitErrorMessages(session); + await testTransitDetailsField(session); await testMultiSession(); } catch (err) { console.error("\nšŸ’„ Fatal error:", err);