POST https://phantom.mealops.ai/mcp (Streamable HTTP), authenticated with Authorization: Bearer <agent-api-key>.
Tool list
The MCP server registers 20 tools. The list is scope-filtered per credential: tools your key lacks the scope for are not registered at all (a discovery-only key sees 7 tools, ~3k tokens of definitions, instead of the full 20). The filter mirrors call-time enforcement exactly, including theorders:submit → payments:start implication. Calling a tool your key can’t see returns the MCP “tool not found” error — if a tool seems missing, check your key’s scopes. Scope upgrades apply on the next request, no reconnect needed.
All output schemas are strict (
additionalProperties: false): a field not declared in a tool’s output schema is never passed through.
Freshness guarantees: agent listings always reflect the latest writes (concurrent duplicate searches share one computation, but results are never served from a stale cache). Menus read by search_menu_items may be up to 30 seconds stale, and every menu write invalidates that cache immediately. get_menu, validation, and quoting are never cached — they see availability flips instantly.
Order tools (get_order_status, get_order_tracking, cancel_order, update_order) enforce ownership: an agent may only touch orders it created. Foreign and missing orders both return Order <id> not found., so order ids are not enumerable across agents. Restaurant-side tools enforce only that the restaurant is live (ordering enabled, payout ready) — there are no per-restaurant agent permissions; approval is platform-wide.
Two tools carry their own per-agent cap on top of the shared quota, because one call costs far more than one call’s worth of work: search_menu_items (60/min — up to 25 menus scanned) and check_delivery_availability (60/min — a live, billable courier request). The budgets are independent: exhausting one leaves the other untouched.
Canonical behavior rules
- Authorization always stays server-side; a client can never widen its own scopes.
- Identity is stamped, never trusted:
order.agent_idis optional and filled in from your API key. Send a different one and the call throws. - Payment always runs after quote and before submit — every order is prepaid, and the hold must cover the order at submit and after any edit that re-prices it.
- All POS providers stay behind the same tool contract — clients never see provider-specific ordering logic.
- An input that cannot be honored is an error, not a silent default: contradictory availability flags (
open_now+requested_time), a half-supplied coordinate pair, andradius_mileswithout an origin all throw rather than returning a plausible answer to a different question. - Prefer server-resolved values (
resolvedMinLeadTimeMinutes,earliest_orderable_time, the quote total,check_delivery_availability) over recomputing them; fall back to components only for compatibility with an older Phantom.