An MCP Server for Freight, Sixteen Tools Agents Call Natively

Pull-quote: “An API is a contract with a developer who reads the docs once and writes code that calls you the same way forever. A tool surface is a contract with a model that reads the docs every single time and improvises. Those are different customers.”
Why this matters
Freight intelligence used to have one consumer: a human at a screen. Then two: humans, and the developers integrating through REST and GraphQL APIs or the Python and TypeScript SDKs. Now there is a third, and it behaves like neither. Enterprises are standing up their own AI agents, planning assistants, supply-chain copilots, analyst workbenches, and those agents need to run freight queries and simulations as steps inside their own reasoning, not as screenshots passed across a chat. The Model Context Protocol is how that happens without custom integration per agent framework: publish the capabilities as tools, and any MCP-speaking agent can discover and call them natively. Publishing sixteen freight analysis tools over MCP teaches one lesson quickly: the protocol is the easy part. Designing a tool surface for agents you did not build and cannot debug is the real work.
What changes when the caller is an agent
External agent (theirs) Freight tool server (ours)
───────────────────── ──────────────────────────
plans a multi-step ── MCP ──► tool schemas +
analysis descriptions
│ │
▼ ▼
picks tool, fills args ────────► validation, scope
│ and audit logging
▼ ▼
reasons over result ◄──────── structured output,
calls the next tool citations attached
| Interface | Consumer | What the contract must survive |
|---|---|---|
| REST / GraphQL API | Developer code | Written once, tested, deterministic call patterns |
| Python / TypeScript SDK | Analyst scripts | Human judgment at every step |
| MCP tool surface | External agents | A model choosing tools and arguments fresh, every session |
Four design rules the surface taught us
Tools follow analytical intent, not endpoints. An API can afford thirty fine-grained routes a developer composes. An agent choosing among tools does better with a smaller set shaped like analyst questions: query flows, run a simulation, screen corridors, check anomalies. Sixteen tools is a deliberate size, wide enough to cover the real analytical capabilities, small enough that selection stays reliable.
The description is load-bearing. The agent decides what to call and how from the tool description and schema alone. Every parameter documented with its units and bounds, every output shape stated, every limitation written down: this text is not documentation about the interface. It is the interface.
Every answer carries its citations. The calling agent will synthesize our output into its own answer for its own user. Structured results with citations attached keep the provenance chain intact one hop downstream, so a number that reaches a state DOT briefing can still be traced to the public federal data underneath.
Assume the caller is confused. A well-intentioned agent will eventually send the wrong zone code, an impossible year, a simulation parameter outside any sane range. Validation, scoping, and audit logging on every call are not defensive pessimism; they are what makes an open tool surface operable. The same audit trail that serves enterprise governance answers the new question MCP raises: which agent asked for what, when, with which arguments.
Closing
The interfaces stack rather than compete: REST and GraphQL for integrations, SDKs for analysts, MCP for the agents your organization is already building. Publishing sixteen freight tools over MCP turns an analytics system from a destination into a capability that other systems compose, and the craft that makes it work is unglamorous: intent-shaped tools, descriptions treated as the interface, citations on every output, validation and audit on every call. Agents are the new integration surface. Design for them like you mean it.
