Inspiration

AI assistants are getting good at finding things, but they still stop at the moment that matters: committing to a booking and putting money on the line. Meanwhile, Paris restaurants lose real money to no-shows, which is why so many ask for a card or a deposit. We wanted to see if an AI agent could do the whole job, from "find me a table" to a confirmed booking with a deposit held, without ever being trusted with the money itself.

What it does

TableAgent is an AI agent that finds a table in a Paris restaurant, books it, and secures it with a no-show deposit held through PayPal.

  • You ask in plain language: "Italian near me, now, 4 people, one vegetarian, under €60 a head."
  • The agent searches, explains why each restaurant matches, and shows a proposal: restaurant, time, deposit amount, and the exact cancellation policy with its deadline.
  • Once you say yes, it gives you a PayPal link. You approve a hold, not a charge. The table is confirmed only after you approve it on PayPal.
  • If you show up, the hold is released. If you don't, or you cancel after the deadline, the restaurant keeps the deposit. Cancelling before the deadline costs nothing.
  • To cancel, you ask the agent. It tells you what will happen to the deposit, and you confirm with one click on a signed link.

It runs as an MCP server, so any MCP-compatible assistant (Claude and others) can use it as a set of tools.

How we built it

  • Next.js 16 (App Router, Server Actions, Cache Components), with Prisma 7 + PostgreSQL.

  • MCP server (Streamable HTTP, stateless) exposing six tools: search_restaurants, check_availability, propose_booking, book_table, list_my_bookings, propose_cancellation.

  • PayPal Orders v2 with intent: AUTHORIZE: the deposit is authorized (held), then either voided when the guests are seated, captured for a no-show or late cancellation, or refunded later.

  • Safety by design: the agent proposes, the human confirms. None of the tools can move money. The deposit is always computed on the server from the restaurant's data, never supplied by the model. Proposals snapshot every amount and policy term, and confirmation happens through a human action (PayPal approval or a signed link).

  • Payment integrity: before confirming, we check that the PayPal order matches the booking exactly (amount, currency, booking id). Every PayPal call uses a deterministic PayPal-Request-Id, so a retry can't charge twice. Every PayPal call, real or mocked, is logged in an audit trail.

  • Concurrency: atomic seat reservation, plus optimistic locking on every state change, so a double click can't capture twice.

  • A pure, unit-tested booking state machine, with cancellation rules computed in Europe/Paris time (including daylight-saving changes).

  • A mock PayPal gateway that follows PayPal's state rules, so the whole app runs without keys. Smoke scripts drive the MCP flow and every PayPal scenario end to end.

Challenges we ran into

  • Keeping the AI away from the money. The hard part wasn't calling PayPal, it was making sure no prompt, retry or hallucinated amount could ever change what gets charged. That led to the proposal/confirm split, server-computed deposits and the order-matching check.

  • Authorization lifetimes. A PayPal authorization is only guaranteed for 3 days and expires after 29, so the timing of bookings and captures matters.

  • Cancellation terms that change over time. The deadline can pass between the moment the agent explains the terms and the moment the user clicks. We recheck at click time and never capture a deposit the user was told would be released.

  • Links for agents with no browser session. MCP clients don't have cookies, so actions a human must confirm go through HMAC-signed links.

  • A brand-new stack. Next.js 16 changed several conventions (async params, Cache Components, streaming), and we had to relearn them from the docs.

Accomplishments that we're proud of

  • A complete, real flow on the PayPal sandbox: natural-language request → proposal → PayPal approval → confirmed booking → cancellation with the hold released.
  • An agent that is genuinely useful but structurally unable to overcharge anyone.
  • Idempotent, audited payments: retries, double clicks and refreshes are all safe.
  • Works with any MCP client, not only our own UI.

What we learned

  • Designing tools for an AI agent is mostly about deciding what it must not be able to do.
  • PayPal's authorize/capture model fits deposits well: hold first, decide later.
  • An MCP tool result should hand the human a link when consent matters, rather than letting the agent click for them.

What's next for TableAgent

-Restaurant dashboard: a PIN-protected page where staff mark guests as seated or no-show, or refund a deposit, in one click.

  • Web chat: talk to TableAgent directly in the browser, no MCP client needed.
  • Public deployment, so Claude Desktop, claude.ai and other assistants can connect to it.
  • Reauthorizing holds for bookings more than 3 days out.
  • Real restaurant availability, more cities, and live PayPal payments.

Built With

Share this project:

Updates

Submission history