Every change Wellknown observed on this MCP server, newest first, with what it was before and what it became. Tool-surface changes carry the definition diff. Nothing here is edited after the fact.
Changed the definition of "find_routes_between"
⟨80 unchanged words⟩ or when they beat the best direct one. `map_stops` holds the best trip's stops in riding order, each with a `role` (board, transfer — or transfer_alight + transfer_board when the interchange is a walk — and alight). Use when the user asks how to get ⟨80 unchanged words⟩
⟨30 unchanged words⟩ ,"stop_ids"],"type":"object"},"map_stops":{"items":{"additionalProperties":false,"properties":{"id":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"name":{"type":["string","null"]},"role":{"enum":["board","transfer","transfer_alight","transfer_board","alight"],"type":"string"}},"required":["id","name","lat","lng","role"],"type":"object"},"type":"array"},"options":{"items":{"additionalProperties":false," ⟨268 unchanged words⟩ :["from","to","options","transfer_options","map_stops","updated_at"],"type":"object"}, ⟨72 unchanged words⟩
Changed the definition of "find_routes_between"
Lists thedirectroutes(no transfer)from one place to another: which stop to ⟨15 unchanged words⟩ each end — best first, walking counted. `options` are direct routes. `transfer_options` have exactly one interchange (never more): ride `legs[0]`, walk `transfer_walk_meters` (within a 300 m stop cluster, 0 when it is the same stop) to `legs[1].board_stop`, ride `legs[1]`. They are listed when there is no direct route or when they beat the best direct one. Use when the user asks how to get ⟨41 unchanged words⟩ different names; `board_stop` says where to actually wait.An emptyBoth`options`listslistempty meansnothedirect
Changed the definition of "get_route_static"
⟨19 unchanged words⟩ timetable of departures from the first stop (workday, Saturday andweekendSunday). Use when the user asks which stops ⟨59 unchanged words⟩
⟨76 unchanged words⟩ schedule":{"additionalProperties":false,"properties":{"saturday":{"items":{"type":"string"},"type":"array"},"sunday":{"items":{"type":"string"},"type":"array"},"weekend":{"items":{"type":"string" ⟨6 unchanged words⟩ type":"array"}},"required":["workday","saturday","sunday","weekend"],"type":"object"}} ⟨93 unchanged words⟩
Certificate changed, valid to 2026-12-27
Added "find_routes_between" and "search_stops"; removed "get_stop_geometry"; changed the definition of "get_nearby_vehicles", "get_route_realtime", "get_route_static" and 3 more (7 tools before, 8 now)
Returns livepositionsvehiclesfornearallatransitpoint,vehiclesnearestwithinfirst,1eachkmwithofits
Certificate recorded, valid to 2026-10-29
Authorization not required
First tool surface recorded: 7 tools (server version 1.4.0)
Showing the latest 8 events. The API returns up to 500 and filters by kind: ?kind=tool_surface_changed
⟨162 unchanged words⟩ ,"stop_ids"],"type":"object"},"transfer_options":{"items":{"additionalProperties":false,"properties":{"legs":{"items":{"additionalProperties":false,"properties":{"alight_stop":{"additionalProperties":false,"properties":{"id":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"name":{"type":["string","null"]}},"required":["id","name","lat","lng"],"type":"object"},"board_stop":{"additionalProperties":false,"properties":{"id":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"name":{"type":["string","null"]}},"required":["id","name","lat","lng"],"type":"object"},"destination":{"type":["string","null"]},"direction":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"route":{"type":"string"},"stops_count":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"vehicle_type":{"type":"string"}},"required":["route","vehicle_type","direction","destination","board_stop","alight_stop","stops_count"],"type":"object"},"type":"array"},"stops_count":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"transfer_walk_meters":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"walk_from_alight_meters":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"walk_to_board_meters":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"}},"required":["legs","transfer_walk_meters","stops_count","walk_to_board_meters","walk_from_alight_meters"],"type":"object"},"type":"array"},"updated_at":{"type":"string"}},"required":["from","to","options","transfer_options","updated_at"],"type":"object"}, ⟨72 unchanged words⟩
⟨8 unchanged words⟩ of the centre point, WGS84 (e.g. 49.842 for central Lviv).","maximum":90,"minimum":-90,"type":"number"},"limit":{"description":"Maximum vehicles to return, nearest first (1–50, default 15). `total` reports how many were in range.","maximum":50,"minimum":1,"type":"integer"},"longitude":{"description":"Decimal longitude of the centre point, WGS84 (e.g. 24.031 for central Lviv).","maximum":180,"minimum":-180,"type":"number"},"radius_meters":{"description":"Search radius in metres (100–1000, default 500).","maximum":1000,"minimum":100,"type":"integer"},"route":{"description":"Only vehicles on this route, by short name (e.g. \"Т30\", \"А1\"). Omit for all routes.","minLength":1,"type":"string"}},"required":["latitude","longitude" ⟨2 unchanged words⟩
⟨15 unchanged words⟩ "type":["number","null"]},"radius_meters":{"type":"number"},"total":{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},"updated_at":{"type":"string"},"vehicles" ⟨5 unchanged words⟩ "type":["number","null"]},"destination":{"type":["string","null"]},"direction":{"anyOf":[{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},{"type":"null"}]},"distance_meters":{"type":["number","null"]},"id":{"type":["string","null"]},"lat":{"type":["number", ⟨18 unchanged words⟩ ":["id","route","vehicle_type","direction","destination","lat","lng","bearing","lowfloor","distance_meters"],"type":"object"},"type":"array"}},"required":["center_lat","center_lng","radius_meters","total","vehicles","updated_at"],"type":"object"} ⟨21 unchanged words⟩ "minItems":2,"type":"array"},"vehicles":{"itemslayers":{"additionalProperties":false,"properties":{"bearing":{"type":["number","null"]},"eta_minutes":{"anyOf":[{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},{"type":"null"}]},"eta_status":{"enum":["assigned","unassigned"],"type":"string"},"idpolylines":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"next_stop_idstops":{"type":["string","null"]},"routevehicles":{"type":["string","null"]}},"required":["id","route","lat","lng","bearing","next_stop_id","eta_minutes","eta_status"],"type":"object"},"type":"array"},"zoom":{"type":"number"}},"required":["center","zoom","vehicleslayers"],"type":"object"},"type": ⟨22 unchanged words⟩
Returnslive positions for alleveryvehiclesvehicle currently running on a route: position,optimisedthefordestinationmapitrendering.is heading to, and its next stop with estimated arrival. Use when the user asks "where is my tram/bus right now?"or wants,tohowseemanyallvehiclesactivearevehiclesrunning,onorahowspecificfarroutetheonnextaonemap.is. Prefer `get_stop_realtime` when the user is at a stop and wantsto knowarrival timesrather than vehicle positions. Prefer `get_route_static` when only the route shape or stop list is needed without live data.there. Requires a route short name (e.g. "T30 ⟨5 unchanged words⟩
⟨6 unchanged words⟩ data":{"additionalProperties":false,"properties":{"destinations":{"items":{"type":["string","null"]},"type":"array"},"route_name":{"type":"string"},"updated_at" ⟨8 unchanged words⟩ "type":["number","null"]},"destination":{"type":["string","null"]},"direction":{"anyOf":[{"maximum":9007199254740991, ⟨18 unchanged words⟩ :{"type":["boolean","null"]}},"requirednext_stop":{"anyOf":[{"idadditionalProperties":false,"directionproperties",:{"latarrival",:{"lngtype",:"bearingstring
Returns static routemetadatadata:short andname, long name, vehicle type,brandcolour, the ordered stoplistslist for both directions, androutethepolylinestimetable(shapes)offordeparturesmapfromrendering.the first stop (workday and weekend). Use when the user asks which stops a route serves,whatwhereaitroutegoes,looksorlikeitsonscheduledadeparturemap,times.orSetwhat`include_shapes`theonlyscheduledwhendepartureyoutimeswillaredraw(workdaytheandrouteweekendonschedulesa map — the polylines areincludedlargeinandeachcarrystop'snothing`schedule`afield).text answer needs. Do NOT use thiswhenfor live vehicle positionsare needed— use `get_route_realtime` instead. Requires a route short name (e.g. "T30", "32A") or numeric externalID; call `get_stops_around_location` first if you only know a location and need to discover which routes serve it.ID.
{"$schema":"http://json-schema.org/draft-07/schema#","properties":{"include_shapes":{"description":"Include route polylines ([lat, lng] points per direction) for map drawing. Default false.","type":"boolean"},"route_name":{"description":"Route short name ( ⟨17 unchanged words⟩
⟨112 unchanged words⟩ },"required":["route","stops","shapes","updated_at"],"type":"object"},"ui_blocks" ⟨20 unchanged words⟩ "minItems":2,"type":"array"},"polylines":{"items":{"items":{"items":{"type":"number"},"type":"array"},"type":"array"},"type":"array"},"stops":{"itemslayers":{"additionalProperties":false,"properties":{"idpolylines":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"namestops":{"type":["string","null"]}},"required":["id","name","lat","lng"],"type":"object"},"type":"array"},"vehicles":{"items":{"additionalProperties":false,"properties":{"bearing":{"type":["number","null"]},"eta_minutes":{"anyOf":[{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},{"type":"null"}]},"eta_status":{"enum":["assigned","unassigned"],"type":"string"},"id":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"next_stop_id":{"type":["string","null"]},"route":{"type":["string","null"]}},"required":["id","route","lat","lng","bearing","next_stop_id","eta_minutes","eta_status"],"type":"
Returns live arrivalsand vehicle positions forat a stop: route,producingdestination,bothvehicleatype,mapminutesUIuntilblockarrival, anda structuredeacharrivalvehicle'slist.position. Use this as the **default tool** when the user asks about arrivals, departures, orvehiclesthe next bus/tram at a specific stop.Prefer `get_stop_geometry` when only static route polylines are needed and live data is irrelevant.Requires a numeric stop ID (shown on stop signage); use`get_stops_around_location` first`search_stops`ifwhen youonlyhaveanaaddressstop name, or `get_stops_around_location` when you have coordinates.
⟨123 unchanged words⟩ "minItems":2,"type":"array"},"stop":{"anyOflayers":[{"additionalProperties":false,"properties":{"idpolylines":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"namestops":{"type":["string","null"]}},"required":["id","name","lat","lng"],"type":"object"},{"type":"null"}]},"vehicles":{"items":{"additionalProperties":false,"properties":{"bearing":{"type":["number","null"]},"eta_minutes":{"anyOf":[{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},{"type":"null"}]},"eta_status":{"enum":["assigned","unassigned"],"type":"string"},"id":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"next_stop_id":{"type":["string","null"]},"route":{"type":["string","null"]}},"required":["id","route","lat","lng","bearing","next_stop_id","eta_minutes","eta_status"],"type":"object"},"type":"array"},"zoom":{"type":"number"}},"required":["center","zoom","
Discovers transitFinds stops near a geographic point, returning each stop's numericcodeID, name, coordinates,andwalkingdistance. Also emits a map UI block with multiple markersdistance,forandmap-capabletheclientsroutes(e.g.servingChatGPT).it. Use this as the **first step**wheneverwhen the userprovidesgives an address,place name,or coordinates and you need stop IDsbefore callingfor `get_stop_realtime` or`get_stop_geometry`. Do NOT use this to fetch`find_routes_between`.arrivalsUseor`search_stops`liveinsteadvehiclewhendatathe—useritgivesreturnsa stopmetadata only.name. Default radius is 1 000 m; narrow it ⟨18 unchanged words⟩
⟨42 unchanged words⟩ :{"type":["string","null"]},"routes":{"items":{"type":"string"},"type":"array"}},"required":["id","name","lat","lng","routes","distance_meters"],"type":"object"},"type" ⟨33 unchanged words⟩ "minItems":2,"type":"array"},"stops":{"itemslayers":{"additionalProperties":false,"properties":{"distance_meters":{"type":["number","null"]},"idpolylines":{"type":"string"},"lat":{"type":["number","null"]},"lng":{"type":["number","null"]},"namestops":{"type":["string","null"]}},"required":["id","name","lat","lng","distance_meters"],"type":"object"},"type":"array"},"vehicles":{"items":{"additionalProperties":false,"properties":{"bearing":{"type":["number","null"]},"eta_minutes":{"anyOf":[{"maximum":9007199254740991,"minimum":-9007199254740991,"type":"integer"},{"type":"null"}]},"eta_status":{"enum":["assigned","unassigned"],"type":"string"},"id":{"type":"string"},"lat":{"type":[
Returnsfulldetails fora specific transitone vehicle byitsID:currentposition,bearingroute,routedestination, license plate,direction,and its upcomingstopstopsarrivals.with names and estimated arrival times. Use when the user wants totrackfollow a particular vehicle,(e.g.after"whereseeingdoesitthisontramago`get_route_realtime`next?"map)or "when will it reach X?". Vehicle IDs come from `get_route_realtime`, `get_nearby_vehicles`, ⟨18 unchanged words⟩
⟨11 unchanged words⟩ "type":["number","null"]},"destination":{"type":["string","null"]},"direction":{"anyOf":[{"maximum":9007199254740991, ⟨28 unchanged words⟩ "type":["string","null"]},"codedeparture":{"maximumtype":9007199254740991["string","minimumnull":-9007199254740991]},"id":{"type":"integerstring"},"departurename":{"type":["string","null"]}},"required":["codeid","name","arrival","departure"],"type":"object"} ⟨12 unchanged words⟩ lat","lng","bearing","direction","destination","upcoming_stops","updated_at"],"type":"object"} ⟨21 unchanged words⟩ "minItems":2,"type":"array"},"vehicles":{"itemslayers
Find Routes Between Stops — Lists the direct routes (no transfer) from one place to another: which stop to board, where to get off, the direction's destination, stops in between, and the walk at each end — best first, walking counted. Use when the user asks how to get from A to B, or which bus/tram goes from one place to another. Each end covers every stop within a 300 m walk of the one given, since a line's two directions often stop on opposite sides of a street under different names; `board_stop` says where to actually wait. An empty `options` list means no direct route: a transfer is needed. Requires numeric stop IDs…
Search Stops — Finds stops by name (Ukrainian or English transliteration, case-insensitive, partial match) and returns each stop's numeric ID, coordinates, and the routes serving it. Use this as the **first step** when the user names a stop or landmark stop (e.g. "Опера", "Rynok", "Головний вокзал") and you need a stop ID for `get_stop_realtime` or `find_routes_between`. One name usually covers both sides of the street under different IDs; each is returned, and the `routes` list tells them apart. Use `get_stops_around_location` instead when you have coordinates rather than a name.
Get Stop Geometry — Returns static map context for a stop: its marker and polylines for every route that serves it. No live data is fetched. Use this when you need to enrich an existing map with route shapes (e.g. overlay polylines alongside a `get_stop_realtime` map block) or when the user asks to visualise which routes pass a stop without needing live arrivals. Do NOT use this when live arrival times or vehicle positions are needed — use `get_stop_realtime` instead. Requires a numeric stop ID; call `get_stops_around_location` first if you only have coordinates.