Routerra LogoTeams
Browse articles· MCP connector
For ownersUpdated 2026-09-08 · 6 min read

MCP connector

The Routerra Teams MCP server: endpoint and headers, the 18 tools and the REST endpoint each one wraps, and every place MCP behaves differently from REST.

The MCP connector puts the External API in front of an AI assistant. Same key, same data, same rules — the tools are thin wrappers over the REST endpoints, and the handful of places where the two transports genuinely differ are the reason this article exists.

The server is Streamable HTTP with no sessions: every call is a self-contained JSON-RPC POST, and there is no handshake to keep alive.

The facts

EndpointPOST /mcp · POST /mcp/{key}
Required headerAccept: application/json, text/event-stream
Tools18 — read-only ones carry readOnlyHint
Tool resultThe same endpoint's JSON, in content[0].text
curl -X POST https://teams-api.routerra.io/mcp \
  -H "X-API-Key: rtk_…" -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"get_plan","arguments":{"planId":315}}}'

The 18 tools

ToolREST endpointNotes
get_team_contextGET /teamread-only
list_driversGET /driversread-only
update_driverPATCH /drivers/{driverId}
search_address_bookGET /address-bookread-only
optimize_planPOST /optimize
list_plansGET /plansread-only
get_planGET /plans/{planId}read-only · view defaults to CONCISE
cancel_planDELETE /plans/{planId}confirm, propose
duplicate_planPOST /plans/{planId}/duplicate
add_stopsPOST /plans/{planId}/stops
update_stopPUT /plans/{planId}/stops/{stopId}takes a patch argument
remove_stopsPOST /plans/{planId}/stops/removeconfirm
dispatch_planPOST /plans/{planId}/dispatchconfirm, propose
approve_planPOST /plans/{planId}/approvepropose
revoke_planPOST /plans/{planId}/revokeconfirm, propose
get_delivery_statsGET /statisticsread-only
apply_changePOST /changes/{changeId}/apply
list_changesGET /changesread-only

There is no MCP tool for POST …/preview or POST …/changes, and none is needed: on MCP the preview arrives on its own when confirm was not passed, and a proposal is made with propose: true on the tool itself.

Where MCP and REST diverge

DifferenceDetails
Response envelopecancel_plan, revoke_plan, remove_stops, dispatch_plan and approve_plan return {applied, result, preview, change} rather than the endpoint body directly. When applied is true the payload is in result. Empty members are omitted, not sent as null — a successful approve_plan returns exactly {"applied": true, "result": {…}}, so read a missing key as null
confirmMCP only, on cancel_plan, revoke_plan, remove_stops and dispatch_plan against an APPROVED plan. REST applies immediately
proposeMCP only. The REST equivalent is POST …/changes
autoRevokeREST only. dispatch_plan drops the parameter — confirm=true is what stands in for consenting to the revoke
Missing scopeOn MCP a key with write gets a proposal instead of a 403. In REST it is always 403 insufficient_scope
PreviewIn REST it is a separate POST …/preview. On MCP it comes back by itself whenever confirm was not passed
Default viewget_plan defaults to CONCISE; GET /plans/{planId} defaults to detailed
Rate-limit tierEvery MCP call is filtered in the shared tier (capacity 60), because the tier is picked from the URI and every tool call arrives at /mcp. The five-token optimize tier still applies on top: optimize_plan and dispatch_plan take an optimize token themselves, so an MCP optimization spends one token from each bucket. Over REST, /optimize and …/dispatch are filtered straight into the optimize tier and spend one token there

The same call, two behaviours

The scope row above is the divergence that surprises people, so it is worth stating twice. A key holding write but not dispatch that tries to send routes gets:

  • over REST — 403 insufficient_scope, and nothing happens;
  • over MCP — applied: false, a change with status: "PROPOSED", and a dispatcher who can apply it.

Nothing about the key changed. Only the transport did. A key with only read is refused on both, because it cannot even propose. See Proposed changes.

An MCP optimization spends two tokens, not one

What the assistant is told

The server ships its own instructions, so a connected model already knows the shape of the product before you prompt it: that dispatch computes routes and approve sends them; that editing stops on a computed plan gives HAS_CHANGES; to prefer the concise view; to show people the …Local times rather than the UTC ones; to ask the user before cancelling, removing stops, revoking, or dispatching over an APPROVED plan; to call get_team_context at the start of a session and dispatch only with drivers whose startLocation is near the stops; to name the missing scope and stop retrying when a call is refused; and, for proposals, to tell the user the change is queued and to call apply_change only after explicit agreement in that same conversation.

For the REST side of each tool, see Plan endpoints and Plan operation endpoints. For where a key's scopes come from, see API authentication & scopes.

Was this article helpful?

Still stuck?

Write to us — a human reads every message.

Contact support