Tools & errors
Nine tools, generated from the server's own schemas, so this page always matches the code. Every successful result includes a next_step hint; every error includes a code and suggested_next_tool.
Jump to: list_locations · search_menu · get_item · check_availability · plan_group_order · quote_order · place_order · get_order_status · cancel_order · errors · resources
list_locations
Start here. Lists the merchant's locations with address, hours, fulfillment modes (pickup, delivery, dine_in, catering), and whether each is open right now.
Pass near (lat/lng) to sort by distance, and/or postal_code to learn whether each location delivers there (delivers_to_you: yes | no | unknown). With fulfillment="delivery", locations that definitely do not deliver to you are dropped.
Returns location ids. Next: call search_menu with a location_id.
Read-only.
| Parameter | Type | Notes |
|---|---|---|
near | { lat, lng } | Customer coordinates |
postal_code | string | Customer postal code, e.g. B3J 2K9 |
fulfillment | "pickup" | "delivery" | "dine_in" | "catering" | Only locations offering this mode |
get_item
Full detail for one item: description, price, every modifier group with option ids and min/max, dietary tags, and the complete allergen map (contains | may_contain | unknown for each major allergen; unknown means the merchant has not said, so never treat it as safe), lead time, serves, plus availability at each location that sells it. Use before quoting anything with modifiers or when a customer has allergies. Next: quote_order.
Read-only.
| Parameter | Type | Notes |
|---|---|---|
item_idrequired | string |
check_availability
Check whether specific items can be ordered at a location for a given time. Honors stock (in_stock | low | sold_out | unknown, with quantity when tracked), item lead times (e.g. cakes need 48h), opening hours, and fulfillment mode. Returns per-item orderable, earliest_time, a reason when not orderable, and stale=true if the merchant's stock data has outlived its ttl. Use before quote_order for pre-orders, catering, or anything with a future desired_time. Next: quote_order, or search_menu for substitutes.
Read-only.
| Parameter | Type | Notes |
|---|---|---|
location_idrequired | string | |
item_idsrequired | string[] | |
desired_time | string | When the order should be ready (pickup) or arrive (delivery). Omit for ASAP. |
fulfillment | "pickup" | "delivery" | "dine_in" | "catering" | |
quantities | object | item_id → quantity wanted |
plan_group_order
Propose a cart that feeds a group: team lunch, catering, an offsite. Deterministic, no LLM inside.
Give headcount, budget_per_person (minor units, ALL-IN: tax and fees included), dietary_requirements as counts (e.g. {"vegetarian": 3, "gluten_free": 1}; each count is treated as different people), and desired_time.
It covers each dietary group with individual portions first, fills the rest with up to three mains for variety, then adds drinks (and dessert if asked) only if the budget allows.
Returns lines ready to pass to quote_order unchanged, a per-line breakdown of who each item covers, an estimate with per-person cost, a coverage report, any unmet constraints, and warnings (e.g. shared-kitchen gluten risk).
Next: show the plan to the customer, then quote_order with the same lines.
Read-only.
| Parameter | Type | Notes |
|---|---|---|
location_idrequired | string | |
headcountrequired | integer | |
budget_per_personrequired | integer | Minor units, all-in. 2000 = $20.00 |
dietary_requirements | { vegetarian, vegan, gluten_free, dairy_free, nut_free, halal, kosher } → number | |
avoid_allergens | "gluten" | "wheat" | "milk" | "egg" | "peanut" | "tree_nut" | "sesame" | "soy" | "fish" | "shellfish" | "mustard" | "sulphites"[] | Excluded for everyone, including items with unknown status |
desired_timerequired | string | |
fulfillment | "pickup" | "delivery" | "dine_in" | "catering" | Default pickup |
extras | "drinks" | "dessert"[] | Default ["drinks"] |
quote_order
Price a cart and lock it for 10 minutes. Required before place_order: there is no way to order without a quote. Validates everything an order can fail on: opening hours (CLOSED), delivery zone (OUTSIDE_DELIVERY_ZONE), stock (ITEM_SOLD_OUT), lead times (LEAD_TIME_NOT_MET), modifiers (INVALID_MODIFIERS), delivery minimum (MINIMUM_NOT_MET). Errors include suggested_next_tool and details such as earliest_time. Returns quote_id, itemized lines, subtotal, fees, tax, total (minor units), eta, expires_at, and a policy check. If policy.allowed is false, place_order will refuse; tell the customer why. Next: confirm the total with the customer, then place_order.
Changes state.
| Parameter | Type | Notes |
|---|---|---|
location_idrequired | string | |
linesrequired | { item_id, quantity, modifiers, notes }[] | |
fulfillmentrequired | "pickup" | "delivery" | "dine_in" | "catering" | |
desired_time | string | Ready time for pickup, arrival time for delivery. Omit for ASAP. |
delivery_address | { line1, line2, city, region, postal_code, country, lat, lng } | Required for delivery. Include lat/lng for radius-based zones. |
headcount | integer | For catering/group orders; checked against policy |
place_order
Turn a quote into a real order. Only call after the customer has seen the quote total and said yes. Requires an unexpired quote_id, a unique idempotency_key you generate (e.g. a UUID), customer contact (name plus email or phone), and confirm: true. Retrying with the same idempotency_key and quote returns the original order (idempotent_replay: true), never a duplicate. Safe to retry on timeouts. Fails with QUOTE_EXPIRED, QUOTE_ALREADY_USED, PRICE_CHANGED or ITEM_SOLD_OUT (re-quote), or POLICY_BLOCKED (spending policy; do not work around it). No card data is ever taken here: payment is at pickup, on invoice, or via a merchant-hosted link in order.payment. If order.dry_run is true, the order was recorded but NOT sent to the merchant; say so. Next: get_order_status.
Changes state. Safe to retry.
| Parameter | Type | Notes |
|---|---|---|
quote_idrequired | string | |
idempotency_keyrequired | string | |
customerrequired | { name, email, phone, company, notes } | |
confirmrequired | true | Must be true: the customer approved this exact total |
payment_method | "pay_at_pickup" | "invoice" | "payment_link" | Defaults to the merchant's first accepted method |
get_order_status
Track an order. Returns the current status (received, accepted, preparing, ready, out_for_delivery, delivered, picked_up, cancelled), a timestamped timeline, eta, and until when it can be cancelled. ttl_seconds says how long before checking again is useful. DRY_RUN orders stay "received" because they were never sent.
Read-only.
| Parameter | Type | Notes |
|---|---|---|
order_idrequired | string |
cancel_order
Cancel an order within the merchant's cancellation window (see cancellable_until on the order, or orderable://policies). Fails with CANCELLATION_WINDOW_CLOSED once the window has passed or the order is ready/out for delivery; details include the store phone number so a human can call. Cancelling an already-cancelled order succeeds again (idempotent). Only cancel when the customer asked to.
Changes state (destructive). Safe to retry.
| Parameter | Type | Notes |
|---|---|---|
order_idrequired | string | |
reasonrequired | string |
Errors
Errors come back as an MCP tool error whose text content is JSON:
{
"error": {
"code": "LEAD_TIME_NOT_MET",
"message": "Chocolate Celebration Cake (8 in) needs 48h notice. Earliest: 2026-10-09T13:00:00.000Z",
"suggested_next_tool": "check_availability",
"details": { "problems": [{ "item_id": "crumb-chocolate-cake", "earliest_time": "2026-10-09T13:00:00.000Z" }] }
}
}| Code | Meaning |
|---|---|
QUOTE_EXPIRED | The quote is older than 10 minutes. Quote again. |
QUOTE_NOT_FOUND | No such quote. Orders need a quote from quote_order. |
QUOTE_ALREADY_USED | This quote already became an order; details.order_id has it. |
ITEM_SOLD_OUT | Sold out, or fewer left than requested (details.problems[].available_quantity). |
ITEM_NOT_FOUND | The item doesn't exist at that location. |
ITEM_UNAVAILABLE | The item isn't offered for that fulfillment mode. |
INVALID_MODIFIERS | Missing or unknown modifier choices; the message lists them. |
MINIMUM_NOT_MET | Below the delivery minimum. |
OUTSIDE_DELIVERY_ZONE | The address is outside the location's delivery zone. |
CLOSED | Closed at that time; details.next_open_at and suggested_desired_time help. |
LEAD_TIME_NOT_MET | Needs more notice (e.g. cakes); details include earliest_time. |
POLICY_BLOCKED | The spending policy blocks it; details.violations explains. Don't work around it. |
PRICE_CHANGED | Prices moved since the quote. Quote again and reconfirm the total. |
LOCATION_NOT_FOUND | No such location. Call list_locations. |
FULFILLMENT_UNAVAILABLE | The location doesn't offer that mode. |
ORDER_NOT_FOUND | No such order. |
CANCELLATION_WINDOW_CLOSED | Too late to cancel; details include the store phone. |
IDEMPOTENCY_KEY_REUSED | The key was used for a different quote. Use a new key. |
INVALID_REQUEST | Something in the request is wrong; the message says what. |
ADAPTER_ERROR | The merchant's system failed or rejected the request. |
Resources
orderable://menu/{location_id}: the full menu with modifiers, allergens and availability.orderable://policies: cancellation, refund, payment and delivery fees, plus the agent spending policy and ordering rules.