Skip to content

MCP server

unmap runs a Model Context Protocol server at https://api.unmap.dev/mcp, so an agent can look up Canadian places and route between them without you writing an HTTP client. It is the same API behind the same key: an MCP client is just another API client, authenticated, rate-limited and metered exactly like curl.

Connect

The transport is Streamable HTTP, and the key travels as a bearer token. Most clients take this as a block of JSON:

{
  "mcpServers": {
    "unmap": {
      "type": "http",
      "url": "https://api.unmap.dev/mcp",
      "headers": { "Authorization": "Bearer um_live_..." }
    }
  }
}

You need a key first; Authentication covers how to create one. There is no anonymous access and no OAuth flow: a human creates a key in the dashboard and hands it to the agent, which is what /auth.md tells an agent that arrives without one.

To check the connection by hand:

curl https://api.unmap.dev/mcp \
  -H "Authorization: Bearer $UNMAP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

The eight tools

ToolWhat it does
geocode_searchFind Canadian addresses, streets, localities and points of interest by name.
geocode_reverseTurn a longitude/latitude into the places nearest to it.
geocode_nearbyFind features of a category (pharmacies, cafés, parking) near a point.
routeRoad distance, travel time and the route line between two points.
isochroneTravel-time polygons: how far you can get in 10, 20, 30 minutes.
identifyWhich catalog features contain a coordinate: municipality, survey cell, well, parcel.
data_queryEvery feature of one catalog layer inside a bounding box.
list_layersThe layer catalog itself, with each layer's licence, coverage and known gaps.

identify is not geocode_reverse. Reverse geocoding finds the nearest named places to a point; identify returns the polygons the point falls inside. Ask a model for "what municipality is this in" and identify is the right answer; "what is the address here" is reverse.

list_layers is worth calling before promising a layer to a user. Coverage is recorded honestly per layer and several are one province rather than national, so the catalog is the difference between an agent that says "British Columbia only" and one that quietly returns nothing.

Every one is read-only. There is no tool that writes anything, and none that can spend money beyond the metered call itself.

Arguments mirror the REST endpoints under clearer names: query for q, language for lang, and a single coordinate, near, from, to or center as a [longitude, latitude] array (the "lng,lat" string form is accepted too). geocode_nearby takes categories as an array, and isochrone takes minutes as one. A bad argument comes back as an errored result the model can read and correct, rather than as a protocol error it cannot see.

What is deliberately absent

  • Tiles, styles, glyphs and sprites. The only useful thing a tool could return is a style URL with your key embedded in it, and that is a credential to leak, not a tool to call. To render a map, build the URL yourself. Maps API is the page, and the unmap-map-styles skill below is the same thing written for an agent.
  • /geocode/autocomplete. It ranks on term match and prominence alone, so it is the right endpoint for a keystroke in an input box and the wrong one for everything else. Offering it beside geocode_search would mostly get it chosen by mistake.
  • Resources and prompts. The server declares tools and nothing else.

Billing

One tools/call is one billable request, counted against the service it used: a geocode_search lands in your geocoding usage, a route in your routing usage, exactly as the REST call would. Protocol traffic (initialize, tools/list) is counted too, under mcp. See Plans & Limits.

Unlike the REST endpoints, MCP tool calls do not use the 24-hour geocoding edge cache. Agent traffic is low volume, and a second cache keyed differently from the first is a second thing that can serve a stale corpus.

Protocol details

The server is stateless: no session id, one JSON-RPC message per request, one response per request. A GET on the endpoint answers 405, because in Streamable HTTP a GET opens a server-to-client event stream and there is nothing here to push.

Protocol revisions 2025-03-26, 2025-06-18, 2025-11-25 and 2026-07-28 are all negotiated, and both initialize and its 2026-07-28 replacement server/discover are answered, so a client of any recent vintage connects without special-casing.

Discovery

Three documents describe the server to a machine, all unauthenticated:

curl https://api.unmap.dev/mcp/server-card        # SEP-2127 Server Card
curl https://unmap.dev/.well-known/ai-catalog.json # domain-level discovery
curl https://unmap.dev/.well-known/agent-skills/index.json

The Server Card carries the server's identity, its transport and the protocol revisions it speaks. It is served at the reserved <streamable-http-url>/server-card location and, identically, at /.well-known/mcp/server-card.json on both hosts. It deliberately does not enumerate tools: a static document cannot honestly describe a surface that may vary, so tools/list on a live connection is the authority.

The AI Catalog at unmap.dev/.well-known/ai-catalog.json is the domain-level entry point, naming the card rather than repeating it.

The Agent Skills index is not MCP at all. It publishes four Markdown skills (unmap-quickstart, unmap-geocoding, unmap-routing, unmap-map-styles) that teach an agent to call the plain HTTPS API, including the parts MCP does not cover. An agent with no MCP client, or one that needs to render a map, can read those instead.

Next steps

  • Geocoding API and Routing API for what each tool does underneath, including the coverage gaps worth knowing before you rely on one.
  • Errors for every status the API answers with.