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
| Tool | What it does |
|---|---|
geocode_search | Find Canadian addresses, streets, localities and points of interest by name. |
geocode_reverse | Turn a longitude/latitude into the places nearest to it. |
geocode_nearby | Find features of a category (pharmacies, cafés, parking) near a point. |
route | Road distance, travel time and the route line between two points. |
isochrone | Travel-time polygons: how far you can get in 10, 20, 30 minutes. |
identify | Which catalog features contain a coordinate: municipality, survey cell, well, parcel. |
data_query | Every feature of one catalog layer inside a bounding box. |
list_layers | The 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-stylesskill 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 besidegeocode_searchwould mostly get it chosen by mistake.- Resources and prompts. The server declares
toolsand 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.jsonThe 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.