Inspiration

312Deals is a live site: 80,000+ food and drink deals at 12,000+ venues across 149 Chicagoland neighborhoods, covering the city and 60+ suburbs, re-verified weekly against 18,000+ tracked sources. People use it to figure out where to go tonight. When agent browsers arrived, we watched them try to do the same job by reading the page, and get it wrong in ways that matter: a happy hour that ended at six, a venue across town, a "deal" that was last week's. The inventory is structured and time-sensitive; the UI was built for people. WebMCP is the bridge. Tell the agent what the site can do instead of making it guess from what it shows.

The idea we wanted to test: planning a night out is genuinely collaborative work. Ranking 80,000 time-windowed deals is the agent's job. Taste and veto are the person's. So instead of an agent that hands you a plan, we built a plan that both of you edit, on the same page.

The idea we wanted to test: planning a night out is genuinely collaborative work. Ranking 80,000 time-windowed deals is the agent's job. Taste and veto are the person's. So instead of an agent that hands you a plan, we built a plan that both of you edit, on the same page.

What it does

Open 312deals.com in ChatGPT's desktop browser and the page registers 17 tools on document.modelContext:

10 data tools over the live corpus: search deals by neighborhood, day, type, and cuisine; deals near an address; a venue's deals; deal of the day; chain deals; neighborhood summaries; a multi-stop crawl planner; order and reservation links; and a moderated community deal tip (a write, so the browser's confirmation applies). 7 "Tonight" tools over a plan that lives in the page: the Tonight panel, bottom-right on every screen. The agent reads the plan, sets constraints (budget, hours, group size, max stops, neighborhood), adds stops from real deals, moves them, reorders them by deal window, removes, and clears. Every agent change lands in the panel with an "agent" chip and a toast. The person adds any deal from its card, reorders, vetoes, and locks the stops that must stay. Locked stops are constraints, not suggestions: an agent call against a locked stop returns a structured refusal, so the agent re-plans around it instead of over it. Every stop ends in action. Reservation links carry the plan: OpenTable's dateTime and covers, and Resy's date and seats, are built from the plan's start time and group size (or from the time and party size the agent passes), so the booking page opens on your slot rather than its 7-PM-for-2 default. Why this use case is a strong fit for WebMCP. Deal discovery is precisely the case WebMCP was made for: typed tools over live, structured, expiring data beat screen-reading on speed, accuracy, and reliability. And the site already had an audience and a corpus. This isn't a demo dataset: 312Deals ranks on page one for its core Chicago queries and most of its traffic is organic search, so the pages an agent lands on are the same pages people land on.

How it creates a better user experience. One request replaces a dozen searches across tabs. The agent searches real, verified deals, builds the plan from what is actually on at each hour, and shows its work in a panel you can touch. You lock what you care about; it optimizes the rest.

What people and agents can do together that was difficult or impossible before. Before, you had two options: do all the work yourself in the UI, or let an agent scrape the UI and hand you a plan you couldn't touch. Now both act on one live surface. The agent proposes against live inventory, the person constrains with locks the agent must respect, and each sees the other's changes immediately. The plan is yours, built on tonight's real deals.

How we built it

Next.js 14 and React on Vercel, FastAPI on Railway, SQLite with FTS5 distributed through Cloudflare R2 with an ETag conflict guard, zustand for the shared plan, and the ElevenLabs API for the demo narration. Built and shipped solo under Hoyne Labs LLC. All challenge work went to production the same day it was written and was tested against ChatGPT's desktop browser on a free account.

How we implemented WebMCP:

Registration feature-detects document.modelContext (the current spec surface; ChatGPT desktop and Chrome 149+) with navigator.modelContext as a fallback for earlier Canary builds. Every tool carries readOnlyHint / destructiveHint annotations and is registered with an AbortSignal; teardown runs through both paths; tools re-register across client-side navigations. Agent-shaped results. The site's REST API returns about 60 columns per deal and about 92 per venue (a 20-result search is roughly 32 KB; one venue lookup roughly 117 KB). The tools trim each result to what a person acts on, add a link to the page, and say how many results were left out. Shared state. The Tonight tools act on a persisted zustand store the panel renders. The lock and veto contract is enforced in the store, so a refusal comes back to the agent as data with instructions ("locked by the user, plan around it"). One link builder, three surfaces. A single reservation-link helper is used by the Tonight tools, the get_reservation_link tool, and the panel's own Reserve link, so the agent's path and the person's path emit the same fully parameterized URL. Dates default to today in America/Chicago; times accept what an agent or a person would write ("6pm", "18:00"). Catalog and analytics. An informational manifest at /.well-known/webmcp.json lists all 17 tools alongside the site's existing /llms.txt, /llms-full.txt, /skill.md, and /.well-known/mcp.json. The FastAPI middleware that detects agent traffic and records tool calls predates the challenge, which is why the first real calls were captured the moment they arrived. Pre-existing project, what's new. 312deals.com existed before the challenge, including an earlier 10-tool WebMCP layer on the legacy navigator.modelContext surface. All challenge work is in the public repo's commits dated Sep 3, 2026, after a clearly labeled baseline commit: the spec-surface migration and agent-shaped results, the entire Tonight collaboration (panel, store contract, 7 tools), the lock guidance, and the plan-aware reservation links. Everything was deployed to production on Sep 3.

Challenges we ran into

The spec moved under us. The site's original WebMCP layer, built in February 2026 after joining Chrome's Early Preview Program for built-in AI, registered on navigator.modelContext, with a declarative form API on the highest-frequency tools. ChatGPT's browser only looks at document.modelContext. Until the migration, the 17 tools were invisible to the one client that mattered. Version fragility had been the known risk with this standard for months, and this is what it looked like in practice. The agent web-searched instead of calling tools. A plain "find me a happy hour" sent ChatGPT to general search, citing venue websites. Naming the site tools in the request ("using this site's tools...") reliably routes it to the page. The testing instructions say so. The lock was bypassable through the human UI. Asked to remove a locked stop, the agent hit the tool's refusal, then clicked the panel's padlock itself, announced it, and removed the stop. The refusal now tells the agent plainly that only the person unlocks, by hand. It's an honest lesson: when the agent can drive the UI too, "human affordances" are agent affordances unless the contract is explicit. Shallow deep links. The first reservation handoff landed on OpenTable's default slot. Pushing the plan's date, time, and party size into the URL made the link finish the job.

Accomplishments that we're proud of

The first real WebMCP tool calls the site ever received came from ChatGPT during this challenge: search, then tonight_add_stop three times, then a reorder that respected a lock. The site's own analytics recorded them. Seven months of building an agent surface (REST API, MCP server, custom GPT, llms.txt, WebMCP) and this was the first time we watched an outside agent discover the tools on the page and use them end to end.

What we learned

WebMCP's value isn't the tool list; it's designing for two actors on one surface. The interesting engineering is the contract between them: attribution, refusals as data, and what a lock actually means when the other party can also click.

What's next for 312Deals: Tonight

Keeping deals , venues and more up-to-date to enable discovery of venues, deals and more for small business owners. The goal was to spread awareness of this to support small biz. Hopefully this does just that by making it easier for the ever changing landscape of the web with AI, to support and facilitate that. A collaborative crawl builder with a live map; making the lock enforceable at the UI layer; per-stop notes both parties can edit; instrumenting agent traffic as a first-class analytics view for the site; and porting the Tonight surface to the next city in the area-code model.

Built With

Share this project:

Updates

Submission history