Skip to main content
Glama
realtycalendar-web-mcp

realtycalendar-web-mcp

by stek29

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

Hosted HTTP

A connector URL for Claude or ChatGPT

Docker, an HTTPS reverse proxy and a persistent server key

Local stdio

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-mcp

To 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:

  1. Generate a server key with openssl rand -base64 32.

  2. 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=1
  3. Restrict access to that file, then start the server:

    chmod 600 deploy/.env
    docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -d
  4. Forward your public HTTPS origin to 127.0.0.1:8080 and have the proxy append the client IP to X-Forwarded-For. Set MCP_TRUST_PROXY_HOPS to 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/mcp

Require approval for write tools in the client; see write approval.

Hosted settings

Variable

Default

Meaning

MCP_PUBLIC_URL

required

Public origin without a path; HTTPS required except for local development

MCP_SERVER_KEY

required

Persistent base64/base64url secret of at least 32 bytes

MCP_SERVER_KEY_PREVIOUS

unset

Previous key accepted during rotation; keep it for the refresh-token lifetime of 30 days

PORT

8080

HTTP listening port

MCP_TRUST_PROXY_HOPS

0

Trusted proxies that append to X-Forwarded-For; 0 uses the direct peer address

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 login

Login 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.js

For 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

RC_TOKEN

required

Session token printed by login

RC_CONFIRM_KEY

random per process

Key that signs preview confirmation tokens

Shared settings

Variable

Default

Meaning

RC_ACCESS

read

read; book adds create; edit adds update/cancel; full adds delete. In hosted mode, the maximum connection level

RC_SITE_BOOKINGS

protect

Protect booking-site reservations from changes RC does not send back to the site. allow permits those changes with a warning

RC_TIMEZONE

Europe/Moscow

Hotel time zone, using an IANA identifier

RC_AUDIT

summary

One audit entry per write; full includes the pre-write booking body and guest data

RC_HIDE_GUEST_PII

false

Hide known structured guest-name and phone fields in MCP responses; accepts true/false or 1/0

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 level

Fixtures 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

Tool specification

Inputs, outputs, errors and approval flow

Architecture

Code structure, upstream client, caching, OAuth and privacy

Booking workflows

Upstream semantics and supported workflows

API scope

Endpoint reference

Testing

Unit checks, eval runners and opt-in live tests

Remaining work

Unfinished client validation and known limitations

Design decisions

Rationale for the current implementation

License

This project's source code is licensed under the Mozilla Public License 2.0.

Available Tools

4 tools
check_availabilityCheck availabilityA
Read-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 bookingA
Read-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 bookingsA
Read-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 roomsA
Read-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

    A4.4/5.0

    Scored across 4 tools

    Disambiguation5/5

    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.

    Naming Consistency5/5

    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.

    Tool Count4/5

    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.

    Completeness3/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables 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
    • F
      license
      Not graded
      quality
      B
      maintenance
      Enables AI agents to search for available desk space, submit room reservations, and let admins approve or reject booking requests through a scoped MCP API.
      -
    • A
      license
      A
      quality
      B
      maintenance
      Book 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/mcp
      8
      10 npm
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables AI assistants to discover availability, place expiring holds, and confirm or cancel appointments for connected booking businesses, with idempotent retries and explicit user consent.
      1
      Apache 2.0