realtycalendar-web-mcp
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., "@realtycalendar-web-mcp check which rooms are available from July 10 to 12"
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.
realtycalendar-web-mcp
An MCP server for RealtyCalendar that lets AI assistants check room availability, find reservations, and create, update, cancel or delete bookings.
Independent, unofficial project: this software is not affiliated with, endorsed by, sponsored by or supported by RealtyCalendar.
Provided “as is”, without warranty of any kind, to the extent permitted by applicable law. See sections 6 and 7 of the MPL-2.0 license for the warranty disclaimer and limitation of liability.
Run it locally over stdio or self-host it over HTTP for connector clients. Access defaults to read-only. Every write uses a separate preview step and requires approval through the client's write-tool prompt.
List categories and rooms, availability, prices and stay restrictions.
Find stays, arrivals, departures, unpaid and unassigned bookings.
Read booking details, payments and optional change history.
Create, update, cancel and delete bookings at the configured access level.
This uses RealtyCalendar's unofficial web app API, which can change without notice. Payment writes, guest-contact editing and searches by booking creation date are outside the current tool set.
Current release: v0.4.0. There is no npm package. Local stdio runs from a checkout; Docker serves hosted HTTP.
Choose a setup
Setup | Use it for | Requirements |
A connector URL for Claude or ChatGPT | Docker, an HTTPS reverse proxy and a persistent server key | |
A local MCP client such as Claude Desktop, Claude Code or Codex | Node.js 22+ and an RC session token |
Create a dedicated RealtyCalendar user with only the objects and role it needs (Settings → Users). Its actions then appear under its own identity in RC's history. Use an upstream read-only role when access must be read-only.
Clone the repository for either setup:
git clone https://github.com/stek29/realtycalendar-web-mcp.git
cd realtycalendar-web-mcpTo build a specific release locally, run git checkout v0.4.0 before building.
Related MCP server: lig-room
Hosted HTTP
The hosted server exposes Streamable HTTP at <MCP_PUBLIC_URL>/mcp. Each connection signs in with its own
RealtyCalendar credentials and picks an access level, capped by the server's RC_ACCESS setting.
The OAuth implementation accepts Claude, Claude Code and ChatGPT client metadata. End-to-end validation in Claude web and ChatGPT web is still pending; see remaining work.
Deploy
The image ghcr.io/stek29/realtycalendar-web-mcp supports linux/amd64 and linux/arm64. The package is currently
private: pulling it requires docker login ghcr.io with a GitHub token that has read:packages and access to the
package. Release images use version tags such as 0.4.0; main tracks the main branch.
Use the compose example behind your own HTTPS reverse proxy:
Generate a server key with
openssl rand -base64 32.Create
deploy/.env, replacing the example origin and key:MCP_PUBLIC_URL=https://rc.example.com MCP_SERVER_KEY=REPLACE_WITH_GENERATED_KEY RC_ACCESS=read MCP_TRUST_PROXY_HOPS=1Restrict access to that file, then start the server:
chmod 600 deploy/.env docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -dForward your public HTTPS origin to
127.0.0.1:8080and have the proxy append the client IP toX-Forwarded-For. SetMCP_TRUST_PROXY_HOPSto the actual number of trusted proxies in front of the server.
The container speaks plain HTTP. GET /healthz reports server health without contacting RC. A
Kubernetes example is also available. To build your own image, use
docker build -t realtycalendar-web-mcp:local . and select that image in your deployment configuration.
Connect
Add https://your-host/mcp as a custom connector in your client and complete sign-in. For Claude Code:
claude mcp add --transport http realtycalendar https://your-host/mcpRequire approval for write tools in the client; see write approval.
Hosted settings
Variable | Default | Meaning |
| required | Public origin without a path; HTTPS required except for local development |
| required | Persistent base64/base64url secret of at least 32 bytes |
| unset | Previous key accepted during rotation; keep it for the refresh-token lifetime of 30 days |
|
| HTTP listening port |
|
| Trusted proxies that append to |
Keep the server key across restarts. Replacing it without retaining the previous key disconnects existing users.
Hosted mode obtains RC session tokens through sign-in and derives its confirmation key from the server key;
RC_TOKEN and RC_CONFIRM_KEY are local-stdio settings.
Local stdio
Requires Node.js 22+.
npm ci
npm run build
node dist/main.js loginLogin asks for the dedicated RC user's credentials and prints a session token. The local CLI does not store the password. The token represents a separate RC session; browser logout does not end it.
Verify the connection with RC_TOKEN=YOUR_SESSION_TOKEN node dist/main.js check, then add the server to your client.
For Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"realtycalendar": {
"command": "node",
"args": ["/absolute/path/to/realtycalendar-web-mcp/dist/main.js"],
"env": { "RC_TOKEN": "YOUR_SESSION_TOKEN", "RC_ACCESS": "read" }
}
}
}For Claude Code:
claude mcp add realtycalendar -e RC_TOKEN=YOUR_SESSION_TOKEN -e RC_ACCESS=read -- node /absolute/path/to/realtycalendar-web-mcp/dist/main.jsFor Codex (~/.codex/config.toml), start with read-only access:
[mcp_servers.realtycalendar]
command = "node"
args = ["/absolute/path/to/realtycalendar-web-mcp/dist/main.js"]
env = { RC_TOKEN = "YOUR_SESSION_TOKEN", RC_ACCESS = "read" }Codex's default_tools_approval_mode = "prompt" has not been verified for this server. Verify its approval behavior
before enabling writes. Do not use automatic write approval for normal operation.
End the MCP's RC session with RC_TOKEN=YOUR_SESSION_TOKEN node dist/main.js logout.
Variable | Default | Meaning |
| required | Session token printed by |
| random per process | Key that signs preview confirmation tokens |
Shared settings
Variable | Default | Meaning |
|
|
|
|
| Protect booking-site reservations from changes RC does not send back to the site. |
|
| Hotel time zone, using an IANA identifier |
|
| One audit entry per write; |
|
| Hide known structured guest-name and phone fields in MCP responses; accepts |
With RC_SITE_BOOKINGS=protect, booking-site reservations cannot receive new dates, category, status or price, or
be canceled/deleted. Assigning a room within the same category, changing arrival/departure times and adding notes
remain available.
Hide guest names and phone numbers
Guest-name and phone masking is available starting with v0.4.0.
Set RC_HIDE_GUEST_PII=true in the server environment (or deploy/.env for the compose example) and restart the
server. This is a server-wide option for both hosted HTTP and local stdio; it also applies to existing hosted
connections, with no OAuth or token changes.
When enabled, structured guest names and phone numbers become null, including nested previews, conflicts and
warnings. Generated write summaries omit the guest name. Recognized guest-name and phone changes in history have
their old/new values hidden; recognized booking-site contact fields contain [hidden].
Booking IDs, rooms, dates and financial data remain available. Names and phones remain intact inside RC: searches,
duplicate detection and writes still use the original values. Notes, other free text, guest emails and staff names
are untouched. This masks the specified response fields; it is not complete anonymization. RC_AUDIT=full still
writes the original booking body to server logs.
Write approval
Each write is two calls: preview_<write> returns the proposed changes and a confirm_token; the write tool then
requires that token with the same arguments. The token binds the write to the preview. Approval must come from the
client's write-tool prompt; the token itself is not proof of human approval.
Require approval for create_booking, update_booking, cancel_booking and delete_booking. Do not mark them
“always allow” or add them to Claude Code's allowedTools.
Read and preview tools do not modify reservations. Automatically allowing them still grants access to the guest data available to that connection.
Data and credentials
Guest names, contacts, notes and booking details pass through the server to the model provider used by the client. The server has no booking database. Default application logs omit guest contact details; clients, model providers and hosting infrastructure may retain outputs or logs according to their own settings.
RC_AUDIT=full writes the pre-write booking body, including guest data, to logs. Logs and audit entries go to stderr
for local stdio and stdout for hosted HTTP.
Hosted authorization codes and refresh tokens contain RC credentials encrypted with MCP_SERVER_KEY, allowing
the server to sign in again when an RC session expires. Protect the key and client-held tokens. Authentication
limitations, including the lack of per-user revocation, are listed in remaining work.
The hotel operator is responsible for applicable privacy obligations, including disclosures about transfers to the model provider and any cross-border processing. Keep session tokens, client configuration containing tokens, server keys and local credential files out of Git.
Development
npm run check # typecheck, lint and existing unit tests
npm run build
npm run tools # print MCP instructions and tool schemas for the configured access levelFixtures and documentation examples use fictional identifiers, contacts, dates and financial values. Model evals, fixture maintenance and opt-in live testing are covered in the testing guide.
Documentation
Document | Purpose |
Inputs, outputs, errors and approval flow | |
Code structure, upstream client, caching, OAuth and privacy | |
Upstream semantics and supported workflows | |
Endpoint reference | |
Unit checks, eval runners and opt-in live tests | |
Unfinished client validation and known limitations | |
Rationale for the current implementation |
License
This project's source code is licensed under the Mozilla Public License 2.0.
Available Tools
4 toolscheck_availabilityCheck availabilityARead-onlyIdempotent
Rooms of the user's hotel in RealtyCalendar for a stay: per category which rooms are free, busy, on hold or closed, occupancy (загрузка), the price of the stay for the number of guests, and the booking rules for the dates: minimum stay (минимальный срок), no check-in / no check-out days. A room is bookable only if it is empty AND its category has capacity every night (unassigned bookings use capacity without a room): answer from bookable_rooms and stay_rules, not empty_rooms. Mention holds (заявки) on free rooms. Not for finding a booking: use list_bookings. Not for the user's own calendar, free time or meetings, staff schedules, other hotels or travel plans. Dates: today is in every result; stays are nights (check_out = departure day); a week is Monday to Sunday; "на выходные" = Friday and Saturday nights; a date without a year is the next one, or the last one when the user asks about the past. Say which dates you used.
Inputs: check_in (required), check_out (required), room, detail, +2 more. Returns: today, nights, check_in, currency, +6 more
get_bookingGet bookingARead-onlyIdempotent
One booking of the user's hotel in RealtyCalendar by id: guest and contacts, category and room, dates and times, source, booking-site details (booking number, date booked), notes, total / paid / left with each payment, created and changed times; with history, who changed what and when. Not needed before a write: the preview reads the booking itself.
Inputs: booking_id (required), history. Returns: id, left, paid, room, +25 more
list_bookingsList bookingsARead-onlyIdempotent
Bookings and guests of the user's hotel in RealtyCalendar in a period: match=staying (guests in the house, who is in which room), arriving (check-ins, заезды) or departing (check-outs, выезды; rooms to clean). Filters: room, category, source (booking site: Островок, Яндекс…), guest name or phone, holds (заявки), unassigned (неразобранные: no room yet), unpaid (balance left to pay). Totals (sum, paid, left) cover all matches and their whole stays: a stay crossing the period's edge counts in full; say so with the totals. The period defaults to today; to find a guest's booking with no dates given ("найди бронь Петровой") use today to today + 180 days, and say which period you searched. No filter by the date a booking was made: for a recent booking from a site, filter by source and read "Дата бронирования" in get_booking. Not for "is room X free": use check_availability. Not for the user's own calendar, free time or meetings, staff schedules, other hotels or travel plans. Dates: today is in every result; stays are nights (check_out = departure day); a week is Monday to Sunday; "на выходные" = Friday and Saturday nights; a date without a year is the next one, or the last one when the user asks about the past. Say which dates you used.
Inputs: to, from, room, limit, +7 more. Returns: to, from, hint, match, +7 more
list_roomsList roomsARead-onlyIdempotent
Room categories (типы номеров) of the user's hotel in RealtyCalendar and the rooms in each, with ids, capacity and max guests. No availability or prices: use check_availability. Other tools take names directly, so this is not needed first.
Inputs: no named parameters. Returns: categories
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
Each tool targets a distinct object and action: availability/pricing by date, room-category inventory, booking search by period, and single booking by id. The descriptions explicitly fence off the tempting confusions (check_availability vs list_bookings for 'is room X free', list_rooms vs check_availability for availability/prices), so an agent can select correctly.
All four tools follow a strict snake_case verb_noun pattern (check_availability, list_rooms, list_bookings, get_booking). List vs get vs check is used in the conventional, predictable way.
Four tools is lean but each covers a genuinely separate query axis, and there is no redundancy. It sits at the thin edge for a hotel/booking domain, where one might expect at least a write or payment operation.
Read coverage is solid (availability, inventory, booking search, booking detail), but the surface is read-only: no create/update/cancel booking or payment recording. get_booking even references 'a write' and a 'preview' that do not exist as tools here, which is a dead end for an agent trying to follow that instruction.
Maintenance
Related MCP Connectors
Connect AI assistants to hotel reservations, availability, rates, guests, and analytics with OAuth.
Calendar API for AI agents: events, availability, Google/Microsoft setup, scheduling, and iCal.
Run hotels, apartments, job offers and real-estate listings in MyBooking.ai from your AI assistant.
Calendars, tasks, contacts, bookings and agent inboxes for your assistant. EU-hosted, OAuth.
1
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables managing restaurant table bookings through natural language conversations with an AI assistant, with built-in safety measures like no deletion and explicit write enable.MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to search for available desk space, submit room reservations, and let admins approve or reject booking requests through a scoped MCP API.-
- AlicenseAqualityBmaintenanceBook a table, an appointment or a place in a class at a real local business. Live availability, instant confirmation, no account and no API key. Eight tools: search, fetch, get_business, check_availability, create_booking, check_booking, cancel_booking and request_listing. Guest emails in eight languages. Hosted at https://g-guest.app/api/mcp810 npmMIT
- 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