Skip to main content
Glama

Best visiting order for stops

optimize_route
Read-onlyIdempotent

Find the optimal visiting order for 2-10 stops by solving the traveling-salesman problem over street networks. Returns per-leg distance, duration, totals, and export links.

Instructions

Best order to visit several stops: multi-stop route ordering (a small TSP).

Answers "I have these five errands, what order costs least" — stops is a
list of 2-10 points, each a {"lat": ..., "lon": ..., "name": ...
(optional)} dict, a GERS id, or a free-text name, mixed freely. The
answer is the cheapest visiting order over the real street graph, not a
straight-line guess. Solved exactly (Held-Karp over the routed cost
matrix), so it is the optimum, not a nearest-neighbour approximation.
Any stop given by id/name that failed to resolve returns an indexed
error (stops[i]: ...) with candidates on ambiguity — the whole call
fails, not silently drops that stop.

Returns {"order": [stop indices, in visiting order], "legs":
[{"from_idx", "to_idx", "distance_m", "duration_s"}, ...],
"total_distance_m", "total_duration_s", "mode", "roundtrip", "export"}
— indices refer to the input `stops` list, and there is no
polyline/geometry — for a single pair's numbers on their own, call
`route`. export is the pocket handoff: a multi-stop Google/Apple Maps
directions URL (coordinates only — no Maps API), a GPX 1.1 document
with every stop as a waypoint, and a printable list that keeps any
names the caller passed. If a stop already carries confidence or
operating_status (from a prior place lookup), the response adds
verify_before_going naming the 1–2 weakest. Any stop given as an id or
name adds "resolved": [{"stop": i, "name", "id", "lat", "lon",
"matched_by"}, ...] for just those stops — plain {lat,lon} stops need
no echo and the key is absent when every stop was already coordinates.

keep_order=true visits the stops in the order you gave and never
reorders them: the itinerary is the caller's, and this tool supplies
routed (not straight-line) per-leg numbers, the totals, and the export
for it — one street-graph build for the whole run instead of chaining
`route` per leg. Use it whenever the order came from the user ("first
the bank, then the school, then home"); leave it off to be told the
cheapest order. The response echoes "keep_order": true, and "order" is
then just 0..n-1. start_index must stay 0 with it (there is nothing to
fix — the given order already starts where it starts), and roundtrip
still chooses whether the last leg closes back to the first stop, so a
one-way itinerary wants roundtrip=false.

start_index (default 0) is fixed as the first stop. roundtrip=true (the
default) returns to it; the closing leg is in "legs" but the start is not
repeated in "order". roundtrip=false is an open path that ends wherever
is cheapest. Omit mode to use the stored preferences mode, else drive. Same
cost model every routing tool uses; one-ways make the drive/cycle cost
matrix asymmetric and that is solved for exactly. The objective minimized
is total duration.

If some pair of stops has no route between them (disconnected road data),
the call still succeeds: that leg's numbers are a straight-line estimate,
the leg carries "estimated": true, and the response carries
"estimated": true plus a note naming the estimated legs — so a flagged
approximation, never a crash.

confirm=true after the user agreed to wait for a first-time street-graph
build (about 5–25 seconds). Pass it only after a needs_confirm reply
and they said yes. One gate for the whole call — every stop rides the
same graph, so it asks once, never once per leg. A warm or cached graph
never needs it. Omit confirm unless you just asked and they said yes.

Errors are structured, not raised: fewer than 2 or more than 10 stops, a
stop that is not a valid location reference, an out-of-range
start_index, or keep_order=true with a non-zero start_index return
{"error": "bad_request"} naming the offending stop
index; an unresolvable name/id returns {"error": "not_found"} or
{"error": "ambiguous_place", "candidates": [...]}, indexed the same way;
an unknown mode returns {"error": "unsupported_mode"}; a stop set whose
two furthest-apart stops are further apart than the mode's straight-line
cap (see `route`) returns {"error": "route_too_long"}; a stop with no
usable street node near it returns {"error": "no_graph_nearby"} naming
that stop's index.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeNoTravel mode. Default: stored preference, else drive.
stopsYes
confirmNo
roundtripNo
keep_orderNo
start_indexNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Install Server

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare read-only, idempotent, and non-destructive behavior, and the description adds substantial behavioral context beyond that: exact Held-Karp optimization, structured errors, estimated straight-line legs on disconnected graphs, and the confirmation/one-time-build behavior. There is no contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but each paragraph covers a distinct, necessary concern: optimization semantics, `keep_order`, start/roundtrip behavior, estimation, confirmation, and errors. The key distinction from `route` is front-loaded, and the length is justified by the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite the sparse schema, the description is complete: it covers input constraints, parameter interactions, return structure, error categories, ambiguous stops, disconnected road data, and the confirmation flow. An agent has everything needed to invoke and interpret the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 17%, so the description carries the full burden for parameters. It explains each stop format (`{lat, lon, name}`, GERS id, free-text name, mixed), mode defaults, `roundtrip`, `keep_order`, `start_index`, and `confirm` in enough detail to use the tool correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a precise statement of what the tool does: 'Best order to visit several stops: multi-stop route ordering (a small TSP).' It also differentiates from the sibling `route` tool by explicitly saying a single pair's numbers should use `route` instead.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: use `keep_order=true` when the order came from the user, omit it to get the cheapest order, and call `route` for a single pair. It also clearly states the `confirm` gate: pass it only after a `needs_confirm` reply and user agreement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chuofringer/placeroot'

If you have feedback or need assistance with the MCP directory API, please join our Discord server