bookings-mcp
Allows the AI receptionist to operate behind a WhatsApp chat, enabling customers to book, move, and cancel appointments while the server enforces its booking rules.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@bookings-mcp book me a haircut Wednesday morning, I'm Ana, +355 69 234 5678"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
bookings-mcp: an AI booking agent that can't break the rules
An MCP server that lets an AI receptionist book, move and cancel appointments for a salon, clinic or studio, safely. The business rules live in code, not in the prompt, so a confused or manipulated model still can't double-book, ignore opening hours, cancel someone else's appointment or quietly rewrite history.
Works with Claude Desktop, Claude Code or any MCP-capable agent, and behind a WhatsApp or website chat.
▶ Live demo: https://enxo7899.github.io/bookings-mcp/ (replays agent conversations against the real booking rules in your browser)

Guardrails
Risk | What stops it |
Booking without the customer agreeing |
|
Double booking | Overlap check per staff member on every create and move; |
Impossible times | Opening hours per weekday, closed days, 15-minute grid, service length must fit before closing |
Last-minute and far-future bookings | Minimum 2 hours' notice, maximum 60 days ahead |
One customer blocking the diary | At most 2 bookings per customer per day |
Seeing or changing other people's bookings | No "list all" tool exists; find, move and cancel require the phone number the booking was made with, and "wrong phone" looks the same as "no such booking" |
Late changes | Within 24 hours, a move or cancellation becomes a request for staff; the agent has no tool to approve it |
Approving a slot that filled up meanwhile | Staff approval re-runs every check |
Covering tracks | Every call, including refusals, goes into a SHA-256 hash-chained audit log with phone numbers masked; |
Bad input | Zod schemas at the MCP layer, then validation in the core with a reason the agent can pass on |
Prompt injection gets nowhere | Late cancellation waits for staff | Editing the log is detected |
|
|
|
Related MCP server: booking-mcp
Tools exposed to the agent
Tool | Annotations | Purpose |
| read-only | Services, prices, staff, hours and rules |
| read-only | Free start times for a service and date |
| write | Preview, then book after the customer confirms |
| read-only | Upcoming bookings for one phone number |
| destructive | Move a booking (or request it, inside 24h) |
| destructive | Cancel a booking (or request it, inside 24h) |
Staff actions (approve, reject, list everything, verify the log) are in scripts/admin.js and are never exposed over MCP.
Run it
npm install
npm test # 16 tests: rules, privacy, approvals, audit chain, and a real MCP client round-trip
TZ=Europe/Tirane npm start # MCP server on stdio, data in data/state.json
npm run admin -- pending # staff: see requests waiting for approval
npm run admin -- approve RQ-001
npm run admin -- verify # check the audit log hasn't been editedUse it from Claude Desktop or Claude Code
{
"mcpServers": {
"bookings": {
"command": "node",
"args": ["/path/to/bookings-mcp/src/server.js"],
"env": { "BOOKINGS_DATA": "/path/to/bookings.json", "TZ": "Europe/Tirane" }
}
}
}Then just ask: "Book me a haircut on Wednesday morning, I'm Ana, +355 69 234 5678."
Adapt it
Services, staff, opening hours and rules are one config object (DEFAULT_CONFIG in src/core.js). Storage is a JSON file written atomically; swapping in Postgres, Supabase or Google Calendar means replacing loadState / saveState. The core has no dependencies and also runs in the browser (that's what the demo uses).
Path | What it is |
| Booking rules, privacy checks, approvals, audit log |
| MCP server (stdio) with Zod schemas and tool annotations |
| Dependency-free SHA-256 for the audit chain |
| Staff command line |
| Rule tests and an end-to-end MCP client test |
| Interactive demo |
Built by EmSoft: AI agents with safety guardrails, MCP servers and booking assistants. Get in touch through my Fiverr or Upwork profile.
Available Tools
6 toolscancel_bookingCancel bookingADestructive
Cancels a booking. The phone must match the booking. Within 24 hours of the appointment this creates a request for staff instead.
Inputs: booking_id (required), customer_phone (required), reason.
create_bookingCreate bookingA
Books an appointment. First call WITHOUT customer_confirmed to get a summary, read it to the customer, and only call again with customer_confirmed: true after they say yes.
Inputs: date (required), time (required), service (required), customer_name (required), +3 more.
find_bookingsFind a customer's bookingsARead-only
Upcoming bookings for one phone number. There is no way to list other customers' bookings.
Inputs: customer_phone (required).
find_slotsFind free slotsARead-only
Free start times for a service on a date. Always check before offering a time.
Inputs: date (required), service (required), staff.
list_servicesList servicesARead-only
Services, prices, staff, opening hours and booking rules. Call this first.
Inputs: no named parameters.
reschedule_bookingReschedule bookingADestructive
Moves a booking. The phone must match the booking. Within 24 hours of the appointment this creates a request for staff instead.
Inputs: new_date (required), new_time (required), booking_id (required), customer_phone (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 6 tools
Each tool maps to a distinct step of the booking workflow: catalog (list_services), availability (find_slots), booking creation, and per-phone booking lookup/modification. The descriptions explicitly disambiguate the closest pair (find_slots = free times vs find_bookings = existing bookings) and enforce call ordering, leaving no realistic misselection.
All names are snake_case verb_noun and read predictably. The only minor deviation is mixing 'list_' and 'find_' for read operations (list_services vs find_slots/find_bookings), which is slightly inconsistent but still clear.
Six tools is well-scoped for a customer-facing appointment booking server, and each one earns its place in the flow. Nothing feels redundant or missing at the tool-count level.
The full customer lifecycle is covered: browse services, check availability, book, look up, reschedule, and cancel, including the 24-hour escalation rule. Minor gaps remain — no retrieval of a single booking's details or booking identifier, and find_bookings only returns upcoming appointments, so past or specific-booking lookups are dead ends.
Maintenance
Related MCP Connectors
Scheduling infrastructure for AI agents across Google and Microsoft calendars.
Verified local businesses, bookable by AI agents: services, prices, availability and appointments.
Voice agents that book into the software your clients actually run, built and audited from chat.
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceScheduling and booking engine for AI agents. Check availability, hold slots, and confirm appointments with two-phase booking and conflict-free resource management.2Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to safely manage appointment bookings for appointment-based businesses over MCP, including searching availability, holding, confirming, rescheduling, and canceling bookings, and reading business policies.MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to discover availability, place expiring holds, and confirm or cancel appointments for connected booking businesses, with idempotent retries and explicit user consent.1Apache 2.0
- AlicenseAqualityCmaintenanceEnables AI agents to browse customers, bookings, and availability while any booking creation or cancellation stays gated behind a human-approved, single-use token cryptographically bound to the exact arguments. Runs over stdio or Streamable HTTP and enforces the read/write separation in host code with a full audit trail.7MIT


