Introducing MapMap: out of stealth, still in beta

# Introducing MapMap: out of stealth, still in beta

> **Note, updated 2 August 2026.** The MCP server exposed sixteen tools when this was written. It exposes **32** today. See [/docs/mcp](/docs/mcp) for the current list.

MapMap is a self-hostable navigation platform: routing, turn-by-turn guidance and vector maps for car, van, truck, bus, two-wheeler and pedestrian, online or fully offline, running against our hosted API or entirely on your own hardware. We built it in stealth between January and July 2026 and we are publishing it today. It is in beta, and we say so plainly. The hosted gateway at `https://api.mapmap.ai` is live, the free tier is 50,000 calls a month after you verify an email, commercial use included, and the parts that are not finished are named further down this post rather than buried in a footnote.

## What is MapMap?

MapMap is one routing engine, one guidance core and one map stack, delivered three ways: a hosted API with metered keys, an offline SDK for Android and iOS, and a Docker Compose distro you run inside your own network. All three read the same signed territory packages, so a route planned in the cloud and a route planned on a device in an underground car park come from the same code and the same data.

The surface, as it stands today:

| Capability | How you call it |
| --- | --- |
| Compatible URL routing | `GET /route/v1/{profile}/{coordinates}` with vendor params `height`, `width`, `length`, `weight`, `hazmat`, `tunnel_code` |
| Native JSON routing | `POST /route` with `costing_options.truck` and a top-level `adr` extension |
| Pure ADR compliance | `POST /adr/check` returns the ADR 8.6.4 tunnel-entry decision with reasoning, no routing |
| Data APIs | `POST /isochrone`, `POST /matrix`, `POST /trace_route`, `POST /trace_attributes`, plus geocoding |
| Fleet optimisation | `POST /optimise` (alias `/optimize`), multi-vehicle and multi-stop over a matrix from our own engine |
| Maps | `GET /tiles/{territory}/{z}/{x}/{y}.mvt`, `/styles`, `/fonts/{fontstack}/{range}`, `/sprite/{file}` |
| Agents | `sn-mcp`, sixteen MCP tools, stdio or streamable HTTP, hosted at `https://mcp.mapmap.ai/mcp` |
| Offline | ed25519-signed territory packages with BLAKE3 content hashes and differential over-the-air updates |

The profiles on the routing endpoint are `truck`, `driving` (aliases `car` and `auto`), `bus`, `bicycle` (`bike`, `cycling`), `walking` (`foot`, `pedestrian`), `scooter` and `motorcycle` (`motorbike`). One engine, one set of semantics, not a car router with a lorry mode bolted on the side.

Errors are RFC 9457 `application/problem+json` with stable `urn:sn-gateway:problem:<slug>` type URIs. Two exceptions, both deliberate: the compatible URL endpoint answers in the OSRM envelope because OSRM clients dispatch on `code`, and a `402` uses the x402 machine-payment wire format so an agent can parse it.

## Why did we build another navigation platform?

Because the navigation market makes you rent your own operational data back from a hyperscaler, and gives you no supported way to take it in-house. That is the whole thesis and everything else in this post follows from it.

Look at what a standard navigation licence actually forbids. Caching beyond a short window. Storing geocoded results. Operating offline. Running the stack inside your own network. A fleet that has spent 10 years accumulating stop data, dwell times and restriction knowledge discovers that the platform holding it is the one asset they cannot move, and that the price of holding it goes up every renewal. When the bill gets uncomfortable, there is no in-house option to negotiate against. That is not an accident of the product. That is the product.

We think the correct shape is different: an engine you can run yourself, a licence that says yes to the things fleets actually need, and data packages you can mirror into an air-gapped network with `rsync`. So we wrote it. First-party Rust for the core, Kotlin and Swift bindings over UniFFI, permissive licences only, and a machine-enforced dependency gate in CI so that stays true.

## What does sovereign navigation mean in practice?

Sovereign means you can run the whole stack on your own hardware, air-gapped, and buy the licence to do it without a sales cycle. The self-host distro is a Docker Compose file: gateway, routing engine, an optional geocoder, and the MCP server. It needs outbound internet on first boot only, to pull an OSM extract and the shared global base-map sources, and air-gapped installs skip even that by starting from a pre-built territory package.

