Lumi MCP turns a restaurant POS into 18 typed tools any AI agent can call. No vendor SDK. No bespoke connector. Just the Model Context Protocol.
llms.txt, fetch tools.json for live schemas, paste mcp.json into your client.
python -m services.mcp_external
POST <host>/mcp/mcp
/tools.json
GET /api/external/agent_audit
# JSON-RPC over HTTP — no SDK required curl -X POST $LUMI_HOST/mcp/mcp \ -H "Authorization: Bearer $LUMI_TOKEN" \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# 1) find a merchant {"method":"tools/call","params":{"name":"merchant.search","arguments":{"area":"Central"}}} # 2) read its menu (sku is a closed enum, validated) {"method":"tools/call","params":{"name":"menu.get","arguments":{"merchant_id":"merch_..."}}} # 3) quote the order — show user the total before they confirm {"method":"tools/call","params":{"name":"order.calculate", "arguments":{"merchant_id":"merch_...", "items":[{"sku":"BEV-LATTE","quantity":2}]}}} # → returns { quote_id, total_hkd, expires_at, needs_review, ... } # 4) commit — quote_id is also a natural idempotency key {"method":"tools/call","params":{"name":"order.place", "arguments":{"quote_id":"q_...", "payment_token":"<jwt from payment.authorize>"}}}
{
"mcpServers": {
"lumi": {
"url": "https://<host>/mcp/mcp",
"transport": "streamable_http",
"headers": { "Authorization": "Bearer <your-token>" }
}
}
}
Two-stage commit (order.calculate → order.place(quote_id=…)) is the recommended path. The quote_id binds items + total + delivery_note at quote time, doubles as a natural idempotency key, and lets you preview the price before charging.
18 primary tools across 7 namespaces. Schemas live in tools.json. {REQ} = required arg; {IDEM} = accepts idempotency_key; {BEARER} = identity prefers Authorization header.
merchant_id to feed everything downstream.items[*].sku is the closed enum the agent must reuse verbatim.quote_id (10-min TTL) + frozen total + review flags. Show the user, wait for confirm.quote_id (recommended) or {merchant_id, items}. payment_token from payment.authorize charges immediately.cart_id.ui://lumi/cart/<id>.cart.update(qty=0).cart_id optional (falls back to the cardholder's most recent open cart).order.place. Cart transitions to checked_out.payment_token to order/cart commit tools.provider="hex" (default; needs token_id + cryptogram_wire) or provider="agenzo" (needs pm_id; fetches network token).amount_cents=0 = full. Logs into the unified audit ledger.namespace.verb.search_merchants, place_order, …) are kept as aliases for back-compat. New agents should use the dotted form.Authorization header is preferred.agent_id / cardholder_id args on tools are a fallback for stdio. Ignored when the header is present.idempotency_key. Same key on retry returns the original order without re-charging.quote_id auto-derives "q:<quote_id>" as the key.items[*].sku is a closed enum derived from the live menu.| Legacy name | Canonical |
|---|---|
search_merchants | merchant.search |
get_menu | menu.get |
place_order | order.place |
list_recent_orders | order.list |
payment.agenzo_charge | payment.charge(provider="agenzo") |