{"serverId":"mcp-registry/ai.mapmap/mapmap","tools":[{"name":"check_adr_tunnel","fixed":{"name":"check_adr_tunnel","description":"Check whether a vehicle may pass through a tunnel of a given ADR category (\"A\"–\"E\"). Provide `hazmat` and, when known, the load's ADR 8.6.4 tunnel restriction code (e.g. \"B\", \"C5000D\", \"B/D\", \"none\"). Applies the conservative worst-case reading: conditional clauses are assumed to apply, so a blocked answer may over-restrict but never under-restricts. No network access; answers instantly.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["hazmat","tunnel_category"],"properties":{"hazmat":{"type":"boolean","description":"Whether the vehicle carries dangerous goods at all. When false the\nADR tunnel matrix does not apply and every tunnel is permitted."},"tunnel_code":{"type":["string","null"],"description":"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\". Leave unset for a hazmat load of unknown\ncode (conservatively treated as code B)."},"tunnel_category":{"type":"string","description":"ADR category of the tunnel to check: \"A\", \"B\", \"C\", \"D\" or \"E\"."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":315,"tokensAfter":315},{"name":"check_clearance_on_route","fixed":{"name":"check_clearance_on_route","description":"Measure a vehicle's overhead clearance along a route against surveyed point cloud geometry, wherever survey coverage exists. Routes with truck costing (so the search already avoids the height restrictions the map has tagged), then measures that corridor. Give `origin`, `destination` and `height_m`; optional `width_m` asks the corridor-width axis too, and optional `margin_m` adds your operating margin to the vehicle before the verdict. Returns `pass`, `fail`, `indeterminate` or `no_verdict` with ","inputSchema":{"type":"object","$defs":{"LatLon":{"anyOf":[{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number","format":"double","description":"Latitude in decimal degrees (−90 to 90)."},"lon":{"type":"number","format":"double","description":"Longitude in decimal degrees (−180 to 180)."}}},{"type":"array","items":{"type":"number","format":"double"},"maxItems":2,"minItems":2,"description":"GeoJSON position [lon, lat]: longitude FIRST."}],"description":"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["origin","destination","height_m"],"properties":{"origin":{"$ref":"#/$defs/LatLon","description":"Route origin."},"width_m":{"type":["number","null"],"format":"double","description":"Vehicle width in metres. Supplying it asks the width axis as well as\nthe height axis; the width answer is reported separately and is\nnever a headroom."},"height_m":{"type":"number","format":"double","description":"Vehicle height in metres. Required: there is no default vehicle,\nbecause a default vehicle is how somebody gets an answer about a\nlorry that is not theirs."},"margin_m":{"type":["number","null"],"format":"double","description":"Operating margin in metres, added to the height before the verdict\nis decided (default 0). Your compliance policy, not ours: the\nmeasured figure and the safe bound are both reported whatever you\nset here, and the margin is echoed back. It is applied to the\nmeasurement, not to the routing step, where the map's own posted\nheights already carry a margin of their own."},"destination":{"$ref":"#/$defs/LatLon","description":"Route destination."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":657,"tokensAfter":657},{"name":"check_style_contrast","fixed":{"name":"check_style_contrast","description":"Audit a map style's colour contrast against WCAG 2.1 (4.5:1 for label text, 3:1 for graphics like the route line), across both the light and dark palette variants. Pass a hosted `style_id` OR an inline `theme` document (as accepted by create_style). Advisory: failing pairs list the palette slots to adjust with set_palette; publishing is never blocked on contrast.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"theme":{"description":"…or an inline theme document (as accepted by `create_style`).\nExactly one of `style_id`/`theme` must be given.","type":"string"},"style_id":{"type":["string","null"],"description":"Hosted style id whose latest theme should be checked…"}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"schema","detail":"Added \"type\":\"string\" to untyped parameters: theme. Change to number/boolean/array where that's what you accept.","verify":true},{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":212,"tokensAfter":217},{"name":"create_style","fixed":{"name":"create_style","description":"Create a hosted map style. Provide a name, optionally a named `base` to start from (light, dark, streets, midnight, navigator-day, navigator-night, fleet, outdoor, dataviz, backdrop, print - call list_style_layers for what each one is for), and optionally a theme document ({base: \"light\"|\"dark\", palette: {slot: colour}, layers: {layer_id: overrides}}). The named base is laid down first and the theme document is merged over it, so \"streets with darker water\" is one call; with neither, the style s","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["name"],"properties":{"base":{"type":["string","null"],"description":"Optional named base to start from, e.g. \"streets\", \"midnight\",\n\"navigator-night\", \"fleet\". Call `list_style_layers` for the\ncatalogue, including which bases expect an overlay of their own. The\nbase's whole document is laid down first and `theme` is merged over\nit, so a base plus two palette entries is a complete style. Omitted,\nthe style starts from the default light theme as it always did."},"name":{"type":"string","description":"Human-readable style name; its kebab-case slug seeds the style id."},"theme":{"description":"Optional theme document (palette/layer overrides). Merged over\n`base` when one is given; on its own, it replaces the default theme\noutright.","type":"string"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"schema","detail":"Added \"type\":\"string\" to untyped parameters: theme. Change to number/boolean/array where that's what you accept.","verify":true},{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":390,"tokensAfter":395},{"name":"get_job","fixed":{"name":"get_job","description":"Read an asynchronous job submitted with `submit_optimise_job`: its status, and once it has finished, its result inline, exactly the body the synchronous tool would have returned. Status is `queued`, `running`, `succeeded` or `failed`; the answer's `terminal` field says whether the job will ever leave the status it is in, so poll while that is false. POLLING IS FREE: the gateway meters the submission and not the reads, deliberately, because a poll that costs quota is a poll a caller rations, and ","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["id"],"properties":{"id":{"type":"string","description":"The job id returned by `submit_optimise_job`."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":207,"tokensAfter":207},{"name":"get_style","fixed":{"name":"get_style","description":"Fetch a hosted style's latest theme document (the editable source) and the URL of its latest compiled MapLibre style. Use the theme to inspect current palette and layer overrides before editing.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["style_id"],"properties":{"style_id":{"type":"string","description":"Hosted style id, e.g. \"midnight-fleet-a1b2c3\"."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":126,"tokensAfter":126},{"name":"get_usage","fixed":{"name":"get_usage","description":"Check what your own API key has spent, so you can decide mid-task whether to keep going. Reading it is free: it costs no quota. Optional `from` and `to` (YYYY-MM-DD UTC, inclusive, at most 92 days apart) bound the report; omitted, it covers the current month to date. Returns `days` (per-day, per-endpoint), `totals` per endpoint over the range, `total_units`, plus `month_used_units` against `monthly_quota_units` and the prepaid `balance_millipence` (thousandths of a penny). Everything is counted ","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"to":{"type":["string","null"],"description":"Last day to report, `YYYY-MM-DD` (UTC) inclusive. Defaults to\ntoday."},"from":{"type":["string","null"],"description":"First day to report, `YYYY-MM-DD` (UTC) inclusive. Defaults to the\nfirst day of the current month. At most 92 days may separate\n`from` and `to`."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":266,"tokensAfter":266},{"name":"list_place_categories","fixed":{"name":"list_place_categories","description":"List the canonical place categories you can pass as `category` to `nearby_places` and `search_along_route` (and browse on with `geocode`). Each entry is a `category` token (the exact value to send, e.g. \"fuel\", \"charging_station\", \"hgv_parking\"), the `aliases` that colloquially name it (\"petrol station\", \"EV charger\", \"lorry park\"), and a one-line `description` of what it covers. Read this before guessing a category: a token that is not on this list matches nothing, and quietly returns an empty ","inputSchema":{"type":"object","properties":{}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":170,"tokensAfter":170},{"name":"list_style_layers","fixed":{"name":"list_style_layers","description":"List everything a MapMap style theme can style: the first-party named bases a style can start from (pass one as `create_style`'s `base`, or as the static-map API's `style=`), the named palette slots with their light/dark default colours, the skeleton layer ids (paint order) that `set_layer_paint` accepts, the OpenMapTiles source-layers extra layers may reference, the insertion slots (`bottom`, `middle`, `top`) an extra layer may name, and the rules for a theme's own `sources` (your data by https","inputSchema":{"type":"object","properties":{}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":165,"tokensAfter":165},{"name":"nearby_stops","fixed":{"name":"nearby_stops","description":"England bus and coach stops near a point, nearest first. Pass `lat` and `lon` (WGS84), optional `radius_m` (1 to 2,000, default 500) and `limit` (1 to 50, default 10). Each stop carries its NaPTAN ATCO code `id` (pass it to `next_departures`), `name`, `indicator` (e.g. \"Stop S\"), `locality`, position, `distance_m` and `bearing_deg` from the point, and `lines`, the line names the Bus Open Data timetables have calling there. Bus and coach only: rail, tram, metro and ferry stops are not included, a","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["lat","lon"],"properties":{"lat":{"type":"number","format":"double","description":"Latitude of the point, WGS84 degrees."},"lon":{"type":"number","format":"double","description":"Longitude of the point, WGS84 degrees."},"limit":{"type":["integer","null"],"format":"uint8","maximum":255,"minimum":0,"description":"Most stops to return, 1 to 50 (default 10), nearest first."},"radius_m":{"type":["integer","null"],"format":"uint32","minimum":0,"description":"Search radius in metres, 1 to 2,000 (default 500)."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":321,"tokensAfter":321},{"name":"order_stops","fixed":{"name":"order_stops","description":"Put a single run's stops in the best visiting order (\"order my errands\"). Provide `start` {lat, lon} and `stops` (1-100 entries of {location, label?, service_s?}); optionally an `end` destination or `round_trip`: true to return to the start. Costing \"auto\" = car, \"truck\" = lorry (pass `truck` as in `route` for a truck-legal order). Returns the stops in visit order with arrival offsets in seconds, plus total duration and distance.","inputSchema":{"type":"object","$defs":{"LatLon":{"anyOf":[{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number","format":"double","description":"Latitude in decimal degrees (−90 to 90)."},"lon":{"type":"number","format":"double","description":"Longitude in decimal degrees (−180 to 180)."}}},{"type":"array","items":{"type":"number","format":"double"},"maxItems":2,"minItems":2,"description":"GeoJSON position [lon, lat]: longitude FIRST."}],"description":"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server."},"TruckSpec":{"type":"object","properties":{"hazmat":{"type":"boolean","default":false,"description":"Whether the vehicle carries dangerous goods (ADR). Defaults to\nfalse."},"width_m":{"type":["number","null"],"format":"double","description":"Vehicle width in metres."},"height_m":{"type":["number","null"],"format":"double","description":"Vehicle height in metres."},"length_m":{"type":["number","null"],"format":"double","description":"Vehicle length in metres."},"tunnel_code":{"type":["string","null"],"description":"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."},"gross_weight_t":{"type":["number","null"],"format":"double","description":"Gross combination weight in metric tonnes."}},"description":"Truck profile for routing: physical dimensions plus the ADR\ndangerous-goods declaration. Omitted dimensions default to the EU\nmaximum authorised dimensions of Council Directive 96/53/EC (4.0 m\nheight, 2.55 m width, 16.5 m length, 40 t gross weight)."},"CostingKind":{"oneOf":[{"type":"string","const":"auto","description":"Standard car costing."},{"type":"string","const":"truck","description":"Truck costing; honours dimensional limits and, when a `truck`\nprofile is supplied, ADR dangerous-goods restrictions."},{"type":"string","const":"bicycle","description":"Bicycle costing; tune it with a `bicycle` options object."},{"type":"string","const":"pedestrian","description":"Pedestrian (walking) costing; tune it with a `pedestrian` options\nobject (lit streets, wheelchair/blind, hiking difficulty)."},{"type":"string","const":"motor_scooter","description":"Motor scooter (moped) costing: like auto but prefers lower-speed\nroads and may use ways closed to larger motor vehicles."}],"description":"Costing models exposed by the MCP tools (a deliberate subset of the\nValhalla costing list), serialised in snake_case exactly as Valhalla\nnames them."},"OrderStopSpec":{"type":"object","required":["location"],"properties":{"label":{"type":["string","null"],"description":"Human-readable label echoed back in the ordered plan\n(e.g. \"chemist\" or \"site B\")."},"location":{"$ref":"#/$defs/LatLon","description":"The stop's location."},"service_s":{"type":["integer","null"],"format":"uint32","minimum":0,"description":"On-site time in seconds (waiting, loading, shopping)."}},"description":"One errand stop of an `order_stops` request."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["start","stops"],"properties":{"end":{"anyOf":[{"$ref":"#/$defs/LatLon"},{"type":"null"}],"description":"Optional fixed final destination. Mutually exclusive with\n`round_trip`; omitted (and not a round trip), the run ends at\nwhichever stop the solver visits last."},"start":{"$ref":"#/$defs/LatLon","description":"Where the run starts."},"stops":{"type":"array","items":{"$ref":"#/$defs/OrderStopSpec"},"description":"The stops to put in the best visiting order (1–100)."},"truck":{"anyOf":[{"$ref":"#/$defs/TruckSpec"},{"type":"null"}],"description":"Truck profile (dimensions + ADR declaration); requires costing\n\"truck\". The travel-time matrix then respects dimensional and\ndangerous-goods restrictions."},"costing":{"$ref":"#/$defs/CostingKind","default":"auto","description":"Costing model: \"auto\" (default) or \"truck\"."},"round_trip":{"type":"boolean","default":false,"description":"Return to `start` after the last stop (default false)."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":1317,"tokensAfter":1317},{"name":"places_in_view","fixed":{"name":"places_in_view","description":"What is over THERE: given a position and the direction the user is facing, the places inside that cone, and whether the ground and the buildings in between let them actually be seen. Use this for \"what is that over there\", \"is there a pub in that direction\", \"what am I looking at\". Use `nearby_places` instead when the question is about what is NEAR a point rather than what is in a direction. Provide `lat`, `lon`, `bearing_deg` (degrees CLOCKWISE FROM TRUE NORTH: 0 north, 90 east, 180 south, 270 ","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["lat","lon","bearing_deg"],"properties":{"lat":{"type":"number","format":"double","description":"Latitude of the observer in decimal degrees (−90 to 90)."},"lon":{"type":"number","format":"double","description":"Longitude of the observer in decimal degrees (−180 to 180)."},"name":{"type":["string","null"],"description":"A place name or brand to look for. At least one of `category` and\n`name` is required."},"limit":{"type":["integer","null"],"format":"uint32","minimum":0,"description":"Maximum number of results (1–25, default 5)."},"fov_deg":{"type":["number","null"],"format":"double","description":"Full width in degrees of the cone centred on `bearing_deg` (1–360,\ndefault 60, so 30 degrees either side). The FULL width, not the\nhalf angle."},"category":{"type":["string","null"],"description":"The kind of place to look for, from the same vocabulary\n`nearby_places` uses (\"cafe\", \"pub\", \"fuel\", \"charging_station\" …).\nUse \"building\" to ask what a named building over there is. At\nleast one of `category` and `name` is required."},"radius_m":{"type":["integer","null"],"format":"uint32","minimum":0,"description":"Maximum straight-line range in metres (1–5000, default 1000)."},"bearing_deg":{"type":"number","format":"double","description":"Which way the observer is facing, in degrees **clockwise from true\nnorth** (0 = north, 90 = east, 180 = south, 270 = west). Required:\nthis tool answers \"what is over there\", and \"there\" has to point\nsomewhere."},"eye_height_m":{"type":["number","null"],"format":"double","description":"Height of the observer's eye above the ground in metres (0–500,\ndefault 1.6, a standing adult). A driver's eye is nearer 1.2 m."},"visible_only":{"type":["boolean","null"],"description":"When true, return only places whose visibility verdict is `clear`.\nDefault false, which returns everything in the cone WITH its\nverdict, usually the better answer, because \"it is there but you\ncannot see it from here\" is worth saying."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":734,"tokensAfter":734},{"name":"search_along_route","fixed":{"name":"search_along_route","description":"Find places (POIs) along a route with the REAL extra travel time of stopping at each, never a straight-line guess. Provide `origin` + `destination` (a route is computed) or an existing route's `geometry_polyline6`, plus a free-text `query` (\"coffee\", \"EV charger\", \"truck stop\") and `max_detour_minutes` (default 10). For a category intent (\"fuel\", \"EV charger\", \"coffee\") pass `category` instead of relying on words alone: it takes the same vocabulary as `nearby_places` (lowercased OSM tag values s","inputSchema":{"type":"object","$defs":{"LatLon":{"anyOf":[{"type":"object","required":["lat","lon"],"properties":{"lat":{"type":"number","format":"double","description":"Latitude in decimal degrees (−90 to 90)."},"lon":{"type":"number","format":"double","description":"Longitude in decimal degrees (−180 to 180)."}}},{"type":"array","items":{"type":"number","format":"double"},"maxItems":2,"minItems":2,"description":"GeoJSON position [lon, lat]: longitude FIRST."}],"description":"A WGS84 coordinate in decimal degrees: a {lat, lon} object (preferred), or a GeoJSON [lon, lat] array with LONGITUDE FIRST, the same order as every polygon field on this server."},"TruckSpec":{"type":"object","properties":{"hazmat":{"type":"boolean","default":false,"description":"Whether the vehicle carries dangerous goods (ADR). Defaults to\nfalse."},"width_m":{"type":["number","null"],"format":"double","description":"Vehicle width in metres."},"height_m":{"type":["number","null"],"format":"double","description":"Vehicle height in metres."},"length_m":{"type":["number","null"],"format":"double","description":"Vehicle length in metres."},"tunnel_code":{"type":["string","null"],"description":"ADR 8.6.4 tunnel restriction code of the load, e.g. \"B\", \"C5000D\",\n\"B/D\", or \"(-)\"/\"none\" for explicitly unrestricted. Leave unset if\nunknown: a hazmat load without a code is conservatively treated as\ncode B (allowed only through category-A tunnels)."},"gross_weight_t":{"type":["number","null"],"format":"double","description":"Gross combination weight in metric tonnes."}},"description":"Truck profile for routing: physical dimensions plus the ADR\ndangerous-goods declaration. Omitted dimensions default to the EU\nmaximum authorised dimensions of Council Directive 96/53/EC (4.0 m\nheight, 2.55 m width, 16.5 m length, 40 t gross weight)."},"CostingKind":{"oneOf":[{"type":"string","const":"auto","description":"Standard car costing."},{"type":"string","const":"truck","description":"Truck costing; honours dimensional limits and, when a `truck`\nprofile is supplied, ADR dangerous-goods restrictions."},{"type":"string","const":"bicycle","description":"Bicycle costing; tune it with a `bicycle` options object."},{"type":"string","const":"pedestrian","description":"Pedestrian (walking) costing; tune it with a `pedestrian` options\nobject (lit streets, wheelchair/blind, hiking difficulty)."},{"type":"string","const":"motor_scooter","description":"Motor scooter (moped) costing: like auto but prefers lower-speed\nroads and may use ways closed to larger motor vehicles."}],"description":"Costing models exposed by the MCP tools (a deliberate subset of the\nValhalla costing list), serialised in snake_case exactly as Valhalla\nnames them."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["query"],"properties":{"query":{"type":"string","description":"Free-text POI query, e.g. \"coffee\", \"EV charger\", \"truck stop\"."},"truck":{"anyOf":[{"$ref":"#/$defs/TruckSpec"},{"type":"null"}],"description":"Truck profile (dimensions + ADR declaration). Requires costing\n\"truck\"; the detours then respect dimensional/ADR restrictions."},"origin":{"anyOf":[{"$ref":"#/$defs/LatLon"},{"type":"null"}],"description":"Route origin (with `destination`, when no geometry is given)."},"costing":{"$ref":"#/$defs/CostingKind","default":"auto","description":"Costing model for the route and detour matrix: \"auto\" (default),\n\"truck\", \"bicycle\", \"pedestrian\" or \"motor_scooter\"."},"category":{"type":["string","null"],"description":"Explicit place category (\"fuel\", \"cafe\", \"charging_station\", same\nvocabulary as nearby_places). Colloquial phrases are normalised\nserver-side; prefer this over query for category intents."},"destination":{"anyOf":[{"$ref":"#/$defs/LatLon"},{"type":"null"}],"description":"Route destination."},"max_results":{"type":["integer","null"],"format":"uint32","minimum":0,"description":"Maximum results (default 5, at most 25)."},"geometry_polyline6":{"type":["string","null"],"description":"An existing route geometry as an encoded polyline6 (the `route`\ntool's `geometry_polyline6`). Provide either this or `origin` +\n`destination`, not both."},"max_detour_minutes":{"type":["number","null"],"format":"double","description":"Largest acceptable detour in minutes (default 10, at most 120)."}},"additionalProperties":false},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":1373,"tokensAfter":1373},{"name":"set_layer_paint","fixed":{"name":"set_layer_paint","description":"Set one MapLibre paint property on one skeleton layer of a hosted style (e.g. layer_id \"road-major\", property \"line-width\", value 4 or an expression array) and publish the result as a new immutable style version. Layer ids come from list_style_layers. Returns the new version and style URL.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["style_id","layer_id","property","value"],"properties":{"value":{"description":"The paint value (any MapLibre-valid JSON: number, colour string or\nexpression array).","type":"string"},"layer_id":{"type":"string","description":"Skeleton layer id, e.g. \"road-major\". Call `list_style_layers`\nfor the accepted ids."},"property":{"type":"string","description":"MapLibre paint property name, e.g. \"line-width\" or \"fill-color\"."},"style_id":{"type":"string","description":"Hosted style id."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"schema","detail":"Added \"type\":\"string\" to untyped parameters: value. Change to number/boolean/array where that's what you accept.","verify":true},{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":255,"tokensAfter":260},{"name":"set_palette","fixed":{"name":"set_palette","description":"Recolour one or more palette slots of a hosted style (e.g. {\"water\": \"#0b2038\", \"roadMajor\": \"#8a6d3b\"}) and publish the result as a new immutable style version. Slot names come from list_style_layers; colours are CSS (#rgb/#rrggbb/#rrggbbaa/rgb()/hsl()). Returns the new version and style URL.","inputSchema":{"type":"object","$schema":"https://json-schema.org/draft/2020-12/schema","required":["style_id","colours"],"properties":{"colours":{"type":"object","description":"Palette overrides: slot name → CSS colour (e.g.\n{\"water\": \"#0b2038\"}). Call `list_style_layers` for the slot names.","additionalProperties":{"type":"string"}},"style_id":{"type":"string","description":"Hosted style id."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":208,"tokensAfter":208},{"name":"set_temporary_closure","fixed":{"name":"set_temporary_closure","description":"OPERATOR WRITE, ADMIN ONLY. Asserts a short-lived closure (`assert: {kind: closed}`) or speed (`{kind: speed_override, speed_kph}`, 1 to 120) on named OSM `way_ids` (1 to 20) and `direction` (forward, backward or both, default both), for `ttl_secs` (60 to 86400), with a `reason` and an optional `evidence_url`. The record expires on its own, ranks below official closures and is logged with the reason. NEVER CALL THIS WITHOUT A PERSON'S EXPLICIT APPROVAL OF THIS EXACT CLOSURE IN THIS CONVERSATION:","inputSchema":{"type":"object","$defs":{"Direction":{"oneOf":[{"type":"string","const":"forward","description":"Along the way's node order."},{"type":"string","const":"backward","description":"Against it."},{"type":"string","const":"both","description":"Both carriageways."}],"description":"Carriageway of a way, spelled as the artefact spells it. A serde\ntwin of [`WayDirection`], which deliberately carries no serde."},"ClosureAssertion":{"oneOf":[{"type":"object","required":["kind"],"properties":{"kind":{"type":"string","const":"closed"}},"description":"Hard exclusion."},{"type":"object","required":["kind","speed_kph"],"properties":{"kind":{"type":"string","const":"speed_override"},"speed_kph":{"type":"integer","format":"uint32","minimum":0,"description":"The speed."}},"description":"A speed, km/h."}],"description":"What a temporary closure asserts."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["way_ids","assert","ttl_secs","reason"],"properties":{"assert":{"$ref":"#/$defs/ClosureAssertion","description":"`closed` or a speed in km/h (1..=120)."},"reason":{"type":"string","description":"Why, for the audit log and the incidents endpoint note."},"way_ids":{"type":"array","items":{"type":"integer","format":"uint64","minimum":0},"description":"OSM way ids to assert on; at most 20."},"ttl_secs":{"type":"integer","format":"uint64","minimum":0,"description":"Lifetime, seconds, 60..=86400."},"direction":{"$ref":"#/$defs/Direction","default":"both","description":"Carriageway, default `both`."},"evidence_url":{"type":["string","null"],"description":"Evidence link, if any."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":602,"tokensAfter":602},{"name":"submit_integration_retro","fixed":{"name":"submit_integration_retro","description":"Send MapMap a structured integration retro (problems, gotchas, wins, docs gaps). Call at most once, after your MapMap integration works or you stop trying, and only if the developer has approved sending feedback to MapMap. Sends ONLY the structured fields in this schema to MapMap: there is no field for a transcript, a prompt, source code, file contents or coordinates. The free-text fields are short and capped, but they are still free text: do NOT paste code, credentials, customer names or person","inputSchema":{"type":"object","$defs":{"RetroProblemArea":{"oneOf":[{"type":"string","const":"sdk","description":"The mobile/web SDKs."},{"type":"string","const":"api","description":"The hosted HTTP API."},{"type":"string","const":"mcp","description":"The MCP tool surface."},{"type":"string","const":"docs","description":"Documentation."},{"type":"string","const":"billing","description":"Billing, keys or quotas."},{"type":"string","const":"self-host","description":"Self-hosted deployment."},{"type":"string","const":"other","description":"Anything else."}],"description":"The platform area an integration problem belongs to (mirrors the\ngateway's `POST /v1/feedback` schema)."},"RetroProblemInput":{"type":"object","required":["area","description","workaround_found"],"properties":{"area":{"$ref":"#/$defs/RetroProblemArea","description":"Which part of the platform the problem was in."},"description":{"type":"string","description":"What went wrong (at most 1000 bytes)."},"workaround_found":{"type":"boolean","description":"Whether a workaround was found."}},"description":"One problem hit during the integration."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["what_built"],"properties":{"wins":{"type":"array","items":{"type":"string"},"default":[],"description":"What went well (at most 20 entries × 500 bytes)."},"gotchas":{"type":"array","items":{"type":"string"},"default":[],"description":"Surprises/traps worth documenting (at most 20 entries × 500 bytes)."},"problems":{"type":"array","items":{"$ref":"#/$defs/RetroProblemInput"},"default":[],"description":"Problems hit during the integration (at most 20)."},"docs_gaps":{"type":"array","items":{"type":"string"},"default":[],"description":"Documentation gaps hit (at most 20 entries × 500 bytes)."},"agent_name":{"type":["string","null"],"description":"The submitting agent's name, e.g. \"Claude Code\" (at most 100\nbytes)."},"what_built":{"type":"string","description":"What was built with MapMap, in one or two sentences (required, at\nmost 500 bytes)."},"sdk_version":{"type":["string","null"],"description":"MapMap SDK version integrated against, when known (at most 50\nbytes)."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":760,"tokensAfter":760},{"name":"submit_optimise_job","fixed":{"name":"submit_optimise_job","description":"Submit a problem too large to solve inside one request to the asynchronous lane, and get a job id back. Set `kind` to \"optimise\", \"replan\" or \"matrix\", and pass `problem` in EXACTLY the shape the matching synchronous tool takes, `optimise_routes` input, `replan_routes` input, or `matrix` input. Moving a working synchronous call onto this lane changes nothing but which tool you call it with. A field that tool's input does not have is REFUSED by name rather than dropped: the HTTP API accepts some ","inputSchema":{"type":"object","$defs":{"JobKind":{"oneOf":[{"type":"string","const":"optimise","description":"A fleet optimisation, the `optimise_routes` problem, at ten times\nthe synchronous location cap."},{"type":"string","const":"replan","description":"A mid-shift re-plan, the `replan_routes` problem, counted on the\nremaining work."},{"type":"string","const":"matrix","description":"A many-to-many time/distance matrix, the `matrix` problem, at four\ntimes the synchronous element cap."}],"description":"Which asynchronous problem is being submitted."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["kind","problem"],"properties":{"kind":{"$ref":"#/$defs/JobKind","description":"Which problem this is. It selects both the body shape below and the\nceiling the submission is judged against."},"problem":{"description":"The problem itself, in exactly the shape the synchronous tool takes\n, `optimise_routes` input for `optimise`, `replan_routes` input for\n`replan`, `matrix` input for `matrix`. Moving a working synchronous\ncall onto this lane changes nothing but the tool you call it with.","type":"string"},"webhook_url":{"type":["string","null"],"description":"Optional HTTPS URL to POST a signed `{job_id, kind, status,\nresult_url}` notification to when the job finishes. The RESULT is\nnever pushed, the notification says where to fetch it. Requires a\nwebhook signing secret on the key; without one the submission is\nrefused rather than delivered unsigned. An agent that can poll does\nnot need this: polling with `get_job` is free."}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"schema","detail":"Added \"type\":\"string\" to untyped parameters: problem. Change to number/boolean/array where that's what you accept.","verify":true},{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":588,"tokensAfter":593},{"name":"validate_geodata","fixed":{"name":"validate_geodata","description":"Check whether a dataset's DECLARED coordinate reference system actually describes its own coordinates, before you draw it on a map. Catches the failures that are otherwise silent: swapped lat/lon axes, degrees labelled as metres, and Web Mercator or another projection mislabelled with a UTM or national-grid code. Pass the declared CRS (e.g. \"EPSG:4326\") and a sample of the raw coordinates as {x, y} in the dataset's OWN units, deliberately not named lon/lat, because whether they are degrees is th","inputSchema":{"type":"object","$defs":{"XY":{"type":"object","required":["x","y"],"properties":{"x":{"type":"number","format":"double"},"y":{"type":"number","format":"double"}},"description":"One coordinate from the dataset, in the dataset's own units, NOT\nnecessarily degrees. Named `x`/`y` rather than `lon`/`lat` precisely\nbecause whether they are degrees is the thing in question."}},"$schema":"https://json-schema.org/draft/2020-12/schema","required":["declared_crs","coordinates"],"properties":{"coordinates":{"type":"array","items":{"$ref":"#/$defs/XY"},"description":"A sample of the dataset's coordinates. A few dozen is plenty; the\ncheck is about ranges and spans, not volume."},"declared_crs":{"type":"string","description":"The CRS the dataset claims, e.g. `\"EPSG:4326\"`, `\"EPSG:32610\"`,\n`\"EPSG:3857\"`, `\"EPSG:27700\"`."}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":388,"tokensAfter":388}],"toolsChanged":19,"tokensSaved":0,"todo":[],"note":"Deterministic fixes. Changes marked verify need a human look before shipping (renames, inferred annotations, inferred types, removed text). Parameter descriptions in `todo` need to be written by someone who knows the API."}