§1 · The Two Paths
Two parallel commerce surfaces. One model, two implementations.
The AgentMall 4-Layer Model is universal. Restaurants do not change the model — they change how each layer is implemented, specifically because restaurants operate two fundamentally different commerce surfaces. Understanding which surface your restaurant lives on — or which combination — determines your entire build plan.
Path 1 · Restaurant-Direct
MCP Endpoint Wrapping POS API
An MCP server wraps your POS (Toast, Square, Clover), exposing menu, availability, and ordering tools without aggregator involvement. No per-transaction commission. Requires POS API access — which is gated.
Path 2 · Aggregator-Embedded
DoorDash / UberEats / Grubhub as the Commerce Layer
The aggregator IS your Layer 1 structured data, your Layer 2 API, and your discovery surface. Fast to launch; 15–30% commission on every delivery order. The aggregator's internal catalog drives agent discovery.
Path 1: Restaurant-Direct
An independent restaurant operating its own digital ordering wants an MCP endpoint that exposes menu, availability, pickup/delivery options, and ordering without paying aggregator commission on every transaction. The four-layer implementation stack on this path:
- Layer 1 (Structured Data): Schema.org
Restaurant + Menu + MenuItem markup embedded in the restaurant's website, or a JSON-LD endpoint served dynamically by the POS platform. Toast, Square, and Clover all have API paths that feed this layer.
- Layer 2 (API Endpoint): The POS API — Toast at
https://toast-api-server, Square Catalog API via POST /v2/catalog/search, Clover REST at https://api.clover.com/v3/merchants/{mId}/items — is the underlying truth. The restaurant's ordering endpoint receives order injection.
- Layer 3 (MCP): A thin server wrapping the POS API, exposing
search_menu, get_item, check_availability, place_order, and get_order_status. See MCP protocol details.
- Layer 4 (UCP): Delivery time windows, "ready in 30 min" semantics, delivery fee calculation, driver tip handling. For direct restaurants using Toast Delivery Services, this is a flat per-order rate rather than a percentage commission. See UCP deep dive.
Access Gate — Re-verify Before Launch
Toast API access requires either the Partner Connect add-on (~$25/month, re-verify before launch) or formal integration partnership. The read-only sandbox is in beta as of this writing — write access (order injection) requires formal partner onboarding. This access friction is the primary obstacle for restaurant-direct agent commerce today.
Path 2: Aggregator-Embedded
For a restaurant whose primary discovery and ordering surface is DoorDash, UberEats, or Grubhub, the aggregator is the agent commerce layer. Agents querying "pad thai near me" surface results from these platforms' catalogs. The restaurant's menu in the aggregator's system is the de facto Layer 1 structured data. Commission fees are baked into every transaction at 15–30%.
The practical reality: most restaurants operate both paths simultaneously — aggregators for discovery and incremental orders, direct channels for loyal repeat customers. Agent commerce makes this hybrid more important: an agent serving a repeat customer can be configured to prefer the lower-cost direct channel when the restaurant exposes one.
§3 · Aggregator Landscape
Commission rates, API access, and agent implications — re-verify all before launch.
All three major US aggregators charge percentage-based commissions on marketplace delivery orders, with lower rates for pickup. These rates are volatile — re-verify against the DoorDash Merchant Pricing, UberEats Merchant Pricing, and Grubhub pricing pages before publication or any financial model.
| Platform / Plan | Delivery Commission | Pickup Commission | API Access for Agents | Notes (re-verify before launch) |
| DoorDash Basic | 15% | 6% | Drive API production restricted; sandbox open; no public consumer ordering API | Smallest delivery radius; no DashPass access; 7-day 0% intro |
| DoorDash Plus | 25% | 6% | Same as above | Most popular; DashPass access; 30-day 0% intro |
| DoorDash Premier | 30% | 6% | Same as above | Widest radius; order growth guarantee; 30-day 0% intro |
| DoorDash Drive (white-label) | Flat fee per delivery | N/A | POST https://openapi.doordash.com/drive/v2/deliveries (JWT auth, production restricted) | White-label fulfillment; no marketplace listing; fee returned in API response |
| UberEats Lite | 20% | 7% | Marketplace APIs require written approval and OAuth 2.0; 4–8 week integration | Basic marketplace listing |
| UberEats Plus | 25% | 7% | Same as above | Increased discoverability; Uber One orders add 5% |
| UberEats Premium | 30% | 7% | Same as above | Highest discoverability; lowest customer delivery fee |
| UberEats Self-Delivery | 15% | 7% | Same as above | Restaurant uses own drivers; Uber overflow at 25% |
| Grubhub Basic | 5% marketing + ~10% delivery | N/A | Developer portal — POS/partner program only; not self-serve for production | Self-delivery restaurants in Grubhub markets |
| Grubhub Plus | 15% marketing + ~10% delivery | N/A | Same as above | Grubhub driver network access |
| Grubhub All-Access | 20% marketing + ~10% delivery | N/A | Same as above | Full marketing tools; ~3.05% + $0.30 payment processing separate |
| Toast Delivery Services (TDS) | Flat $6.99–$9.99/delivery | N/A | Toast Online Ordering + Drive/Uber Direct backend | Commission-free direct ordering; regulatory surcharges in CA, NYC, Seattle |
Agent Commerce Layer Reality
Neither DoorDash Marketplace nor UberEats provides a public API for placing consumer orders on behalf of a third-party agent. The aggregator IS the agent commerce layer on Path 2 — but only for agents operating inside those platforms' own surfaces. A third-party agent cannot programmatically submit a DoorDash Marketplace order without the consumer completing checkout in the DoorDash app. The only publicly accessible ordering path for external agents is the restaurant-direct stack (Path 1) via POS API or an MCP wrapper.
Toast Delivery Services: the flat-rate direct alternative
Toast Delivery Services uses per-delivery flat rates via Uber Direct or DoorDash Drive as the fulfillment network, decoupled from marketplace commission. For a $40 order, a 30% aggregator commission costs $12 per order — TDS flat rates are material savings at higher order values. California, NYC, and Seattle add regulatory fees of $2.00–$5.00 per delivery on top of the base rate.
§4 · POS as the Underlying Truth
The POS is your Layer 1 and Layer 2. Four platforms, one decision tree.
The POS holds the canonical menu, availability data, modifier structure, and pricing. Every agent interaction with a restaurant's data ultimately traces back to the POS. The decision between POS platforms determines your API access model, your modifier richness, and your delivery configuration options.
| POS | Menu API | Order API | Developer Access Model | Agent-Commerce Notes |
| Toast | GET https://toast-api-server/menus/v2/ — full hierarchy with modifier groups, channel visibility, 86'd status. Metadata check: GET /menus/v2/v2/metadata | Toast Online Ordering (partner-level); write access requires formal onboarding | Partner Connect ~$25/mo (re-verify); read-only sandbox in beta as of this writing — flag; OAuth 2.0 client credentials | Richest restaurant-specific data; dominant full-service US POS; POS-agnostic abstraction recommended |
| Square for Restaurants | POST /v2/catalog/search — 3-call sync pattern; modifier lists as first-class objects; channel visibility via channels array | POST /v2/orders — accessible to third-party developers | Standard OAuth 2.0 merchant authorization; Square Developer account; most accessible path | Best developer experience; modifier lists structured (not text); kitchen_name vs buyer_facing_name distinction |
| Clover | GET /v3/merchants/{mId}/items (100/page); GET /v3/merchants/{mId}/categories/{categoryId}/items; expand=categories | POST /v3/merchants/{mId}/orders; POST /v3/merchants/{mId}/orders/{orderId}/line_items | OAuth 2.0; sandbox: https://apisandbox.dev.clover.com; OLO fields require special permissions (contact developer-relations@clover.com) | Well-documented REST API; reasonable second choice after Square; modifier availability via GET modifier_groups |
| TouchBistro | No public REST API; data accessible via integration marketplace (DoorDash Online Ordering, Flipdish, MarginEdge) | No direct order injection path for third parties | Integration marketplace only; middleware (Otter, KitchenHub) is the practical path | Not suitable for restaurant-direct MCP without middleware layer |
Toast Partner Connect — Beta Flag — Re-verify Before Launch
Toast Partner Connect costs approximately $25/month and provides read-only API access for self-serve integrations. The read-only sandbox is in beta as of this writing. Write access — order injection — requires formal integration partnership, not just the Partner Connect add-on. The actual production API host is provided during partner onboarding; the documentation uses https://toast-api-server as a placeholder. Re-verify both the pricing and sandbox availability against current Toast partner documentation before building.
Toast Menus API v3 — the metadata-first pattern
Before pulling the full menu hierarchy, always check the lightweight metadata endpoint to avoid unnecessary bandwidth:
GET https://toast-api-server/menus/v2/v2/metadata
Header: Toast-Restaurant-External-ID: {restaurantGuid}
Response: { "restaurantGuid": "a1b2c3d4-...", "lastUpdated": "2026-06-03T18:42:00Z" }
If lastUpdated is newer than your agent's cached version, re-fetch. Otherwise, serve from cache. This pattern is essential for high-traffic implementations where pulling full menu data on every agent query would be prohibitive.
Square Catalog API — three-call sync pattern
# Call 1: root MENU_CATEGORY objects
POST /v2/catalog/search
{ "object_types": ["CATEGORY"], "query": { "prefix_query": { "attribute_name": "category_type", "attribute_prefix": "MENU_CATEGORY" } } }
# Call 2: child categories under each root
POST /v2/catalog/search
{ "object_types": ["CATEGORY"], "query": { "item_variations_query": { "item_variation_filter": { "category_ids": ["<root_id>"] } } } }
# Call 3: all items, variations, modifiers, images, taxes
POST /v2/catalog/search
{ "object_types": ["ITEM","ITEM_VARIATION","MODIFIER","MODIFIER_LIST","IMAGE"],
"include_related_objects": true }
The 30-Day AgentMall Newsletter
One operator note per week. The restaurant-direct build in your inbox.
POS API access updates, real-time 86 patterns, ghost kitchen agent commerce, and the next vertical spoke as it ships. No fluff. Cancel any time.
§5 · 4-Layer Model × Restaurants
Layer-by-layer implementation: what changes for restaurants.
The 4-Layer Model is universal. What restaurants add: time-sensitive menus, modifier complexity, delivery logistics, and the tip-and-fee payment contract. This table maps each layer to the restaurant-specific implementation reality.
| Layer | Generic Default | Restaurant-Specific Implementation | Gap or Constraint |
| Layer 1 · Structured Data |
Schema.org Product + Offer |
Schema.org Restaurant + Menu + MenuItem + MenuSection. Dynamic JSON-LD served from POS API at /menu.jsonld. suitableForDiet for 11 diet values. additionalProperty for allergens and modifier groups. |
No native modifier schema. No allergen enumeration. Static markup goes stale within hours — must be dynamically regenerated from POS. |
| Layer 2 · API Endpoint |
8-canonical-endpoint commerce API |
Toast Menus API (GET /menus/v2/), Square Catalog API (POST /v2/catalog/search), Clover REST (GET /v3/merchants/{mId}/items), DoorDash Drive (POST /drive/v2/deliveries). Aggregator path: UberEats Marketplace API (partner-approval required), Grubhub developer portal (partner-only). |
All major APIs are gated — Toast requires Partner Connect or formal partnership; UberEats and Grubhub require written approval; DoorDash Drive production is restricted. |
| Layer 3 · MCP Tool Description |
Generic product search + cart + checkout tools |
search_menu, get_menu (Resource), get_item (Resource), check_availability (Resource — live 86 status), get_delivery_estimate (Tool — DoorDash Drive quote), place_order (Tool — mandatory user confirmation gate), get_order_status (Tool — Drive webhook or POS polling). |
No native restaurant MCP from any major platform as of this writing. Community patterns exist (foodapp://restaurants/{id}/menu URI, food_delivery_mcp on GitHub). See MCP spoke. |
| Layer 4 · UCP Compatibility |
Single-step consumer checkout |
Delivery time windows ("ready in 30 min" semantic — not arbitrary window). pickup_window and dropoff_window ISO-8601 UTC datetimes from DoorDash Drive. Tip field separate from order_value (both in cents). Allergen/dietary confirmation as pre-order UCP check. DoorDash Drive pre-quote flow (/drive/v2/quotes) before committing. See UCP deep dive. |
Time-window semantics are restaurant-specific SLAs, not arbitrary scheduling. The fee field from Drive response is the authoritative delivery cost — never calculate from flat-rate tables (regulatory surcharges apply in CA, NYC, Seattle). |
MCP tool surface — restaurant-specific
| Tool / Resource | MCP Primitive | Description | Underlying API |
get_restaurant_info | Resource | Hours, location, cuisine, payment methods | Toast Restaurant Info API or Schema.org |
get_menu | Resource | Full menu with sections, items, prices, modifier groups | Toast Menus API v3 or Square Catalog API |
get_item | Resource | Single item with modifiers, nutrition, dietary tags, allergens | POS item endpoint |
check_availability | Resource | Live item stock status — is this item 86'd right now? | Toast Availability API or Clover modifier availability |
get_delivery_estimate | Tool | Delivery fee and ETA for a given address — call Drive /quotes before committing | DoorDash Drive Quote or Uber Direct pricing |
place_order | Tool (confirmation required) | Submit order with item and modifier selections — MUST require user confirmation before execution | Toast Online Ordering or Square Orders API |
get_order_status | Tool | Current order state and delivery tracking | POS Orders API or DoorDash Drive GET delivery |
§6 · Ghost Kitchens
CloudKitchens, REEF, and Otter — N virtual brands, one physical kitchen.
Ghost kitchens multiply the agent commerce problem by N virtual brands. A single REEF vessel or CloudKitchens facility may host 5–7 delivery brands simultaneously on DoorDash, UberEats, and Grubhub — creating up to 21 distinct aggregator storefronts from a single physical location.
The operators
| Operator | Model | Scale | Software Stack |
| CloudKitchens (City Storage Systems) | 200–300 sq ft commercial kitchen spaces within delivery hubs; each facility includes basic equipment, order aggregation software, and on-site fulfillment team | 100,000+ restaurants via Otter; Otter processes ~18% of US online food delivery orders (re-verify) | Otter — order aggregation at $99/$149/month + POS at $19/$59/month (re-verify). Otter consolidates orders from UberEats, DoorDash, Grubhub, Postmates into a single tablet. |
| REEF Technology | Converts parking lots and garages into ghost kitchen "vessels" — mobile kitchen trailers ~shipping-container size; each vessel hosts up to 6–7 brands | 50+ vessels across 18+ US markets; partner brands include Wendy's (up to 700 delivery-only locations), TGI Fridays, Milk Bar | Orders flow through major delivery aggregators; no proprietary external-facing API |
Agent commerce implications: brand separation is mandatory
A single CloudKitchens or REEF facility may serve 5–7 brands simultaneously — meaning one physical prep environment generates N distinct restaurant identities in agent systems. Each brand requires:
- Its own Layer 1 structured data (distinct menu per brand, distinct
Restaurant JSON-LD entity)
- Its own aggregator menu, maintained in sync via Otter or direct aggregator API calls
- Its own order routing (all orders funnel to one kitchen tablet/KDS — Otter handles this)
- Its own agent-facing MCP resource URI (
foodapp://restaurants/{brand-id}/menu) if going restaurant-direct
Menu sync bottleneck
An 86'd ingredient shared across multiple virtual brands needs to propagate to all affected brand menus within minutes — not hours. Otter handles this for the POS/KDS layer; the Schema.org and aggregator menu layers require API-level sync (UberEats Menu API, DoorDash menu management) to propagate in near-real-time. No ghost kitchen operator currently offers a public API for external agent access — the stack is Otter + aggregator APIs. An MCP server for a ghost kitchen would wrap Otter's data or the aggregator's menu APIs, not a ghost-kitchen-specific endpoint.
Aggregator Storefront Count at Scale
A CloudKitchens facility with 6 brands × 3 aggregators = 18 distinct consumer-facing storefronts managed from a single kitchen. Each storefront needs its own menu, its own availability state, and its own agent identity. The agent commerce layer must maintain brand separation even when the operational layer consolidates to one tablet.
§7 · Worked Example
Toast + DoorDash Drive: end-to-end agent flow.
Scenario: an AI agent handles the request "Order pad thai for delivery to 123 Oak St from Thai Garden." This walkthrough traces every system call from discovery to delivered order.
Step 1 — Restaurant discovery
The agent queries a restaurant index (DoorDash Marketplace, Google Places with Restaurant structured data, or a local restaurant MCP server). The query resolves "Thai Garden near 123 Oak St" and returns the restaurantGuid, confirms operating hours (open), delivery availability (true), and POS type (Toast).
Step 2 — Menu retrieval via Toast Menus API
# Check metadata first — avoid unnecessary full-menu bandwidth
GET https://toast-api-server/menus/v2/v2/metadata
Header: Toast-Restaurant-External-ID: a1b2c3d4-1234-5678-abcd-ef0123456789
# Response: { "restaurantGuid": "a1b2c3d4-...", "lastUpdated": "2026-06-03T18:05:00Z" }
# lastUpdated is < 1 hour ago — proceed with full fetch
GET https://toast-api-server/menus/v2/
Header: Toast-Restaurant-External-ID: a1b2c3d4-1234-5678-abcd-ef0123456789
The MCP get_menu Resource parses the menu hierarchy and exposes it to the agent. The agent locates "Pad Thai" in the Noodles section, finds base price $14.95, modifier groups (protein, spice, size), dietary tag (GlutenFreeDiet), and allergens (peanuts, egg).
Step 3 — Item resolution and modifier confirmation
The agent surfaces modifier options to the user: "Which protein — tofu, chicken, shrimp, or beef? Beef is +$2.00. Spice level — mild, medium, hot, or extra hot?" User responds: "Chicken, medium spice." The agent also surfaces the allergen warning (peanuts, egg) for user acknowledgment — this is a Layer 4 UCP-level check, not just data enrichment.
Step 4 — Pre-order availability check
Before calling place_order, the MCP server calls the Toast Availability API to confirm the Pad Thai item is not currently 86'd. Only after a live availability confirmation does the agent proceed to order placement.
Step 5 — Order placement via Toast Online Ordering API
The agent calls the MCP place_order Tool (with mandatory user confirmation gate) which translates to a POST to the Toast Online Ordering endpoint. The order payload includes restaurant GUID, item GUID, modifier selections (chicken, medium), delivery address, and user contact. Toast injects the order to the kitchen and returns an orderId. If the restaurant uses Toast Delivery Services with DoorDash Drive, Toast automatically triggers the Drive delivery creation.
Step 6 — DoorDash Drive delivery creation (direct integration path)
If the application calls DoorDash Drive directly rather than via Toast TDS, the JWT is generated first:
# JWT generation (HS256, DD-JWT-V1)
Header: { "alg": "HS256", "dd-ver": "DD-JWT-V1", "kid": "<key_id>", "typ": "JWT" }
Payload: { "aud": "doordash", "iss": "<developer_id>", "kid": "<key_id>",
"exp": <now + 300>, "iat": <now> }
Signature: HMAC-SHA256(base64url(header) + "." + base64url(payload), base64decode(signing_secret))
# Create delivery
curl -X POST https://openapi.doordash.com/drive/v2/deliveries \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{
"external_delivery_id": "TG-ORDER-20260603-001",
"locale": "en-US",
"pickup_address": "421 Elm Street, Austin, TX 78701",
"pickup_business_name": "Thai Garden",
"pickup_phone_number": "+15551234567",
"pickup_instructions": "Order in bag at front counter. Order #1042.",
"pickup_reference_tag": "Order #1042",
"dropoff_address": "123 Oak Street, Austin, TX 78702",
"dropoff_phone_number": "+15559876543",
"dropoff_contact_given_name": "Alex",
"dropoff_contact_family_name": "Rivera",
"dropoff_contact_send_notifications": true,
"dropoff_instructions": "Ring doorbell, leave at door.",
"order_value": 1695,
"items": [
{
"name": "Pad Thai - Chicken, Medium Spice",
"description": "Pad Thai with chicken protein, medium spice level",
"quantity": 1,
"external_id": "MENU-PADTHAI-001",
"price": 1695
}
],
"tip": 400,
"contactless_dropoff": true,
"action_if_undeliverable": "return_to_pickup",
"dasher_allowed_vehicles": ["car", "bicycle"]
}'
The API response returns the fee field (delivery fee in cents), support_reference, and delivery tracking ID. The agent extracts the fee and estimated delivery time and surfaces both to the user before final confirmation. The user approves; the delivery is committed.
Step 7 — Order status tracking
GET https://openapi.doordash.com/drive/v2/deliveries/TG-ORDER-20260603-001
Header: Authorization: Bearer <JWT>
# Returns delivery state:
# enroute_to_pickup → picked_up → enroute_to_dropoff → delivered
DoorDash Drive also fires webhooks at each state change — the MCP server can expose these as real-time status updates back to the agent and user.
§8 · The 86'd-Item Problem
Real-time availability: the gap that breaks agent ordering.
Menu freshness matters more for restaurants than for almost any other vertical. A product catalog for a clothing retailer might be accurate for days; a restaurant's menu can have 86'd items within hours — sometimes within minutes during a Friday dinner rush. An agent that reads a menu at 6:00 PM and places an order at 8:30 PM may be working from a menu that no longer reflects reality.
Why static Schema.org markup fails for restaurant ordering
Static Schema.org JSON-LD embedded in a restaurant's HTML is an availability snapshot, not a live feed. Offer.availability: "https://schema.org/InStock" reflects the state when the markup was last updated — which may have been days ago. An agent reading only static markup has no way to know that the salmon special sold out at 7:15 PM.
The live availability architecture
The solution is layered availability checking at multiple points in the agent flow:
- Menu cache invalidation: Subscribe to Toast Events or Clover Inventory webhooks. When item availability changes at the POS, the webhook fires immediately — the MCP server invalidates its cache and re-fetches from the live API.
- Pre-order availability check: The MCP
check_availability Resource must query the live availability API immediately before place_order is invoked — not rely on the cached menu state from the earlier get_menu call.
- Toast Availability API: Returns item-level availability (is this item currently 86'd?). This is separate from the Menus API and must be called on the path to order placement.
- Clover modifier availability:
GET /v3/merchants/{mId}/modifier_groups/{modGroupId}/modifiers/{modId} — the available field on individual modifiers is queryable in real time.
Ghost kitchen amplification
Ghost kitchens compound the 86'd-item problem. If a shared ingredient is depleted in one REEF vessel, all virtual brands running that ingredient must update their availability simultaneously across all aggregator storefronts. Otter handles the KDS-layer propagation; the Schema.org and aggregator API layers require explicit sync calls. An MCP server for a ghost kitchen must treat each brand's availability as independent state, even if the underlying ingredient list is shared.
| Availability Signal | Source | Latency | Use in Agent Flow |
| Schema.org Offer.availability | Static markup on restaurant website | Hours to days stale | Discovery only — never use for order confirmation |
| Aggregator catalog page | Aggregator's cached version of restaurant menu | Minutes to hours stale | Discovery only — not reliable for order-time availability |
| Toast Availability API | Live POS state | Real-time | Required before place_order invocation |
| Clover modifier available field | Live POS state | Real-time | Required for modifier availability pre-order |
| POS webhook (Toast Events, Clover webhooks) | Event-driven push from POS | Seconds | Cache invalidation; proactive MCP state update |
§9 · Common Mistakes
Eight ways restaurant agent integrations fail in production.
1. Treating Schema.org JSON-LD as sufficient for agent ordering
Schema.org markup tells an agent what items exist and their base prices. It does not expose which modifiers are required, their upcharges, or which items are currently available. An agent that reads a restaurant's Schema.org markup and attempts to submit an order will fail at the modifier-selection step. Fix: expose modifier data via the POS API — Toast menuItemModifierGroups, Square CatalogModifierList, Clover /v3/merchants/{mId}/modifier_groups. The MCP get_item Resource must include structured modifier groups with prices and selection rules, not just description text.
2. Caching menu data without checking the metadata endpoint
A menu accurate at 10 AM may have 86'd items by 8 PM. Agents caching full menu data without checking freshness will surface unavailable items, resulting in order cancellations and degraded user experience. Fix: for Toast, always call GET https://toast-api-server/menus/v2/v2/metadata first — if lastUpdated is newer than cached, re-fetch. For Square, use SearchCatalogObjects incremental updates with a cursor from the previous sync to get only changed objects.
3. Conflating DoorDash Marketplace commission with DoorDash Drive fees
DoorDash Marketplace (the consumer app) charges 15–30% commission. DoorDash Drive is a white-label delivery API that charges per-delivery flat fees. These are separate products. A restaurant using its own ordering channel and DoorDash Drive pays Drive fees, not Marketplace commission. Fix: identify which product you are using before building economic models. If on Toast Online Ordering + TDS, the fee is TDS's flat rate. If building a direct Drive integration, the fee is returned in the fee field of the Create Delivery response in cents.
4. Attempting direct consumer-facing UberEats or Grubhub integrations without partner approval
UberEats Marketplace APIs and Grubhub's developer portal require written approval, integration review, and — for UberEats production certification — a 99% injection success rate. They are not self-serve for production use. Fix: route through a middleware platform (Otter, KitchenHub, Chowly) that already holds partner status, or engage aggregator partnership teams directly. For new builds, DoorDash Drive is the most accessible API for production use — the sandbox is open and production registration intent is accepted at the developer portal.
5. Building an MCP server without handling the 86'd-item real-time path
An agent that reads a menu and places an order may select an item that was 86'd between menu read and order placement. This creates order cancellations and degraded user experience. Fix: the MCP check_availability Resource must query the live availability API immediately before the place_order Tool is invoked. Do not rely on cached menu availability data for the order confirmation step. Subscribe to POS webhooks to invalidate cache proactively.
6. Exposing a ghost kitchen's N virtual brands as a single restaurant entity
Ghost kitchens running 5–7 brands from one facility are N distinct restaurants from the agent's perspective. Combining them into a single entity produces incorrect menu data, ordering failures, and confused users. Fix: each virtual brand must have its own MCP Resource URI (foodapp://restaurants/{brand-id}/menu), its own structured data entity, and its own ordering pathway. Otter handles back-end consolidation; the agent-facing layer must maintain brand separation.
7. Ignoring pickup order economics in agent routing
All three major aggregators charge a substantially lower commission on pickup orders (6–7%) versus delivery (15–30%). Agents optimizing for delivery miss that pickup is dramatically cheaper for restaurants. Fix: explicitly route pickup-eligible orders through the lower-commission path when the user is within practical pickup distance. Build pickup availability into the get_delivery_estimate Tool response — surface both delivery (fee + ETA) and pickup (no delivery fee, estimated ready time) options.
8. Not accounting for regulatory surcharges in California, NYC, and Seattle
DoorDash Drive and Toast Delivery Services add mandatory regulatory fees — approximately $2.00 in California, $2.99–$3.00 in New York City, and $4.99–$5.00 in Seattle per delivery. An agent quoting delivery cost without these surcharges gives users inaccurate pricing. Fix: the DoorDash Drive API returns the total fee (including regulatory surcharges) in the fee field of the delivery response. Always use the returned fee value — never calculate delivery cost server-side from flat-rate tables.
§10 · FAQ
Frequently asked questions.
Can an AI agent order food directly from a restaurant without going through DoorDash, UberEats, or Grubhub?
Yes, but it requires the restaurant to have either a direct ordering channel (Toast Online Ordering, Square Online, a custom website order API) or an MCP server wrapping their POS API with a place_order tool. Without one of these, the restaurant has no agent-accessible ordering endpoint. The aggregator platforms do not provide public consumer-facing order APIs for third-party agents. In the US, this path requires a custom build per restaurant or POS platform — the access friction is real and currently the primary obstacle for restaurant-direct agent commerce.
What does a restaurant's MCP server actually need to expose to be agent-commerce ready?
At minimum: a get_menu Resource (full menu with items, prices, modifiers, dietary tags), a check_availability Resource (live stock status), a get_delivery_estimate Tool (fee and ETA for a given address), a place_order Tool (with a mandatory user confirmation gate before execution), and a get_order_status Tool. Optionally: get_restaurant_info Resource (hours, location, cuisine) and a search_menu Tool for semantic search within the menu. The MCP tool/resource distinction matters: Resources are read-only and application-controlled; Tools are agent-invoked and have side effects. See the MCP spoke at /agentmall_spoke_mcp for protocol details.
Which POS system gives the most accessible path to building a restaurant MCP server?
Square is currently the most developer-accessible. The Catalog API uses standard OAuth 2.0 merchant authorization, is well-documented, and provides menu hierarchy (categories, items, variations, modifier lists) plus an Orders API for order creation. Toast offers richer restaurant-specific data — prep times, channel-specific menus, delivery configuration — but requires the Partner Connect add-on (~$25/month, re-verify before launch) or formal integration partnership. The Toast read-only sandbox is in beta as of this writing; write access requires formal onboarding. Clover's REST API is accessible and well-documented, making it a reasonable second choice after Square.
What is DoorDash Drive and how does it differ from being listed on the DoorDash Marketplace?
DoorDash Drive (POST https://openapi.doordash.com/drive/v2/deliveries) is a white-label delivery fulfillment API. It provides access to the Dasher network for any application — a restaurant's own website, a Toast Online Ordering channel, or a custom app — without requiring the restaurant to be listed on the DoorDash consumer marketplace. The restaurant pays a per-delivery flat fee returned in the API response as the fee field, rather than a percentage commission. The consumer never sees DoorDash branding. The DoorDash Marketplace is the consumer app with percentage-based commissions (15–30%) and full marketing exposure. A restaurant can use both: list on the Marketplace for discovery, and use Drive for white-label fulfillment from their direct channel.
How do ghost kitchens handle menu updates across 5–7 virtual brands simultaneously?
The operational tool is typically Otter (CloudKitchens' software arm) or a similar order aggregation platform such as KitchenHub or Chowly. Otter maintains a master menu synced from the POS and pushes changes to each aggregator's API when items are 86'd or prices change. The aggregator APIs (UberEats Menu API, DoorDash menu management) receive the updates and propagate them to the consumer-facing catalog. For an agent commerce layer, an MCP server wrapping a ghost kitchen operation would need to query Otter's data or each aggregator's menu API directly — there is no single ghost kitchen menu API. Each virtual brand is a separate data entity.
Is there a Halal or Kosher flag that agents can reliably use when filtering restaurant menus?
schema.org/HalalDiet and schema.org/KosherDiet are valid RestrictedDiet values for MenuItem.suitableForDiet. They indicate the restaurant claims the item is suitable for those diets. However, Schema.org markup is self-reported and not verified. For strict compliance, agents should surface the item's halal or kosher tag to the user but note that verification — certification body, kashrut authority — is the user's responsibility. Aggregator platforms do not provide verified halal or kosher flags beyond whatever the restaurant self-reports in their menu data.
What happens to menu data if a restaurant switches POS systems from Toast to Square?
The Schema.org JSON-LD served by the restaurant's website, if dynamically generated from the POS API, would need to be regenerated from the new POS. Any MCP server built on Toast API endpoints would need to be rebuilt against the Square Catalog API. Aggregator menus would need to be re-ingested via the new POS's aggregator integration — Square partners with UberEats and others via direct integrations. This is the key reason the restaurant-direct MCP approach requires a POS-agnostic abstraction layer: the MCP tool descriptions should not hard-code POS-specific endpoint paths. The place_order Tool's internal implementation changes; its interface to the agent should not.
What are the real agent-facing limitations of using DoorDash Marketplace or UberEats as the agent commerce layer?
Three material limitations: (1) No public ordering API — neither DoorDash Marketplace nor UberEats provides a public API for placing orders on behalf of a consumer; an agent cannot programmatically place a Marketplace order without the consumer completing checkout in the platform's own app or website. (2) Commission on every order — every order placed through the aggregator carries 15–30% commission, giving the restaurant no lower-cost path for loyal repeat customers reached via agent. (3) No control over menu freshness in the agent's context — if an agent queries a restaurant's aggregator page to surface menu data, that data is the aggregator's cached version, not the POS's live data; 86'd items may still appear.
§11 · Step-by-Step
Building a restaurant-direct agent commerce layer, in five steps.
Each step mirrors the HowTo JSON-LD at the top of this page word for word. Execute in order. The access-provisioning steps (POS API credentials, DoorDash Drive production access) add latency that the technical build does not — plan for 2–4 weeks total calendar time.
Step 1 — Establish POS API access and generate live Schema.org menu markup
Get API credentials for your POS: Square via the OAuth flow at developer.squareup.com; Toast by requesting the Partner Connect add-on (~$25/month, re-verify before launch — read-only sandbox is in beta); Clover via a developer account and OAuth app registration. Write a script that calls the POS Catalog or Menus API on a schedule or via webhook and generates a valid Schema.org JSON-LD document at a public URL such as https://yourrestaurant.com/menu.jsonld. Include Restaurant, Menu, MenuSection, MenuItem, NutritionInformation, and suitableForDiet properties. Serve modifier data via additionalProperty fields, and ensure offers.availability reflects live stock status.
Step 2 — Build the MCP server resource and tool layer
Create an MCP server (reference /agentmall_spoke_mcp for protocol details) that exposes get_restaurant_info and get_menu as Resources (read-only, application-controlled), and check_availability, get_delivery_estimate, place_order, and get_order_status as Tools (agent-invoked, side-effecting). For place_order, implement a mandatory user confirmation step before submitting the order to the POS — a restaurant order has real-world side effects and this gate is not optional. For get_delivery_estimate, call the DoorDash Drive quote endpoint or Uber Direct pricing API to return a real fee and ETA.
Step 3 — Wire delivery fulfillment via DoorDash Drive or Toast Delivery Services
If using DoorDash Drive directly: register at developer.doordash.com, create an access key to get your developer_id, key_id, and signing_secret, generate a JWT using HS256 with header dd-ver: DD-JWT-V1, and call POST https://openapi.doordash.com/drive/v2/deliveries with the order payload. The fee field in the response is the delivery charge in cents — submit this to the user before final confirmation. If using Toast Delivery Services, configure TDS within Toast Web and Toast handles the Drive or Uber Direct handoff automatically; fees are withheld from credit card payouts.
Step 4 — Implement real-time 86 and availability checks
Before any place_order Tool invocation, call the live availability endpoint: Toast Availability API, Clover GET /v3/merchants/{mId}/modifier_groups/{modGroupId}/modifiers/{modId} for modifier availability, or the equivalent for your POS. If an item or required modifier is unavailable, surface the error to the agent and user before attempting the order. Subscribe to POS webhooks — Toast Events, Clover Inventory webhooks — to invalidate cached menu data when availability changes so the agent never offers a menu that is hours stale.
Step 5 — Test the full agent flow end-to-end in sandbox environments
Use DoorDash Drive's sandbox — create a sandbox access key at developer.doordash.com and use the Delivery Simulator to advance through Dasher-assigned, picked-up, and delivered states. Test the complete flow: agent queries menu, surfaces modifier options, user confirms selection, place_order executes, Drive delivery is created, and get_order_status returns tracking. Verify that allergen and dietary data surfaces correctly in the get_item Resource response, and that the place_order confirmation includes the delivery fee from the Drive response fee field and the estimated delivery time before the user's final approval.
§12 · Continue the Guide
Next stops in the AgentMall guide.
Verticals · Hub
Vertical Agent Malls Roundup
The hub page surveying all 6 verticals — B2B procurement, travel, grocery, healthcare, and restaurants — plus the decision framework for picking your vertical.
Platform · Commerce
Shopify Agent-Ready Build
The platform analog for restaurant operators using Shopify for online ordering — Schema.org via Liquid, Storefront API, native MCP at /api/mcp, and the UCP checkout hook.
Pillar
The Full AgentMall Roadmap
The pillar page that ties all four layers and every vertical and platform spoke together into one 30-day operator plan.
Layer 3 · Protocol
MCP — Model Context Protocol
Tool schemas, JSON-RPC envelope, transports, and the server framework for the restaurant MCP layer — get_menu, check_availability, place_order.
Layer 4 · Protocol
UCP — Universal Commerce Protocol
Delivery time-window semantics, tip and fee handling, the payment confirmation state machine — all the Layer 4 details unique to restaurant delivery.
Vertical · B2B
B2B Wholesale & Agent Procurement
Net-30, quoted pricing, multi-level approval, and the buyer-agent protocol for the structurally different world of B2B commerce.
Vertical · Travel
Travel & Hospitality via AI Agents
GDS, NDC, PNR mechanics, and the loyalty-credential delegation problem unique to hotel and airline booking agents.
Vertical · Pet
Agent Commerce for Pet Products
Autoship, prescription meds, the three buyer segments, and the honest account of why Chewy has no public consumer API for third-party agents.
Layer 1 · Reference
Product Data — The 20-Field MVP
Field-by-field reference for the Schema.org block that gets any product — including restaurant menu items — discoverable across every agent runtime.
The Window
The window for restaurant-direct agent commerce is opening now.
DoorDash Drive's sandbox is open. Square's Catalog API requires no partnership approval. Toast's read-only sandbox is in beta. The operators who close all four layers — Schema.org menu markup, POS API wrapper, MCP tool layer, delivery fee semantics — before the aggregators build native agent ordering surfaces will have the channel economics advantage that compounds over every subsequent order. The 15–30% commission on aggregator-mediated repeat customers is the cost of waiting.
Open the AgentMall Roadmap →