Toll comparison for the same truck route with and without vehicle profile

Location Data for AI Agents: What We Learned Building an MCP Server

We priced a truck run twice. Same origin, same destination, same day. The first call told the routing engine it was a truck. The second call told it what kind of truck.

The toll estimate went from $20.70 to $55.00.

Nothing else moved. Distance changed by two miles. Drive time didn’t change at all. Same two tollways, same four gantries, both answers back in about a second, both in the same format. Illinois prices commercial tolls by axle tier, and the first call never carried an axle count — so it quoted a vehicle we don’t operate.

That gap is the whole reason we built what follows. One lane, run twice a day, is roughly $17,000 a year of tolls that never reach the quote. And the number that’s wrong doesn’t look wrong.

The problem with asking a model where something is

Ask any current AI assistant a geography question and it will answer. Fluently, immediately, in the right format.

It is not looking anything up. A language model predicts text. It has seen the phrase “about a twenty-minute drive” in millions of documents and can produce it on demand, without any mechanism for knowing whether this origin is twenty minutes from that destination. The output is a plausible sentence, not a computed result.

For most questions that’s fine. For a dispatcher deciding which truck goes where, or an operations lead quoting a lane, it isn’t — and the failure mode is that nothing looks broken.

We ran into a sharper version of this with our own geocoder. Asked for “downtown Chicago,” it returned a street in Omaha, Nebraska.

That’s not a defect. “Downtown” isn’t an address. The geocoder tokenised the string, found a street that matched, and returned it with high confidence, because geocoders have no “I don’t know” mode. Their job is to return the best available match, and they always find one.

The failure isn’t imprecision. It’s certainty about the wrong thing, in the right format, 700 kilometres away.

What we built

The Placematic MCP Server is an endpoint that lets an AI agent call our spatial APIs as tools. MCP — Model Context Protocol — is the emerging standard for how agents connect to external systems, and it’s supported by Claude, ChatGPT, Cursor and a growing list of clients.

Four tools:

  • Territory assignment. Which of your delivery zones or sales territories covers a point, which of your locations serve it, and on what terms — minimum order, delivery fee, priority.
  • Truck routing. Road distance, driving time and toll cost, computed against the vehicle’s height, weight, length and axle count.
  • Geocoding and reverse geocoding. Address to coordinates and back, against licensed HERE map data.

Everything is read-only. There is no function in the schema that writes, edits, deletes or moves anything — not in your Placematic account, not in your systems. The capability is absent, not switched off, which makes the conversation with a security team considerably shorter than it usually is.

Placematic USA LLC is the contracting party. Customers don’t hold a HERE account, negotiate a HERE contract, or manage a second key.

Five things that surprised us

1. The tool description is the interface, and the user is a model

We named one argument query. The agent called it with address.

It wasn’t wrong. Half the geocoding APIs on the market call that field address, and the model reached for the name that made sense rather than the one in our schema. So we renamed it.

That’s when the real lesson landed. An agent selects a tool by reading its description. Everything the description doesn’t say, the model has to guess — and it guesses confidently.

So the descriptions now say, explicitly, that height is in centimetres and not feet. That a 53-foot trailer at 80,000 pounds converts to 1,615 centimetres and 36,287 kilograms. That in the territory tool, x is longitude and y is latitude, which is the reverse of every other tool we expose. That a vague descriptor like “downtown” is not an address and should be resolved to a city and state first.

Each of those sentences exists because we watched a model get it wrong without one.

2. Selecting a truck profile is not the same as describing a truck

This is the finding that opened this post, and it generalises.

Setting a truck routing mode selects an engine. It does not tell that engine what your vehicle is. Omit the dimensions and you get a generic result — a route that may take a 4.1-metre trailer under a bridge it cannot clear, and a toll figure priced for the wrong axle tier.

So the tool now refuses to be helpful in the convenient way. Ask it to route a truck without dimensions and it asks for them before calling. When they’re genuinely unavailable, the response carries an explicit warning that neither the route nor the toll estimate is verified for the actual vehicle.

An agent that answers everything is less useful than one that knows what it doesn’t have.

AI agent asking for vehicle dimensions before calculating a truck route using the location MCP server

Two cost models: a backend asking discrete questions, and a device running a continuous session.

3. An empty result is an answer, not an error

A point outside every delivery zone is a valid business answer: we don’t deliver there. An address with no match is a valid result: check the spelling.

We initially returned both as errors. Agents responded the way agents do — by retrying in a loop, burning transactions against a question that had already been answered correctly.

Now empty results come back as results, with wording that tells the agent what happened and what to try instead. Error states are reserved for genuine failures: a rejected key, an upstream outage, a timeout.

4. Renaming an argument breaks every connected client

When we changed query to address, connected agents kept calling with the old name.

Clients cache tool schemas when they connect and don’t refresh them on their own. The agent sent the cached argument, received an error naming the correct one, and corrected itself back to the cached name. Twice.

This has a real consequence for anyone shipping tools to customers: your schema is a public interface with no deprecation path. Names have to be settled before the first integration, not after.

5. The distribution surface is narrower than the spec suggests

If you build an MCP server for your own team, any client works.

If you build one for customers, the picture is different. Claude’s and ChatGPT’s custom connector dialogs take a URL and optional OAuth credentials — neither has a field for a header, which is how API keys normally travel. And on Business, Enterprise and Edu plans of both products, custom connectors are a workspace-level setting an administrator has to enable.

Cursor, Claude Code and anything a developer writes connect with a header in under a minute.

Which told us something about adoption we hadn’t assumed: the first person inside a customer to use this isn’t the dispatcher. It’s the engineer sitting next to them.

Where this actually helps

The tools that matter aren’t the ones that duplicate what an assistant already has. Every major assistant ships a geocoder, and ours competes with it directly.

The ones that matter are the questions a general-purpose model structurally cannot answer:

An order came in from this address — who covers it, what’s the minimum, what’s the fee?

Can the rig we have available legally make this run, how long will it take, and what will the tolls cost?

A driver reported a breakdown at these coordinates — where is that, and which of our locations serves that area?

None of that is on the internet. Your territory map is yours. Your fee table is yours. Your fleet specs are yours. No amount of model training reaches data it has never seen, which is precisely why that data is the part worth connecting.

The companies that get something out of AI in this industry won’t be the ones with the best model. They’ll be the ones whose operational data is clean enough to be worth asking a question of.

Getting access

MCP access is included with a Placematic Spatial API plan. An agent’s call costs the same transaction as a call from your own backend — the connector is a channel, not a separate product. Every pilot key carries a monthly transaction cap agreed before the key is issued, so an agent in a retry loop can’t produce a surprise invoice.

Keys are issued within one business day. No credit card, no demo call required.

Full documentation, tool schemas and per-client configuration:
https://docs.placematic.com/mcp/overview