Restaurants and small shops are the most-attempted and worst-served agent task on the web. Every assistant can find a restaurant. Almost none can do anything with one. The menu lives in a PDF or a photo, the prices are stale, and the booking widget is a third-party iframe an agent cannot reason about. So the agent guesses — and it guesses wrong about the one thing the diner is paying for.

We run two real businesses in Santiago, Chile, and we felt this from the other side. Agents were already describing our menu and our catalog to people, from blog posts written years ago. We had no way to be the author of what agents said about us.

But the thing that actually kept us from opening the door was not the reading. It was the booking. Nobody wants an agent that reserves a table, or buys $80,000 CLP of paint, on their behalf while they are looking away.

So we built for the opposite: the agent does the tedious part and stops.

What it does Two businesses that have nothing in common expose the same pattern.

Tengu — a kappo omakase restaurant, average table $300–400k CLP. Five tools on the page: get_carta (the live menu with real prices, by section), buscar_plato (search dishes, cocktails, wines and sake), get_guia (long-form guides the restaurant wrote about bluefin, sake and kappo cooking), get_info, and the one that matters — preparar_reserva.

Boykot — an art and graffiti supply store, about 3.000 SKUs. Thirteen tools: catalog search, product detail, brand list, quotes, stock subscriptions, promotions, project planning, colour cards — plus agregar_al_carro, ver_mi_carro and guardar_en_lista.

preparar_reserva fills the reservation form on the page with the party size, date, time and name the agent gathered in conversation — and then stops. It does not submit. The form is left visible, filled, scrolled into view, with the fields the agent touched marked, and a notice above it that says so and offers to discard. The human checks it and sends it.

agregar_al_carro does the same on the store side. The cart gets built. Nobody pays.

That is the division of labour we wanted. The agent parses "a table for four next Friday, somewhere quiet, my wife doesn't eat raw fish". The human keeps the part that costs money and social capital. The restaurant's host still sees a normal booking arrive.

The read tools matter for a subtler reason: grounding. An agent asked "what's the sake situation at Tengu" now answers from the restaurant's own words and tonight's actual list, instead of from a 2023 blog post. For the first time, the business is the author of what agents say about it.

How we built it Eighteen tools across the two sites — five on Tengu, thirteen on Boykot — registered on document.modelContext (with navigator.modelContext as the deprecated alias), feature-detected so each page degrades to an ordinary website when the API is absent:

var mc = document.modelContext || navigator.modelContext; if (!mc || typeof mc.registerTool !== 'function') return; Both sites carry origin trial tokens, so the API is native — no ?webmcp flag, no polyfill, nothing for the judge to enable. Open the URL and the tools are there.

The in-page tools are deliberately thin: they proxy to the same /api/mcp JSON-RPC server each business already runs for out-of-page agents. A browser agent and a server-side agent get the same answers from the same source. One truth, two transports. The exception is the write-side tools — preparar_reserva and agregar_al_carro only exist in the page, because their whole job is to touch the DOM in front of a human and leave it there.

Tengu is static HTML and vanilla JS on Vercel with zero npm dependencies on the page — the smallest attack surface we could manage for something that hands tools to an autonomous caller. Reservations persist to Postgres through SECURITY DEFINER functions behind row-level security that denies all direct access; the page never holds a database credential. Boykot is Next.js, backed by the store's live inventory.

Deliberately not exposed: anything that spends money or commits the business. No payment, no confirmation, no cancellation, no order modification. The reservation engine has its own caps underneath — 8 tables per slot, rate limit per name and phone — and the agent surface sits strictly inside them. A tool we don't register is a tool that can't be jailbroken. Thnks For Reading :)

Built With

Share this project:

Updates

Submission history