The trust model is the part we are most opinionated about. Every package manifest is signed with ed25519 and every layer inside it is content-addressed with BLAKE3, so devices never trust the transport. A hostile CDN, a compromised mirror or a gateway in the middle cannot alter what a device accepts. The update channel is dumb by design: static files, mirrorable with `rsync`, inspectable with `ls` and `tar`. No server-side logic participates in the trust model, because logic you cannot see is not a trust model.

The full argument, including what the signing scheme does not protect you against, is in [why we built sovereign, self-hostable navigation](/news/sovereign-navigation).

## What does agent-native actually mean here?

Agent-native means an agent can discover us, price us, get a key and route, with no human in the loop. That is not a demo, it is the signup flow.

Concretely: `llms.txt` on the website and on every gateway deployment, machine-readable pricing at `/pricing.json`, a one-call card-free key issuance endpoint, an authoritative `/openapi.json` per deployment, RFC 9457 errors an agent can branch on, and an MCP server with sixteen tools covering routing, ADR checks, geocoding, matrix, optimisation, errand ordering and map styling. We did not add these as a marketing layer. We treated the LLM reading our markdown as a first-class customer with the same standing as the fleet CTO, and it changed how we wrote the docs, the errors and the pricing page.

The reasoning, and the parts that are still rough, are in [maps for AI: what agent-native navigation requires](/news/maps-for-ai).

## Where is our commercial edge?

Truck routing with ADR dangerous-goods tunnel enforcement, and as of July 2026 we are the only navigation API offering a self-serve ADR tunnel-compliance product at published per-call prices. Everyone else in this category either does not do ADR, or does it behind a quote.

The technical claim underneath is narrower and matters more. The tunnel category is enforced in costing, not filtered out afterwards, so the route you get back is one the vehicle can legally drive. A post-filter tells you your route was invalid. Costing enforcement gives you the legal route instead. Setting `tunnel_code` implies `hazmat=true`, slashed codes like `B/D` are real and must be URL-encoded, and the truck dimension parameters return `400` on any profile other than `truck` rather than being silently ignored.

Here is the whole thing, from nothing to a compliant 44-tonne route, in two calls:

```sh
export BASE=https://api.mapmap.ai

curl -fsS -X POST "$BASE/v1/keys" \
-H "Content-Type: application/json" \
-d '{"email": "you@example.co.uk", "accept_tos": true}'
```

```json
{
"key": "snk_…",
"key_id": "3f1c…-uuid",
"state": "provisional",
"calls": 1000,
"expires_in_h": 72,
"verify": "link sent to email; clicking upgrades this key to the free tier",
"tos": "https://mapmap.ai/terms"
}
```

The `snk_` key is shown once. Dover to Birmingham, 44 t artic, 4.0 m high, ADR tunnel restriction code D:

```sh
export API_KEY=snk_…

curl -fsS -G "$BASE/route/v1/truck/1.3134,51.1279;-1.8904,52.4862" \
-H "Authorization: Bearer $API_KEY" \
--data-urlencode "overview=full" \
--data-urlencode "height=4.0" \
--data-urlencode "width=2.55" \
--data-urlencode "weight=44.0" \
--data-urlencode "hazmat=true" \
--data-urlencode "tunnel_code=D"
```

```json
{
"code": "Ok",
"routes": [
{
"distance": 362514.3,
"duration": 16043.9,
"geometry": "u{~vHmgg@…",
"weight": 16043.9,
"weight_name": "duration",
"legs": [
{ "distance": 362514.3, "duration": 16043.9, "summary": "M25, M40" }
]
}
],
"waypoints": [
{ "name": "A20", "location": [1.3134, 51.1279] },
{ "name": "", "location": [-1.8904, 52.4862] }
]
}
```

Distances are metres, durations are seconds, geometry is an encoded polyline. The deeper treatment of tunnel codes and what they restrict is in [ADR tunnel compliance, enforced in costing](/news/adr-tunnel-compliance).

## What does it cost?

Free is 50,000 included calls a month after you verify an email, and commercial use is allowed. There is no trial cliff. Before verification you get a provisional key from one card-free call: 1,000 calls, valid 72 hours, rate-limited to 60 requests a minute.

Paid usage is prepaid credit, two-speed, tiered and marginal. The class is decided per request automatically.

| Month-to-date band | Standard class | Premium class (truck and ADR) |
| --- | --- | --- |
| 50,001 to 1M calls | 0.05p per call | 1p per call |
| 1M to 10M calls | 0.03p per call | 0.7p per call |
| Beyond 10M calls | 0.02p per call | 0.4p per call |

