Model Context Protocol

AI agent integrations

Courtbooker publishes a public MCP server so ChatGPT, Claude, Gemini, Cursor and any MCP-compatible assistant can book, list and cancel court reservations on your behalf — with your community's rules enforced server-side.

https://courtbooker.app/mcpStreamable HTTP · OAuth 2.1 · Dynamic client registration
WebMCP-ready. While you're signed in and browsing Courtbooker, the same tools are also exposed to your browser's built-in AI via navigator.modelContext. No extension, no OAuth round-trip — browser agents that implement the WebMCP proposal can call the tools directly as you.

1. Add the connector

In ChatGPT / Claude / Cursor, add a custom connector and paste https://courtbooker.app/mcp.

2. Approve the connection

You'll be redirected to Courtbooker to sign in and approve. Your assistant acts as you — same access, same rules.

3. Ask in plain language

Ask about availability, next reservations, or book a slot. Cancel anytime from the chat.

Example prompts

Once connected, these are the sorts of things you can ask your assistant.

  • "When is my next tennis reservation?"
  • "Can I book a padel court this afternoon between 4pm and 8pm?"
  • "Book me the 18:00 tennis slot on Court 1 tomorrow."
  • "Cancel my Saturday morning booking."
  • "What tennis slots are free this Sunday between 10 and 12?"

Available tools (7)

Every tool your assistant can call on Courtbooker. Live from /.well-known/mcp.json.

list_public_sitesList public communitiesRead-only

List every publicly-visible residential community on Courtbooker. No authentication required — useful for agents to discover communities before a resident signs in.

Input

No parameters.

Output
  • sitesobject[]required
list_sitesList my communitiesRead-only

List residential communities the authenticated user belongs to, with their site_id, name, slug, timezone, role, and residence. Call this first for any user-scoped question ('my bookings', 'available slots today') to obtain the correct `site_id`. If it returns more than one community, ask the user which one.

Input

No parameters.

Output
  • sitesobject[]required

    Communities the caller belongs to. Use `site_id` for other tools.

list_courtsList courtsRead-only

List active courts for a community, optionally filtered by sport (tennis or padel). Useful when the user asks 'which courts do we have' or to resolve a court name to an id. For availability, use `list_available_slots` instead.

Input
  • site_idstring (uuid)required

    Site UUID from list_sites.

  • sporttennis | padel

    Filter by sport.

Output
  • courtsobject[]required
list_available_slotsList available slotsRead-only

Return bookable slots for a community on a given local calendar date. Use this to answer questions like 'can I book tennis this afternoon' or 'what padel slots are free tomorrow between 18:00 and 21:00'. Inputs: - site_id: from `list_sites` (the community the user belongs to). - date: YYYY-MM-DD in the community's local timezone. - sport: 'tennis' or 'padel' to filter courts. - court_id: restrict to a single court. - from_time / to_time: optional local HH:MM window (24h). Slots must START within [from_time, to_time). Use for 'between 4 and 8pm'. Response: per court, `free_slots` with `start_at`/`end_at` in ISO-8601 UTC plus `start_local`/`end_local` HH:MM in the site's timezone. Slots in the past or violating min-notice are omitted. Also returns each court's existing reservations for that day for context.

Input
  • site_idstring (uuid)required

    Site UUID from list_sites.

  • datestringrequired

    Local calendar date YYYY-MM-DD in the community's timezone.

  • sporttennis | padel
  • court_idstring (uuid)
  • from_timestring

    Local HH:MM lower bound (inclusive) on slot start.

  • to_timestring

    Local HH:MM upper bound (exclusive) on slot start.

Output
  • siteobjectrequired

    Echo of the site the results belong to.

  • datestringrequired

    The queried local calendar date (YYYY-MM-DD).

  • timezonestringrequired

    IANA timezone the times are interpreted in.

  • slot_minutesintegerrequired

    Community slot size in minutes. Pass this as `duration_minutes` to create_reservation.

  • min_notice_minutesintegerrequired

    Slots starting sooner than this are omitted.

  • courtsobject[]required
create_reservationBook a court

Book a court for the authenticated user. Use this after confirming an available slot with `list_available_slots` — pass one of the returned `court_id` + `start_at` pairs and the site's `slot_minutes` as `duration_minutes` (usually 60). Recommended flow: 1. `list_sites` -> pick the community's site_id. 2. `list_available_slots` with sport/date/time-window. 3. Show the user the candidate slot and confirm. 4. Call `create_reservation` with that slot. Enforced server-side by RLS and booking rules (min notice, per-day and per-week quotas, max concurrent, days-in-advance). Errors from those rules are returned verbatim so you can relay them to the user. `apartment_id` is optional and defaults to the caller's residence in the site.

Input
  • court_idstring (uuid)required
  • start_atstring (date-time)required

    ISO 8601 start time (UTC or with offset).

  • duration_minutesintegerrequired

    Duration in minutes. Must match the community's slot size (usually 60).

  • apartment_idstring (uuid)

    Optional residence UUID. Defaults to the caller's primary residence for the site.

Output
  • reservationobjectrequired

    The row that was inserted. Its `id` is the `reservation_id` for cancel_reservation.

cancel_reservationCancel a reservationMutates data

Cancel a reservation the authenticated user owns (or has admin rights over). Sets status to 'cancelled'. Use `list_my_reservations` first to look up the `reservation_id` — never guess it. Idempotent: cancelling an already-cancelled reservation is a no-op. Community cancellation-deadline rules are enforced server-side and returned as errors if violated.

Input
  • reservation_idstring (uuid)required
  • reasonstring
Output
  • reservationobjectrequired

    The updated row with status='cancelled'.

list_my_reservationsList my reservationsRead-only

List reservations belonging to the authenticated user. Use this to answer 'when is my next booking', 'what do I have on Saturday', or to look up a reservation_id before calling `cancel_reservation`. Defaults: upcoming, non-cancelled, oldest-first (next up first), limit 50. Set `include_past` or `include_cancelled` to widen the result. Filter by `site_id` when the user belongs to multiple communities. Each item includes the court name, sport, site name, and start/end times both in ISO-8601 UTC and formatted in the community's local timezone (`start_local`, `end_local`).

Input
  • site_idstring (uuid)
  • include_pastboolean

    Include reservations that already ended. Default false.

  • include_cancelledboolean

    Include cancelled reservations. Default false.

  • limitinteger
Output
  • reservationsobject[]required

    Ordered by start_at ascending — index 0 is the next upcoming booking.

Ready to try it?

Sign in to Courtbooker, then paste the MCP URL into your favourite AI assistant. The connection is scoped to your account — you can revoke it any time from your profile.