QR code to paid order in one conversation
Each truck has a unique QR code that opens the customer chat page in their browser. No app download, no account required.
Claude knows the truck's full menu (pulled live from Square catalog), can answer questions about ingredients and allergens, and takes the order conversationally.
Claude calls place_order via the MCP server, which hits Square Orders API. One MCP server instance per truck, registered dynamically — no server restart needed for new trucks.
Claude calls create_checkout_link — Square generates a hosted payment page. No card data touches the server. Customer pays, Square notifies the truck.
The truck sees the order in their existing Square terminal. Nothing changes on their end — they get a new order notification the same way as always.
MCP as the integration layer
The key design decision was using the Model Context Protocol to keep Claude's reasoning separate from the POS integration. Claude doesn't know or care about Square's API — it calls high-level tools and the MCP server handles the translation.
list_menu— fetches catalog from Square for the specific truck location. Location filter was a critical bug fix — without explicit.locationIds(), both demo trucks returned the same menu.place_order— creates an order in Square Orders API with line items, quantities, and modifiers.get_order_status— lets customers check their order after submission.create_checkout_link— generates a Square-hosted payment URL. No PCI scope on the server.
One McpSyncServer instance per truck, not per request. The truckId lives in the constructor closure — each instance is scoped to one truck's credentials. New trucks register via trucks.json with a ConcurrentHashMap, live without restart.
Token storage and OAuth
- AES-256-GCM encryption: Square OAuth tokens encrypted at rest. No plaintext credentials anywhere in the codebase or config files.
- Automatic token refresh: Access tokens are refreshed before expiry transparently — merchants stay connected without re-authorizing.
- Square-hosted payments: Payment page is entirely on Square's domain. No card data, no PCI scope on the OrderAI server.
- OAuth onboarding flow: Merchants connect their Square account through a standard OAuth flow on the merchant onboarding page. Token exchange and storage happens server-side.
Built for multiple POS systems
A PosProvider interface abstracts all POS operations — menu fetch, order placement, checkout link creation. Square is the first implementation. Adding Toast, Clover, or any other system is a new class implementing the interface, not a rewrite of the core.
Toast integration was the next target but hit a wall — Toast's developer portal routes to a sales demo request with up to a 30-day approval timeline. The interface is ready when access opens up.
What it's built on
| MCP server | Java · Jetty HTTP server exposing MCP tools over HTTP |
| LLM | Claude API with mcp_servers parameter pointing to local MCP server |
| POS integration | Square Orders API, Catalog API, Checkout API — via Square Java SDK |
| OAuth | Square OAuth 2.0 — merchant onboarding, token exchange, AES-256-GCM storage |
| Web UI | Three pages: landing, merchant onboarding, customer chat — served by Jetty |
| Truck config | trucks.json — credential store, ConcurrentHashMap for live registration |
| Multi-POS | PosProvider interface — Square is implementation #1 |
| Dev tooling | ngrok for local HTTPS (MCP requires public URL), Claude Code in IntelliJ + VS Code |
OrderAI is open source. The MCP pattern, Square integration, and PosProvider abstraction are all reusable for anyone building AI-powered POS integrations. Check the GitHub repo for the full source.