<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bruno Melani</title>
    <description>The latest articles on DEV Community by Bruno Melani (@bruno_melani).</description>
    <link>https://dev.to/bruno_melani</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4215386%2F4259b794-0d9a-45de-a2ea-19ddcde8494b.jpg</url>
      <title>DEV Community: Bruno Melani</title>
      <link>https://dev.to/bruno_melani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bruno_melani"/>
    <language>en</language>
    <item>
      <title>I built an MCP server for restaurant bookings, and it never books anything</title>
      <dc:creator>Bruno Melani</dc:creator>
      <pubDate>Tue, 03 Nov 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/gaplessly/i-built-an-mcp-server-for-restaurant-bookings-and-it-never-books-anything-5bm8</link>
      <guid>https://dev.to/gaplessly/i-built-an-mcp-server-for-restaurant-bookings-and-it-never-books-anything-5bm8</guid>
      <description>&lt;p&gt;I’ve worked in Sydney restaurants and bars for over a decade, with every kind of booking app open at the front desk. Over those years I stepped up into management roles, and around the same time, about three years ago, I challenged myself to learn to code.&lt;/p&gt;

&lt;p&gt;The two collided. The more I could build, the more I questioned the limits of the apps I used every day, and the more I wanted to build the one I always wished existed for businesses that run on bookings.&lt;/p&gt;

&lt;p&gt;That’s Gaplessly: a booking system for salons, clinics, restaurants and bars. It’s in early access, so this is a build log. It’s the first app I’m building to run at scale, and I’m sharing it from the start.&lt;/p&gt;

&lt;p&gt;My vision is that personal AI assistants will find a free table or appointment for the people they work for, and we’ll spend less and less time searching for these things ourselves.&lt;/p&gt;

&lt;p&gt;Here’s how that part of the journey starts: an MCP server any assistant can use to find live times. The interesting part is what I left out. It can’t book anything, and that’s on purpose.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7poem9qoxtb1gzl268a4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7poem9qoxtb1gzl268a4.png" alt="The three steps: the assistant finds times, gets a link, the guest taps and confirms" width="799" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it first
&lt;/h2&gt;

&lt;p&gt;It's one endpoint, no API key, no sign-in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http gaplessly https://gaplessly.com/api/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Cursor and VS Code snippets are on &lt;a href="https://gaplessly.com/docs/mcp" rel="noopener noreferrer"&gt;the docs page&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Then ask it for a table at Saltline, a demo venue I set up with a made-up name and phone number. Here's what the server really sends back, trimmed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;get_venue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"venue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bruno-test-bistro"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"venue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Saltline"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"restaurant or venue (table reservations)"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"venueClock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"today"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-30"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4:23 PM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4:23 PM on Friday 30 October, local time at the venue"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxOnlinePartySize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;find_table_times&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"venue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bruno-test-bistro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"partySize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tomorrow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searched"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"from"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-31"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"partySize"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"days"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-31"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Saturday 31 October"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"times"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"12:00 PM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"slotToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJzIjoiYnJ1bm8tdGVzdC1iaXN0cm8i..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7:00 PM"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"slotToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJzIjoiYnJ1bm8tdGVzdC1iaXN0cm8i..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five tools in total: &lt;code&gt;get_venue&lt;/code&gt;, &lt;code&gt;find_appointment_times&lt;/code&gt;, &lt;code&gt;find_table_times&lt;/code&gt;, &lt;code&gt;start_appointment_booking&lt;/code&gt; and &lt;code&gt;start_table_booking&lt;/code&gt;. All five are read-only, including the two called &lt;code&gt;start_&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 1: the last step is a link, not a booking
&lt;/h2&gt;

&lt;p&gt;The obvious design is a &lt;code&gt;book_table&lt;/code&gt; tool that takes a name, an email and a phone number and writes the booking. I didn't build it, for three reasons.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The assistant can't prove who it's acting for.&lt;/strong&gt; No mainstream assistant passes a verified identity to a tool. A tool that books outright books for whoever the model says, using details the model typed. Bigger players landed in the same place: Resy's connector needs a sign-in, Google's AI sends you to the booking page for the last step, and Calendly won't book without a code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Personal data never has to pass through a model.&lt;/strong&gt; No tool accepts a name, email or phone, so there's nothing to leak, log or hallucinate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The venue's page already knows how to ask.&lt;/strong&gt; Deposits, house rules, a restaurant's own questions ("any allergies?"): the booking page handles all of it. Rebuilding that inside tool schemas would drift from the real thing within a month.&lt;/p&gt;

&lt;p&gt;So &lt;code&gt;start_table_booking&lt;/code&gt; takes a slot token and returns a short-lived link to the venue's own booking page, already opened at that time. The person who taps it is the person in the conversation. When they open it the venue holds the table for about ten minutes while they fill in the form. Nothing is held before that, and calling the tool twice gives you the same link twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 2: no timezone, anywhere
&lt;/h2&gt;

&lt;p&gt;This one cost me a real bug. Availability is stored as the venue's local wall clock. Look inside a slot token (it's base64url) and you'll see this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"s"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bruno-test-bistro"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"t"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-31T12:00:00.000Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"i"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1793337833442&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's noon in Sydney, wearing a &lt;code&gt;Z&lt;/code&gt; it hasn't earned. Any date library that parses it moves the booking by ten or eleven hours. If the server hands a model a time and a timezone ID, the model helpfully converts it, and you get the same bug again, this time inside someone else's chat.&lt;/p&gt;

