atlasfetch-mcp
MCP server for AtlasFetch — reverse geocode a coordinate to its country, region and municipality (ISO 3166 codes), the nearest street and house number, geocode South African addresses, match against your own geofences, and route around them.
npm · fingerprint ad4786b7ba276d157453fbce · repository · RSS
What changed
Changed 2026-10-21 11:54 UTC
6 descriptions rewritten.
--- pinned/add_boundary +++ observed/add_boundary { "annotations": { "destructiveHint": true, - "description": "Adds ONE polygon to an existing boundary set on this account, so that lookup_location\nreports when a point falls inside it — delivery zones, service areas, sales territories.\nEach call creates a new boundary: calling twice with the same name stores two.\n\nBefore calling: the set must already exist (create_boundary_set). A set matches nothing in\nlookups until it is switched on and granted to an API key in the dashboard at\nhttps://atlasfetch.xyz/dashboard, which this server cannot do.\n\ngeometry must be a single GeoJSON Polygon — not a MultiPolygon, Feature or\nFeatureCollection. Positions are [longitude, latitude]. Each ring needs at least 4\npositions and must be closed (last position equals the first); extra rings are holes.\nSelf-intersecting shapes are rejected. To store a MultiPolygon, add each part separately.\n\nPlan limits cap vertices per polygon (every position counts, including the closing one),\nproperties per boundary and boundaries per set; a limit hit is refused with a message naming\nit. WITHOUT YOUR OWN KEY, the shared demo key is on the Public plan: at most 5 positions per\npolygon (a closed quadrilateral), properties only category (zone, area, route, place,\nother), color (green, blue, red, yellow, purple, orange) and priority (low, medium, high),\nand one set shared with every demo user, where adding to a full set silently deletes its\noldest boundary. Never upload anything private with the demo key.\n\nReturns the stored boundary: id, set, name, properties, pointCount and createdAt.", + "description": "Adds ONE polygon to an existing boundary set on this account, so that lookup_location\nreports when a point falls inside it — delivery zones, service areas, sales territories.\nEach call creates a new boundary: calling twice with the same name stores two.\n\nBefore calling: the set must already exist (create_boundary_set). A set matches nothing in\nlookups until it is switched on and granted to an API key in the dashboard at\nhttps://atlasfetch.xyz/dashboard, which this server cannot do.\n\ngeometry must be a single GeoJSON Polygon — not a MultiPolygon, Feature or\nFeatureCollection. Positions are [longitude, latitude]. Each ring needs at least 4\npositions and must be closed (last position equals the first); extra rings are holes.\nSelf-intersecting shapes are rejected. To store a MultiPolygon, add each part separately.\n\nA polygon may have at most 50 points on EVERY plan, the closing one included; more is\nrefused, unbilled, with advice to simplify the shape or split it into several boundaries.\nPlan limits cap properties per boundary and boundaries per set. WITHOUT YOUR OWN KEY, the\nshared demo key is on the Public plan: properties only category (zone, area, route, place,\nother), color (green, blue, red, yellow, purple, orange) and priority (low, medium, high),\nand one set shared with every demo user, where adding to a full set silently deletes its\noldest boundary. Never upload anything private with the demo key.\n\nReturns the stored boundary: id, set, name, properties, pointCount and createdAt.", "execution": { "taskSupport": "forbidden" },
--- pinned/create_boundary_set +++ observed/create_boundary_set { "annotations": { "destructiveHint": false, - "description": "Creates an empty named set to hold your own polygons: delivery zones, service areas,\nsales territories.\n\nIMPORTANT, and not a bug: a new set is created unavailable and granted to no key, so it\nmatches nothing until both are changed. Granting is addressed by API key id, and the only\nendpoint that lists key ids needs a browser session — which this server does not have. So\nthis tool can create the set and add boundaries to it, but CANNOT make it queryable. Tell\nthe user to finish that at https://atlasfetch.xyz/dashboard.", + "description": "Creates an empty named set to hold your own polygons: delivery zones, service areas,\nsales territories.\n\nIMPORTANT, and not a bug: a new set is created unavailable and granted to no key, so it\nmatches nothing until both are changed. Granting is addressed by API key id, and nothing\nthis server can call tells it its own key's id. So this tool can create the set and add\nboundaries to it, but the FIRST grant has to happen in the dashboard: tell the user to\nswitch the set on and grant it to the key this server uses, at\nhttps://atlasfetch.xyz/dashboard.", "execution": { "taskSupport": "forbidden" },
--- pinned/geocode_address +++ observed/geocode_address { "annotations": { "openWorldHint": true, - "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"intersection\"\nmeans a street corner (\"Cnr Main Rd and Belmont Rd\", \"Bree & Strand Streets\"), at the\npoint where the two meet, with the second street in matched.crossStreet; \"site\" means a\nnamed site — a shopping centre, office park, complex or estate, hospital, school, airport\nor hotel — at a point inside it, named in matched.site; \"street\" means the right street\nbut NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address, interpolated, intersection or site, not ambiguous, confidence 0.5 or more:\n dispatch. For a site, pass on the unit or shop number from the original address\n (\"Shop 12\") — the answer does not include it, and the driver needs it.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well, or the street was a near-miss spelling with no house\nnumber to confirm it. result null means nothing trustworthy was found, and that still\ncosts the lookup.\n\nSome addresses name something that cannot be placed: an erf, stand, plot or farm portion\n(land parcels — there is no cadastre), a township stand, a PO box or private bag. Those\nparts come back in unmatched and the answer is the place named, at locality: ask the\ncustomer for a street address.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", + "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"intersection\"\nmeans a street corner (\"Cnr Main Rd and Belmont Rd\", \"Bree & Strand Streets\"), at the\npoint where the two meet, with the second street in matched.crossStreet; \"site\" means a\nnamed site — a shopping centre, office park, complex or estate, hospital, school, airport\nor hotel — at a point inside it, named in matched.site; \"street\" means the right street\nbut NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address, interpolated, intersection or site, not ambiguous, confidence 0.5 or more:\n dispatch. For a site, pass on the unit or shop number from the original address\n (\"Shop 12\") — the answer does not include it, and the driver needs it.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nWhen the advice is to ask the customer, ASK — do not pick one. result.alternatives holds up\nto 4 other candidates the answer was chosen from, and the result line lists them with their\ndistance and direction from the first, because they often share a street name AND a town\n(five \"Long Street, Cape Town\"s). Put the first answer and those to the user. Free: still\none lookup.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well, or the street was a near-miss spelling with no house\nnumber to confirm it. result null means nothing trustworthy was found, and that still\ncosts the lookup.\n\nSome addresses name something that cannot be placed: an erf, stand, plot or farm portion\n(land parcels — there is no cadastre), a township stand, a PO box or private bag. Those\nparts come back in unmatched and the answer is the place named, at locality: ask the\ncustomer for a street address.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", "execution": { "taskSupport": "forbidden" },
--- pinned/get_route +++ observed/get_route { "annotations": { "openWorldHint": true, - "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less;\nX-Lookups-Remaining is always the truth). Everything it returns is included in that, so do\nnot call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless routeGeometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped.\n\nTRUCKS (Pro only): a truck over 9 t, or with no weightTonnes, is capped at 80 km/h, as South\nAfrican law caps goods vehicles; a lighter truck keeps car speeds. The vehicle’s height,\nwidth, length, weight, axle load and hazmat are checked against road limits where\nOpenStreetMap records them, which is not everywhere — a good start, not a legal clearance.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\nalternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", + "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less;\nX-Lookups-Remaining is always the truth). Everything it returns is included in that, so do\nnot call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless routeGeometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped. Along very\nmany exposure zones (over 1,000, or over 5 s to measure) exposure is skipped: it comes back\nempty with a note in errors, and the route is still answered and billed.\n\nTRUCKS (Pro only): a truck over 9 t, or with no weightTonnes, is capped at 80 km/h, as South\nAfrican law caps goods vehicles; a lighter truck keeps car speeds. The vehicle’s height,\nwidth, length, weight, axle load and hazmat are checked against road limits where\nOpenStreetMap records them, which is not everywhere — a good start, not a legal clearance.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\nalternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", "execution": { "taskSupport": "forbidden" },
--- pinned/list_boundary_sets +++ observed/list_boundary_sets { "annotations": { "openWorldHint": true, - "description": "Lists the boundary sets on this account with their boundary counts and the API keys (id and label) each is granted to. A set only matches during a lookup when it is available AND granted to the key making the call.", + "description": "Lists the boundary sets on this account with their boundary counts and the API keys (id and label) each is granted to. A set only matches during a lookup when it is available AND granted to the key making the call. On the shared demo key, grantedKeys is always empty.", "execution": { "taskSupport": "forbidden" },
--- pinned/update_boundary +++ observed/update_boundary { "annotations": { "destructiveHint": true, - "description": "Replace the shape of ONE existing boundary. Its id, name, properties and set stay as they\nare, so every lookup that matches it keeps returning the same properties.\n\nUse this to fix or move a zone. Do NOT delete it and add it again: that gives it a new id\nand loses the properties unless they are re-sent.\n\nName the boundary by set and name; this finds its id. If a set holds two boundaries with\nthat name, the answer lists their ids and asks for one. The new shape gets the same\nchecks as add_boundary, including the plan’s points-per-boundary cap (refused, unbilled).\nOnly boundaries on this account can be changed.", + "description": "Replace the shape of ONE existing boundary. Its id, name, properties and set stay as they\nare, so every lookup that matches it keeps returning the same properties.\n\nUse this to fix or move a zone. Do NOT delete it and add it again: that gives it a new id\nand loses the properties unless they are re-sent.\n\nName the boundary by set and name; this finds its id. If a set holds two boundaries with\nthat name, the answer lists their ids and asks for one. The new shape gets the same\nchecks as add_boundary, including the 50-point cap (refused, unbilled).\nOnly boundaries on this account can be changed.", "execution": { "taskSupport": "forbidden" },
Changed 2026-10-16 11:32 UTC
1 description rewritten.
--- pinned/get_route +++ observed/get_route { "annotations": { "openWorldHint": true, - "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less;\nX-Lookups-Remaining is always the truth). Everything it returns is included in that, so do\nnot call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless geometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\ntruck is Pro only; alternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", + "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less;\nX-Lookups-Remaining is always the truth). Everything it returns is included in that, so do\nnot call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless routeGeometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped.\n\nTRUCKS (Pro only): a truck over 9 t, or with no weightTonnes, is capped at 80 km/h, as South\nAfrican law caps goods vehicles; a lighter truck keeps car speeds. The vehicle’s height,\nwidth, length, weight, axle load and hazmat are checked against road limits where\nOpenStreetMap records them, which is not everywhere — a good start, not a legal clearance.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\nalternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", "execution": { "taskSupport": "forbidden" }, - "description": "The route line. Defaults to none. Ask for polyline6 or geojson only when something will draw it: it is long, and an assistant cannot read it usefully.", + "description": "DEPRECATED: use routeGeometry, which takes the same values. Removed in 1.0.", "enum": [ "none", "polyline6", - "description": "Travel mode. Defaults to car. \"truck\" is Pro only and obeys vehicle limits.", + "description": "Travel mode. Defaults to car. \"truck\" is Pro only; see TRUCKS above.", "enum": [ "car", "bike", + "routeGeometry": { + "description": "The route line. Defaults to none. Ask for polyline6 or geojson only when something will draw it: it is long, and an assistant cannot read it usefully.", + "enum": [ + "none", + "polyline6", + "geojson" + ], + "type": "string" + }, "steps": { "description": "Turn-by-turn steps per leg. Defaults to true here; set false for distance and time only.", "type": "boolean" - "description": "Truck dimensions and load. Only with mode \"truck\"; rejected otherwise.", + "description": "Truck dimensions and load. Only with mode \"truck\"; rejected otherwise. Give weightTonnes: without it the truck is treated as heavy (over 9 t) and capped at 80 km/h.", "properties": { "axleLoadTonnes": { "type": "number"
Changed 2026-10-15 11:32 UTC
1 description rewritten.
--- pinned/geocode_address +++ observed/geocode_address { "annotations": { "openWorldHint": true, - "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"intersection\"\nmeans a street corner (\"Cnr Main Rd and Belmont Rd\", \"Bree & Strand Streets\"), at the\npoint where the two meet, with the second street in matched.crossStreet; \"street\" means\nthe right street but NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address, interpolated or intersection, not ambiguous, confidence 0.5 or more: dispatch.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well, or the street was a near-miss spelling with no house\nnumber to confirm it. result null means nothing trustworthy was found, and that still\ncosts the lookup.\n\nSome addresses name something that cannot be placed: an erf, stand, plot or farm portion\n(land parcels — there is no cadastre), a township stand, a PO box or private bag. Those\nparts come back in unmatched and the answer is the place named, at locality: ask the\ncustomer for a street address.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", + "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"intersection\"\nmeans a street corner (\"Cnr Main Rd and Belmont Rd\", \"Bree & Strand Streets\"), at the\npoint where the two meet, with the second street in matched.crossStreet; \"site\" means a\nnamed site — a shopping centre, office park, complex or estate, hospital, school, airport\nor hotel — at a point inside it, named in matched.site; \"street\" means the right street\nbut NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address, interpolated, intersection or site, not ambiguous, confidence 0.5 or more:\n dispatch. For a site, pass on the unit or shop number from the original address\n (\"Shop 12\") — the answer does not include it, and the driver needs it.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well, or the street was a near-miss spelling with no house\nnumber to confirm it. result null means nothing trustworthy was found, and that still\ncosts the lookup.\n\nSome addresses name something that cannot be placed: an erf, stand, plot or farm portion\n(land parcels — there is no cadastre), a township stand, a PO box or private bag. Those\nparts come back in unmatched and the answer is the place named, at locality: ask the\ncustomer for a street address.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", "execution": { "taskSupport": "forbidden" },
Changed 2026-10-14 12:01 UTC
1 description rewritten.
--- pinned/geocode_address +++ observed/geocode_address { "annotations": { "openWorldHint": true, - "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"street\" means the\nright street but NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address or interpolated, not ambiguous, confidence 0.5 or more: dispatch.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well. result null means nothing trustworthy was found, and\nthat still costs the lookup.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", + "description": "Turn ONE address into a point, with an honest account of how much of it was found. Built\nfor deliveries. South Africa today; more countries as their data loads. 1 lookup per\naddress, found or not.\n\nSend either q (one line) or address (housenumber, street, suburb, city, postcode, unit) —\nnever both. If the address is already split, send it split: it matches better.\n\nREAD precision BEFORE using the point. \"address\" means the house was found;\n\"interpolated\" means it was estimated between the numbers either side; \"intersection\"\nmeans a street corner (\"Cnr Main Rd and Belmont Rd\", \"Bree & Strand Streets\"), at the\npoint where the two meet, with the second street in matched.crossStreet; \"street\" means\nthe right street but NOT the house; \"locality\" means only the suburb or town. NEVER present\na street- or locality-level point as a door: a driver sent there will be at the wrong\nhouse. In South Africa most answers are street-level, because OpenStreetMap has house\nnumbers on about 13% of street names — that is the data being honest, not a failure.\n\nWhat to do with an answer — the result line says which applies:\n- address, interpolated or intersection, not ambiguous, confidence 0.5 or more: dispatch.\n- street: ask the recipient for a pin or a landmark.\n- ambiguous, or locality: ask the customer before dispatching.\nconfidence ranks answers; it is NOT a probability. ambiguous means a same-named street\nelsewhere scored about as well, or the street was a near-miss spelling with no house\nnumber to confirm it. result null means nothing trustworthy was found, and that still\ncosts the lookup.\n\nSome addresses name something that cannot be placed: an erf, stand, plot or farm portion\n(land parcels — there is no cadastre), a township stand, a PO box or private bag. Those\nparts come back in unmatched and the answer is the place named, at locality: ask the\ncustomer for a street address.\n\ncountry is a hard filter; region (ZA-WC, or \"Western Cape\") only ranks streets inside it\nfirst, so a wrong province does not lose the address. An uncovered country is refused,\nunbilled, with the list of covered countries in the message — that message is the live\ncoverage list; there is no other. sets and base answer \"which delivery zone is it in\" in\nthe same call, at no extra cost.\n\nOne address per call, deliberately. For a delivery list, call this once per row so the\nuser sees what is being spent; programs with thousands of rows should use the API’s\nPOST /geocode/batch directly. Not for: searching for a business or landmark by name,\nor a coordinate to an address (that is lookup_location with the street layer).", "execution": { "taskSupport": "forbidden" },
Changed 2026-10-13 14:19 UTC
2 descriptions rewritten, 2 tools added.
+ tool added: geocode_address
--- pinned/get_route +++ observed/get_route { "annotations": { "openWorldHint": true, - "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS, not one. Everything it returns is included in that, but it\nis ten times a lookup, so do not call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless geometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\ntruck is Pro only; alternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", + "description": "A driving, cycling, walking or truck route from the first location to the last, via any\nin between, with distance, duration and turn-by-turn steps.\n\nCOST: a route is 10 LOOKUPS on the standard plans, not one (a custom plan may charge less;\nX-Lookups-Remaining is always the truth). Everything it returns is included in that, so do\nnot call it in a loop to compare options without saying so.\n\nDurations are FREE-FLOW: the road network at its own speed limits, with NO live or\nhistorical traffic. Never present one as an arrival time in traffic — for that, say a\ntraffic-aware service (Google, Mapbox) is needed.\n\nThe route line is NOT returned unless geometry is set, because an encoded polyline is\nthousands of characters that no one reads. Ask for it only when something will draw it.\n\nLocations are SNAPPED to the nearest routable road, and locations[] in the response says\nhow far each one moved. A large snapDistanceMeters means the answer starts somewhere else\nthan asked — worth repeating to the user.\n\navoidSets and exposureSets name BOUNDARY SETS on the account (list_boundary_sets), not\nad-hoc shapes. avoid routes around every zone in those sets; exposure leaves the route\nalone and reports how far it ran inside each zone. A zone containing one of the locations\ncannot be avoided for that route: it is skipped and reported in avoid.skipped.\n\nLimits by plan: 2 locations and 1 alternative on the free plans, up to 25 and 2 on Pro;\ntruck is Pro only; alternatives need exactly 2 locations. Over a cap the answer is 403,\nand nothing is billed. A location with no road near it, or two places with no road\nbetween them, is 422 — and that one IS billed, because the route was attempted.\n\nNot for: distance matrices, isochrones or live traffic (none exist yet), and not for\nwhich-area-is-this questions — that is lookup_location, at one lookup.", "execution": { "taskSupport": "forbidden" },
--- pinned/lookup_location +++ observed/lookup_location { "annotations": { "openWorldHint": true, - "description": "Reverse geocode a coordinate to the administrative areas that contain it — country,\nregion (state or province) and municipality — as names plus ISO 3166 codes, optionally the\nnearest street, and matches from boundary sets the account has uploaded: all in one call.\n\nUse for: which country, region or municipality a point is in; which street a point is on\n(add \"street\" to base); geofence checks against your own polygons; tagging data with region\ncodes.\nDo NOT use for: forward geocoding or place search (an address to a coordinate), or\nfetching boundary geometry. For a route, a travel distance or a travel time between\npoints, use get_route instead — but note it costs 10 lookups to this one’s 1.\n\nCaveats worth repeating to the user: municipal is the finest unit AVAILABLE, not a\nconsistent kind of thing — Los Angeles returns a city, rural Kansas returns a county, so\ndo not assume it names a city. A layer that matched nothing comes back null. The errors\narray is always present: a boundary set that is unavailable or not granted to this key is\nskipped and reported there, while the call itself still succeeds.\n\nSTREETS (opt-in via base, worldwide). base.street is ALWAYS three\nanswers, for 5 m, 20 m and unlimited in that order,\neach with radiusMeters, streetNumber, streetName, postcode and distanceMeters. A numbered\naddress within the radius wins over a nearer street (for the unlimited entry the address\nmust still be within 20 m); otherwise the nearest named street; unnamed roads never answer.\nTwo different nulls: base.street === null means there is no street data for the point’s\ncountry, while an entry whose fields are null means nothing was within that radius —\nnever report them the same way. streetNumber and postcode are STRINGS (44A, 12-14, 0181),\nhouse numbers are rare outside well-mapped areas, and no street geometry is returned.\n\nOne call is one billed lookup however many layers, sets or grid codes it touches, and a\ncall that matches nothing still bills.", + "description": "Reverse geocode a coordinate to the administrative areas that contain it — country,\nregion (state or province) and municipality — as names plus ISO 3166 codes, optionally the\nnearest street, and matches from boundary sets the account has uploaded: all in one call.\n\nUse for: which country, region or municipality a point is in; which street a point is on\n(add \"street\" to base); geofence checks against your own polygons; tagging data with region\ncodes.\nFor the other direction, an address to a coordinate, use geocode_address. For a route,\na travel distance or a travel time, use get_route — 10 lookups on the standard plans to\nthis one’s 1. Do NOT use for place search by name or for fetching boundary geometry.\n\nCaveats worth repeating to the user: municipal is the finest unit AVAILABLE, not a\nconsistent kind of thing — Los Angeles returns a city, rural Kansas returns a county, so\ndo not assume it names a city. A layer that matched nothing comes back null. The errors\narray is always present: a boundary set that is unavailable or not granted to this key is\nskipped and reported there, while the call itself still succeeds.\n\nSTREETS (opt-in via base, worldwide). base.street is ALWAYS three\nanswers, for 5 m, 20 m and unlimited in that order,\neach with radiusMeters, streetNumber, streetName, postcode and distanceMeters. A numbered\naddress within the radius wins over a nearer street (for the unlimited entry the address\nmust still be within 20 m); otherwise the nearest named street; unnamed roads never answer.\nTwo different nulls: base.street === null means there is no street data for the point’s\ncountry, while an entry whose fields are null means nothing was within that radius —\nnever report them the same way. streetNumber and postcode are STRINGS (44A, 12-14, 0181),\nhouse numbers are rare outside well-mapped areas. Street geometry comes back only when\nstreetGeometry is set — leave it off unless something will draw the line.\n\nOne call is one billed lookup however many layers, sets or grid codes it touches, and a\ncall that matches nothing still bills.", "execution": { "taskSupport": "forbidden" }, + }, + "streetGeometry": { + "description": "Give each street answer the line of the street it names, trimmed to about 250 m either side of the point. Implies the street layer. Off by default, and leave it off unless something will draw it: a line is hundreds of characters nobody reads.", + "enum": [ + "polyline6", + "geojson" + ], + "type": "string" } }, "required": [
+ tool added: update_boundary
Changed 2026-10-10 12:43 UTC
1 description rewritten, 1 tool added.
+ tool added: get_route
--- pinned/lookup_location +++ observed/lookup_location { "annotations": { "openWorldHint": true, - "description": "Reverse geocode a coordinate to the administrative areas that contain it — country,\nregion (state or province) and municipality — as names plus ISO 3166 codes, optionally the\nnearest street, and matches from boundary sets the account has uploaded: all in one call.\n\nUse for: which country, region or municipality a point is in; which street a point is on\n(add \"street\" to base); geofence checks against your own polygons; tagging data with region\ncodes.\nDo NOT use for: forward geocoding or place search (an address to a coordinate), routing,\ndistances, or fetching boundary geometry.\n\nCaveats worth repeating to the user: municipal is the finest unit AVAILABLE, not a\nconsistent kind of thing — Los Angeles returns a city, rural Kansas returns a county, so\ndo not assume it names a city. A layer that matched nothing comes back null. The errors\narray is always present: a boundary set that is unavailable or not granted to this key is\nskipped and reported there, while the call itself still succeeds.\n\nSTREETS (opt-in via base, worldwide). base.street is ALWAYS three\nanswers, for 5 m, 20 m and unlimited in that order,\neach with radiusMeters, streetNumber, streetName, postcode and distanceMeters. A numbered\naddress within the radius wins over a nearer street (for the unlimited entry the address\nmust still be within 20 m); otherwise the nearest named street; unnamed roads never answer.\nTwo different nulls: base.street === null means there is no street data for the point’s\ncountry, while an entry whose fields are null means nothing was within that radius —\nnever report them the same way. streetNumber and postcode are STRINGS (44A, 12-14, 0181),\nhouse numbers are rare outside well-mapped areas, and no street geometry is returned.\n\nOne call is one billed lookup however many layers, sets or grid codes it touches, and a\ncall that matches nothing still bills.", + "description": "Reverse geocode a coordinate to the administrative areas that contain it — country,\nregion (state or province) and municipality — as names plus ISO 3166 codes, optionally the\nnearest street, and matches from boundary sets the account has uploaded: all in one call.\n\nUse for: which country, region or municipality a point is in; which street a point is on\n(add \"street\" to base); geofence checks against your own polygons; tagging data with region\ncodes.\nDo NOT use for: forward geocoding or place search (an address to a coordinate), or\nfetching boundary geometry. For a route, a travel distance or a travel time between\npoints, use get_route instead — but note it costs 10 lookups to this one’s 1.\n\nCaveats worth repeating to the user: municipal is the finest unit AVAILABLE, not a\nconsistent kind of thing — Los Angeles returns a city, rural Kansas returns a county, so\ndo not assume it names a city. A layer that matched nothing comes back null. The errors\narray is always present: a boundary set that is unavailable or not granted to this key is\nskipped and reported there, while the call itself still succeeds.\n\nSTREETS (opt-in via base, worldwide). base.street is ALWAYS three\nanswers, for 5 m, 20 m and unlimited in that order,\neach with radiusMeters, streetNumber, streetName, postcode and distanceMeters. A numbered\naddress within the radius wins over a nearer street (for the unlimited entry the address\nmust still be within 20 m); otherwise the nearest named street; unnamed roads never answer.\nTwo different nulls: base.street === null means there is no street data for the point’s\ncountry, while an entry whose fields are null means nothing was within that radius —\nnever report them the same way. streetNumber and postcode are STRINGS (44A, 12-14, 0181),\nhouse numbers are rare outside well-mapped areas, and no street geometry is returned.\n\nOne call is one billed lookup however many layers, sets or grid codes it touches, and a\ncall that matches nothing still bills.", "execution": { "taskSupport": "forbidden" },
Current tools
Show all 7 tool fingerprints
Watch this server yourself
If you run this server, put the proxy in front of it. It pins these exact fingerprints on first connect and stops the session if they move.
npx -y mcp-pin@0.2.3 -- <your atlasfetch-mcp command>
Or subscribe to this page's RSS feed to be told when it changes.
Badge
The badge states one fact about time and nothing else. It never claims a server is safe.
[](https://mcp-pin.gautamkhosla.com/servers/520562b5714e1831.html)