For LLMs, agents and the people who connect them
The Hawkerline agent interface
Hawkerline is a source-available restaurant ordering, kitchen display, menu and POS system that an AI agent can operate, built for Singapore food businesses and running on one Cloudflare Worker and one D1 database. This page describes how an AI agent connects to a Hawkerline store.
Four ways in
| Interface | Address | Notes |
|---|---|---|
| MCP server | /mcp | Model Context Protocol over Streamable HTTP with bearer-key auth. Responses are JSON over POST (no server-sent events). Protocol versions 2025-11-25, 2025-06-18 and 2025-03-26. |
| REST API | POST /api/agent/v1/tools/<tool> | The same tools over HTTP, for any HTTP-capable agent, workflow tool or script. |
| OpenAPI document | /api/agent/v1/openapi.json | OpenAPI 3.1 description, for tool-calling frameworks that import OpenAPI. |
| llms.txt | /llms.txt | Served by every deployment. Tells an LLM what the store offers and how to operate it. |
Compatibility. Any MCP client that can send an Authorization: Bearer header over Streamable HTTP works, for example Claude Code. OAuth is not implemented, so connectors that only support OAuth cannot connect directly. Such agents can use the REST API instead.
Agent keys and scopes
The owner creates and revokes agent keys in /admin on the AI access page. A key looks like hlk_ followed by 40 hex characters. It is shown once and only its hash is stored. Revoking a key cuts the agent off immediately. Each key is limited to 120 calls per minute.
| Scope | Allows |
|---|---|
menu:read | Read products, categories and publication status; preview the draft |
menu:write | Create and edit draft products, images, display order and categories |
menu:publish | Publish the previewed draft to customers, now or scheduled |
orders:read | Read orders and the kitchen board |
orders:write | Move orders through the kitchen flow (new, preparing, ready, done) |
store:write | Pause or resume online ordering |
reports:read | Read sales summaries |
Give each agent only the scopes it needs.
Tools and their scopes
Every tool is available over both MCP and REST.
| Tool | Scope | What it does |
|---|---|---|
get_store_overview | menu:read | Start here: store name, whether it accepts orders, categories, product counts, live release and current draft revision |
list_categories | menu:read | Menu categories (key, Chinese label, English label) and how many draft products use each |
list_products | menu:read | All draft products with SGD price, category, components and image status |
preview_menu | menu:read | Compare the draft with the live menu and get a 10-minute preview link; returns draft_checksum and live_release_id |
set_categories | menu:write | Replace the whole category list; order is display order |
upsert_product | menu:write | Create a product or update only the fields you pass, matched by sku |
bulk_upsert_products | menu:write | Create or update up to 100 products in one call, such as a whole menu read from a photo or PDF |
set_product_availability | menu:write | Put a product on or off sale in the draft |
set_product_image | menu:write | Set the product image from an https URL or base64 data (PNG, JPEG or WebP, up to 640 KB) |
reorder_products | menu:write | Set the display order by passing skus in order |
publish_menu | menu:publish | Publish exactly the previewed draft; needs draft_checksum and live_release_id from preview_menu; optional effective_at_sgt schedules it |
list_orders | orders:read | Recent orders; phone numbers are masked unless include_contact is true |
get_kitchen_board | orders:read | Today's paid orders that are not done, with set components expanded |
advance_order | orders:write | Move a paid order to the next kitchen status, or to a later status with "to" |
set_store_open | store:write | Pause or resume new online orders immediately |
get_sales_summary | reports:read | Paid orders, revenue (SGD), GST, service charge and top items for a Singapore-time date range |
Menu edits go to a draft. Customers see only a published release. A bulk call accepts up to 100 products.
Example MCP flow: photo of a menu, products, preview, publish
- Connect. Add your store to an MCP client with an agent key that has the scopes you want.
- Photo of a menu. Give the agent a photo or PDF of the menu.
- Products. The agent calls
set_categoriesif needed andbulk_upsert_products, with single items before the sets that use them.set_product_imagecan add images. - Preview.
preview_menucompares the draft with the live menu and returnsdraft_checksum,live_release_idand a 10-minute preview link. - Publish.
publish_menutakes thatdraft_checksumandlive_release_id. If anything changed since the preview, nothing is published and the agent must preview again. - Operate. The same agent can use
list_orders,get_kitchen_board,advance_order,set_store_openandget_sales_summary, if its key has those scopes.
Connect a client
Replace your-store.example with your store's domain and hlk_… with a key created in /admin.
Claude Code
claude mcp add --transport http my-store https://your-store.example/mcp \
--header "Authorization: Bearer hlk_…"
MCP client with a JSON config
Field names vary between clients; the client must be able to send an Authorization header to a remote HTTP server.
{
"mcpServers": {
"my-store": {
"type": "http",
"url": "https://your-store.example/mcp",
"headers": { "Authorization": "Bearer hlk_…" }
}
}
}
REST
curl -s https://your-store.example/api/agent/v1/tools/list_products \
-H "Authorization: Bearer hlk_…" -H "content-type: application/json" \
-d '{"only_on_sale":true}'
Responses are {"ok":true,"result":{…}} or {"ok":false,"error":"…","code":"…"} with an HTTP status: 400 invalid arguments, 401 bad key, 403 missing scope, 404, 409 conflict, 429 rate limit.
Safety rails
- Preview checksum. An agent can only publish the exact draft it previewed.
- Scopes. Each key can do only what its scopes allow. Agent keys, payments, members, refunds and store settings stay owner-only.
- Audit log. Every agent call is written to an audit log the owner can read in
/adminon the AI access page. - Revocation. The owner can revoke a key instantly.
- Privacy. Phone numbers in order data are masked unless the agent asks for contact details with
include_contact. - Stale-edit protection. Concurrent edits are guarded by revision checks; a stale edit is rejected instead of overwriting.
- Rollback. Rolling back creates a new release from an older one.
More detail: agent guide and tool reference on GitHub. Back to Hawkerline overview.