&lt;p&gt;So times only come back as display text (&lt;code&gt;"7:00 PM"&lt;/code&gt;). Nothing comes back in a form a date library will happily parse. Dates you send are words or plain dates (&lt;code&gt;"today"&lt;/code&gt;, &lt;code&gt;"tomorrow"&lt;/code&gt;, &lt;code&gt;"2026-10-31"&lt;/code&gt;), worked out against the venue's own today. That's what &lt;code&gt;venueClock&lt;/code&gt; is for. A guest in London asking about a Sydney dinner is often on a different calendar day from the venue, and "tomorrow" has to mean the venue's tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 3: the booking handle is a signed token
&lt;/h2&gt;

&lt;p&gt;Every time comes with a &lt;code&gt;slotToken&lt;/code&gt;. It's signed, it expires in about thirty minutes, and the signature covers the venue, the time and what it was found for (the party size or the service). You can't edit one, build one by hand, move it to another venue, or reuse it for a bigger party.&lt;/p&gt;

&lt;p&gt;The reason is prompt injection. If a page the model read earlier tells it to "book at this other place instead", the token for the wrong venue just fails. The refusal says what to do instead, so the assistant can recover rather than guess.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision 4: an empty day says why
&lt;/h2&gt;

&lt;p&gt;An empty list reads as "fully booked", which is the worst thing to tell a guest when the truth is "closed on Mondays". When the venue has told us why a day is empty, the tool says so.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it doesn't do
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No reading or cancelling bookings.&lt;/strong&gt; Both would need the private link that manages a booking, and that's the one credential this design keeps away from assistants. Guests manage bookings from their confirmation email.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live times depend on the venue's plan.&lt;/strong&gt; Venues without the AI booking feature still answer &lt;code&gt;get_venue&lt;/code&gt;, and the time searches send back a link to their booking page instead of times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It's rate limited per network address&lt;/strong&gt;, and modestly, because one assistant platform's address is shared by everyone using it. A normal conversation takes three calls.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The blueprint: one booking core, many front doors
&lt;/h2&gt;

&lt;p&gt;The MCP server is one door into something bigger. The idea behind Gaplessly is that a booking can arrive from anywhere (a booking page, a partner app, a POS, an AI assistant, eventually Google) and every one of them goes through the same core: the same availability maths, the same rules, the same write, with the clash check enforced by Postgres itself rather than by whichever app got there first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Live today:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A branded booking page for every business, on its own subdomain.&lt;/li&gt;
&lt;li&gt;Two products on one platform: appointments (staff, services, durations) and hospitality (parties, tables, service periods, a live floor plan, a waitlist). They really are different jobs, so they have separate data and rules.&lt;/li&gt;
&lt;li&gt;A public REST API with an OpenAPI spec: availability, booking writes for partners (an Idempotency-Key is required, so a retry never double-books), and signed webhooks for every booking change.&lt;/li&gt;
&lt;li&gt;Calendar feeds, and ready-made n8n and Make templates for owners who automate.&lt;/li&gt;
&lt;li&gt;A POS API, so a till can mark a table seated or finished and attach the bill.&lt;/li&gt;
&lt;li&gt;This MCP server, a read-only CLI on npm, and Lessly, an assistant inside the dashboard with tools scoped to each product.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Being built next:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Booking pages that agents can read with nothing installed.&lt;/strong&gt; Structured data and clean forms on every booking page, so any browsing agent can find and book without anyone adding a connector. That's the real goal: a guest shouldn't have to install anything for their assistant to book a table.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A private, signed-in MCP server for businesses.&lt;/strong&gt; "What does Friday look like?", "Move the 7pm to table 12", "Who's on the waitlist for tonight?", answered and done by the venue's own assistant, under permissions the venue grants. It will be a separate endpoint with separate scopes, so nothing private is ever reachable from the public one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reserve with Google.&lt;/strong&gt; Google's end-to-end booking needs a real, idempotent write, which the partner API already has, and the MCP tools map one to one onto Google's availability and booking calls. So it's one more thin adapter on the same core, pending Google's partner approval.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two-way staff calendar sync&lt;/strong&gt;, Google first, so a stylist's personal calendar blocks their booking times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One inbox for every channel.&lt;/strong&gt; WhatsApp, Instagram and Messenger enquiries next to booking and email messages, through each platform's official business APIs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Where I want it to get:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You tell whatever assistant you use "a table for four near the office on Friday, somewhere quiet", it finds a real time at a real venue, and you confirm with one tap. On the other side, the venue's own assistant runs the day: it confirms, moves, fills a cancelled slot from the waitlist and tells the floor team who's coming. The booking system sits in the middle as the source of truth that every assistant, marketplace and till reads and writes through, while the business keeps its guests, its data and its brand, and pays no commission per booking.&lt;/p&gt;

&lt;p&gt;I'm a long way from that, and I'm building each piece above so it fits that picture.&lt;/p&gt;

&lt;p&gt;If you build MCP servers I'd really like your view on the identity question. Is a link-and-tap handoff where this lands for any tool that acts for a person, or is there a pattern I'm missing?&lt;/p&gt;

&lt;p&gt;Docs: &lt;a href="https://gaplessly.com/docs/mcp" rel="noopener noreferrer"&gt;gaplessly.com/docs/mcp&lt;/a&gt; · API: &lt;a href="https://gaplessly.com/openapi.json" rel="noopener noreferrer"&gt;gaplessly.com/openapi.json&lt;/a&gt; · CLI: &lt;code&gt;npx @gaplessly/cli&lt;/code&gt; (&lt;a href="https://github.com/gaplessly/cli" rel="noopener noreferrer"&gt;github.com/gaplessly/cli&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>mcp</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