Standard covers car, van, bus, two-wheeler and pedestrian routing, geocoding, matrix, isochrone and map-matching. Premium covers truck routing and ADR compliance. Included volume is denominated in standard calls, so one premium call draws 20 of them: all-premium free usage is 2,500 calls a month.

Size-metered requests bill by size, not by request:

- A matrix bills one call per started block of 25 elements, capped at 10,000 elements per request.
- An isochrone bills one call per contour, capped at 10 contours.
- An optimisation bills a flat 10 calls, fair-use capped at 200 unique locations.

No credit means `402` or `429`, never surprise billing. Above 25M calls a month we quote. `/pricing.json` is the machine-readable source of truth and it wins over any prose, including this paragraph.

## What is solid, and what will change?

We are in beta. Things will change, and we will tell you when they do. Here is the honest split.

**Solid enough to build on.** The hosted gateway is live. Routing, truck dimensions and ADR tunnel enforcement work and are covered by tests. The compatible URL endpoint, `POST /route`, `POST /adr/check`, matrix, isochrone and map-matching are all live. The territory trust model (ed25519 manifests, BLAKE3 layers, atomic-swap updates) is done and we do not expect to change its shape. Pricing is published and machine-readable.

**Named limitations, today.**

- **The repository is private** while we finish the sdk-v1 release, so there is no public clone URL yet. Self-hosting works, but you email [hello@mapmap.ai](mailto:hello@mapmap.ai) for source access first. We are aware that "self-hostable" and "email us for the source" sit awkwardly in the same sentence. That gap closes with sdk-v1.
- **`POST /optimise` is enabled per deployment.** If a deployment has no VROOM sidecar you get a `503` with `optimisation-not-enabled`, and that is deliberate rather than a bug.
- **The hosted MCP endpoint is for evaluation.** `route`, `matrix`, `check_adr_tunnel` and the style-read tools work today. `geocode` and `optimise_routes` answer with tool errors until their upstreams are enabled on that deployment, and style publishes are metered and may be unavailable. For production, use your own `snk_` key against the REST API or run the server yourself.
- **Territory packages have no freshness guarantee by default.** Devices accept any signed version, because rollback-by-republish is a feature operators asked for. The consequence is real: a stale mirror can hold devices on an older legitimate version. A signed index TTL can be layered on where that matters, and we would rather tell you than let you find out.
- **Coverage is territory-based.** The full world map is now built and published, and deployments can still scope to individual territories. `GET /territories` on a given deployment is the source of truth for what it actually publishes.

**What we will not do in beta.** We will not break the compatible URL endpoint's shape, and we will not raise published prices without notice. Anything else is fair game to improve.

## Why does this feed start with six months of backlog?

Because this news feed is our build log from the stealth period, published now rather than written after the fact. We wrote posts as we built, and today they go up together. That means the feed contains work that landed in March sitting next to work that landed last week, and it means the early posts describe decisions we made before we knew whether they were right.

We kept them anyway. A build log that only records the decisions that worked out is marketing. Alongside this post you will find the deep dives on the ADR tunnel work, the MCP server, the Docker distro and x402 machine payments, each one written by whoever built the thing.

## How can you check these claims?

We have no customer logos to show you and we have not invented a benchmark, so every claim we make is one you can verify instead of trust. Source access is by email until the sdk-v1 release makes the repository public, and the SBOM ships with every tagged release:

| Claim | How it is proven |
| --- | --- |
| 700+ automated tests | Across the Rust workspace and the Kotlin and Swift bindings |
| Signed offline packages | ed25519 manifests, BLAKE3 content hashes, atomic-swap updates |
| Licence-clean distributables | Permissive-only dependency gate in CI, lineage documented per component |
| Supply-chain transparency | CycloneDX SBOM and licence inventory published with every tagged release |
| ADR enforced, not filtered | Enforced in costing, cross-validated with differential route tests |

The SBOM point is the one we would push hardest. Every distributable is permissive-licence only, and we publish a CycloneDX SBOM with each release so your legal team can check rather than trust us. Trust-us is how you end up unable to self-host.

## Try it

Get a key in one call and route a truck in the next: the [quickstart](/docs/quickstart) is two curl commands and no card. The [playground](/playground) runs the same requests from your browser with no signup at all. If you want the stack inside your own network, mail hello@mapmap.ai and we will send the source.

Routing derives from OpenStreetMap. Credit "© OpenStreetMap contributors" when you render or republish it.