Tool reference
The Foyer MCP server exposes 411 tools across 77 domains. This page is generated from the running registry, so it cannot drift from what the server actually serves.
agents
agents.configureAgents: configure. Mutation — changes data. See the input schema for argument details.
agents.list· read-onlyList all registered agents with their per-tenant config (enabled, schedule, guardrails) and last run status.
agents.proposals.list· read-onlyList agent proposals awaiting human review. Defaults to pending proposals only.
agents.proposals.review· requires confirmationApprove or reject an agent proposal. Approved proposals are logged; execution is handled by the application layer.
agents.runs.list· read-onlyAgents: runs list. Read-only query. See the input schema for argument details.
agents.trigger· requires confirmationManually trigger an agent run. The agent will run asynchronously; check agents.runs.list for status.
ai
ai.acceptDraft· requires confirmationAccept an AI-drafted reply and deliver it to the guest now. This is a real guest-facing send over the booking channel. Requires confirmation.
ai.discard_draftDiscard an AI-generated draft reply. Deletes the draft message and logs the discard for trust-ramp acceptance-rate accounting.
ai.latestDraftForConversation· read-onlyAi: latest draft for conversation. Read-only query. See the input schema for argument details.
ai.metrics· read-onlyAI dashboard data for the tenant: current mode (suggest/auto), 7-day acceptance metrics, auto-mode eligibility, current-month spend, and the last 50 invocations. Read-only.
ai.previewVoiceStyleAi: preview voice style. Mutation — changes data. See the input schema for argument details.
ai.set_mode· requires confirmationFlip tenant AI mode between 'suggest' (operator approves each draft) and 'auto' (eligible drafts auto-send). Going to 'auto' requires the trust-ramp gate (7d soak + 5+ drafts + ≥80% acceptance) — server-side re-check; throws on failure. 'auto' -> 'suggest' is always allowed (kill-switch). Mutating action — requires _confirm: true.
aiQuestions
aiQuestions.createAi questions: create. Mutation — changes data. See the input schema for argument details.
aiQuestions.delete· requires confirmationDelete a custom AI question/FAQ entry.
aiQuestions.get· read-onlyAi questions: get. Read-only query. See the input schema for argument details.
aiQuestions.installDefaultPackAi questions: install default pack. Mutation — changes data. See the input schema for argument details.
aiQuestions.list· read-onlyAi questions: list. Read-only query. See the input schema for argument details.
aiQuestions.setEnabledAi questions: set enabled. Mutation — changes data. See the input schema for argument details.
aiQuestions.testMatch· read-onlyAi questions: test match. Read-only query. See the input schema for argument details.
aiQuestions.updateAi questions: update. Mutation — changes data. See the input schema for argument details.
ai_questions
ai_questions.regenerate_embeddings(Re)compute semantic embeddings for every FAQ question using the tenant's current detection provider. No-op when the mode is 'lexical' (returns embedded=0) or the provider's API key is absent from the server env (returns missingKey=true). Calls the embedding provider API. Owner-only.
ai_questions.report_false_positiveMark an FAQ question as a false positive — increments its false_positive_count, which feeds the detection-accuracy analytics. Use when the classifier matched a question it shouldn't have. Mutating.
api_keys
api_keys.list· read-onlyRead-only list of API keys: id, name, prefix (first 12 chars, e.g. fk_live_a1b2), createdAt, lastUsedAt, revokedAt. Secrets are never returned. **Create/revoke are deliberately not exposed via MCP** — they would enable privilege escalation. Use the web UI.
assistant
assistant.ask· read-onlyAnswer a question directly for an inbound asker (phone and/or email), grounded ONLY on what their trust tier is permitted to see for the current tenant. A contact/staff member gets internal guidelines; a verified guest gets their own booking/keybox; a stranger or a low-trust channel gets only general info and a polite refusal for anything else. Pass channel (whatsapp/hospitable = high trust, email/voice = low) so sensitive data unlocks only on verified channels. Never reveals data outside the asker's tier. Read-only.
availability
availability.query· read-onlyCheck room availability for a date range. Returns rooms (by type and room name) that are NOT blocked for any night in [checkIn, checkOut). Optionally filter by roomType. Each result includes the room id, name, type, and the current price from the default rate plan for checkIn (if set).
billing
billing.summary· read-onlyRead-only billing summary: tenant name, room count, computed monthly price (cents), Stripe subscription state, trial-end, and whether a Stripe customer/subscription exists. Schreib-Ops (Checkout, Portal) bleiben Web-UI-only.
breakfast
breakfast.confirmBreakfast: confirm. Mutation — changes data. See the input schema for argument details.
breakfast.getSettings· read-onlyBreakfast: get settings. Read-only query. See the input schema for argument details.
breakfast.listForDate· read-onlyBreakfast: list for date. Read-only query. See the input schema for argument details.
breakfast.setSettingsBreakfast: set settings. Mutation — changes data. See the input schema for argument details.
cannedResponses
cannedResponses.createCanned responses: create. Mutation — changes data. See the input schema for argument details.
cannedResponses.delete· requires confirmationDelete a canned response template.
cannedResponses.get· read-onlyCanned responses: get. Read-only query. See the input schema for argument details.
cannedResponses.list· read-onlyCanned responses: list. Read-only query. See the input schema for argument details.
cannedResponses.updateCanned responses: update. Mutation — changes data. See the input schema for argument details.
channels
channels.activate_ota· requires confirmationSet an OTA connection status from 'pending' to 'active' so rate and availability pushes begin. Call after credentials have been stored via credentials.set. Mutating action — requires _confirm: true.
channels.connect_ota· requires confirmationAdd or update an OTA connection for the current tenant. Creates the connection with status='pending' if it does not exist, or updates hotelExternalId and resets status to 'pending' on conflict. Mutating action — requires _confirm: true.
channels.disconnect_ota· requires confirmationRemove an OTA connection for the current tenant. Deletes the connection row; rate pushes to this OTA will stop immediately. Mutating action — requires _confirm: true.
channels.list· read-onlyList the four ingestion channels (email, whatsapp, hospitable, voice) with their current state, last-event timestamp, and last-error string. Read-only.
channels.list_ota_connections· read-onlyList all OTA (Online Travel Agency) connections for the current tenant. Returns booking_com and expedia connections with their status, hotel external ID, last sync time, and last error. Read-only.
channels.list_property_mappings· read-onlyList the room_type → Hospitable property UUID mappings for the current tenant. Used to configure which Foyer room types map to which Hospitable listings. Read-only.
channels.remove_property_mapping· requires confirmationRemove a room_type → Hospitable property UUID mapping. Rate-sync will stop pushing to this Hospitable listing for this room type. Mutating action — requires _confirm: true.
channels.resync· requires confirmationManually enqueue Hospitable rate-sync jobs for every mapped room type and every rate record in the given date range. Useful after adding new property mappings or re-enabling sync. Returns { ok, enqueued } — enqueued = number of rate-rows submitted. No-ops if sync is disabled or no property mappings exist. Mutating action — requires _confirm: true.
channels.set_active· requires confirmationPause or resume a single ingestion channel. active=false sets state to 'paused' (a kill-switch — channel won't auto-recover on next event); active=true clears the pause flag and restores normal state. Mutating action — requires _confirm: true.
channels.set_property_mapping· requires confirmationAdd a mapping from a Foyer room type to a Hospitable property UUID. Required for Hospitable rate-sync to know which Hospitable listing to push rates to. One room type can map to multiple Hospitable UUIDs (for multi-room properties). Idempotent — silently ignores duplicate (roomType, propertyUuid) pairs. Mutating action — requires _confirm: true.
channels.sync_status· read-onlyReturn the last 24h sync status for a channel (hospitable by default): last sync log row, error count, and the 10 most recent log entries. Read-only.
channels.toggle_hospitable_rate_sync· requires confirmationEnable or disable automatic Hospitable rate-sync for this tenant. When enabled, every rate change in Foyer enqueues a job that pushes the new price to all mapped Hospitable property UUIDs via the Hospitable API. Requires 'hospitable_api_key' in credentials and at least one property mapping. Mutating action — requires _confirm: true.
checkin
checkin.activeForStay· read-onlyCheckin: active for stay. Read-only query. See the input schema for argument details.
checkin.clear_waiverClear a guest's Meldeschein waiver on a pending check-in session — e.g. after the ID-OCR contradiction warning shows the guest is not domestic after all. The portal then asks the nationality question again on the guest's next visit. Only works while the session is still pending.
checkin.createStart a new online check-in session for a stay.
checkin.extract_id_ocrExtract OCR data from a guest ID photo front side using Claude Haiku 4.5 vision. Returns a structured IdOcrResult (vorname, nachname, geburtsdatum, staatsangehoerigkeit, ausweisnummer, address fields, confidence) cached in guest_id_uploads.ocr_data_json. Re-calling returns the cached result without incurring a new Haiku call. Requires a valid 64-char portal token (guest-auth surface). Returns { ok: false, error } for photo_not_found | not_image | cap_exceeded | ocr_failed.
checkin.get· read-onlyGet a single check-in session's detail.
checkin.getMeldescheinEntry· read-onlyCheckin: get meldeschein entry. Read-only query. See the input schema for argument details.
checkin.getPortalMeldeschein· read-onlyCheckin: get portal meldeschein. Read-only query. See the input schema for argument details.
checkin.get_meldeschein· read-onlyGet the finalized operator Meldeschein entry for a stay, or the guest-portal submitted data if no operator entry exists. Returns null when neither source has data for the stay. Prefers the operator-finalized entry (meldeschein_entries) over the guest-portal submission (meldescheine) when both exist.
checkin.list· read-onlyList check-in sessions, optionally filtered by stay/status.
checkin.list_guest_id_uploads· read-onlyList all guest ID document uploads for a given stay. Returns metadata including guest name, index (0 = primary booker, 1+ = co-travelers), photo URLs for the photo-serve endpoint, and upload timestamps. Only owner and staff roles may call this tool.
checkin.markVerifiedMark a guest's submitted check-in / ID as operator-verified.
checkin.revokeForStay· requires confirmationRevoke the online check-in session for a stay. Requires confirmation.
checkin.upcoming_without_session· read-onlyList stays arriving in the next 14 days that have no checkin_session yet — i.e. guests who have not received a portal link. Use this to identify who needs a Pre-Arrival link sent before their arrival. Returns up to 50 rows ordered by check-in date ascending.
checkin.upsertMeldescheinEntryCreate or update a guest's Meldeschein (German registration) entry.
cityTaxSettings
cityTaxSettings.get· read-onlyCity tax settings: get. Read-only query. See the input schema for argument details.
cityTaxSettings.updateCity tax settings: update. Mutation — changes data. See the input schema for argument details.
city_tax
city_tax.get· read-onlyRead the current tenant's accommodation-tax (Beherbergungssteuer / Kurtaxe / city tax) configuration. Fields: enabled, label, method (per_booking | per_night | per_person_booking | per_person_night | percent_total), flatCents (€ amount ×100, for the flat methods), percent (for percent_total), vatRatePct, maxNights (taxable-nights cap, null = none), adultsOnly (children exempt), includedInTotal (carve out of the booking total vs. add on top). Read-only.
city_tax.updateUpsert the tenant's accommodation-tax config. `method` selects how the tax is computed: per_booking (flat per booking), per_night (flat × nights), per_person_booking (flat × persons), per_person_night (flat × persons × nights), or percent_total (percent of the booking total). `amountEur` is the € amount for the flat methods; `percent` is used for percent_total. `maxNights` caps taxable nights (null = no cap). `adultsOnly` exempts children. `includedInTotal` carves the tax out of the booking total instead of adding it on top. Owner-only.
concierge
concierge.addConcierge: add. Mutation — changes data. See the input schema for argument details.
concierge.delete· requires confirmationDelete a concierge recommendation item.
concierge.list· read-onlyConcierge: list. Read-only query. See the input schema for argument details.
contacts
contacts.deleteDelete a contact by id. Phones cascade via FK. Returns { ok: true } or throws if not found.
contacts.get· read-onlyFetch a single contact by id for this tenant. Returns { contact } with phones embedded, or throws if not found. DRY: delegates to the shared getContact() query (same as the tRPC router).
contacts.guest· read-onlyGet a single guest profile by id (name, email, phone, locale). DRY: delegates to getGuestById() (same as tRPC contacts.guests.byId).
contacts.guestBilling.delete· requires confirmationDelete a guest's billing/invoice address.
contacts.guestBilling.list· read-onlyContacts: guest billing list. Read-only query. See the input schema for argument details.
contacts.guestBilling.upsertContacts: guest billing upsert. Mutation — changes data. See the input schema for argument details.
contacts.guests.byId· read-onlyContacts: guests by id. Read-only query. See the input schema for argument details.
contacts.guests.setEmailContacts: guests set email. Mutation — changes data. See the input schema for argument details.
contacts.invoice-guests· read-onlyList guests that have at least one billing address (the 'Rechnungsgäste'). Each guest carries its billing addresses including the reservation number (reservationRef). Optional search filters over guest name/email and billing company. Default limit 25, max 100. DRY: delegates to the shared invoiceGuests() query (same as the tRPC router).
contacts.list· read-onlyList paginated contacts for this tenant. Supports category filter (reinigung/rezeption/hausmeister/dienstleister/sonstig) and free-text search across display name, company, email, and phone number. Ordered by display name ASC. DRY: delegates to the shared listContacts() query (same as the tRPC router).
contacts.search-guests· read-onlySearch guests for linking to a contact. Searches over guest name, canonical email, and canonical phone number. Default limit: 25. Max: 100. DRY: delegates to the shared searchGuests() query (same as the tRPC router).
contacts.upsertCreate or update a contact with its full phones set. If id is provided, updates the existing contact; otherwise creates a new one. Transactional: diffs the phones set (delete removed, insert/update remaining). Enforces UNIQUE(tenant_id, phone_number) across contacts — throws CONFLICT if a phone number is already assigned to another contact. Returns { contact } with phones embedded.
dashboard
dashboard.aiAnalytics· read-onlyDashboard: ai analytics. Read-only query. See the input schema for argument details.
dashboard.summary· read-onlyGet the operator dashboard's summary KPIs (occupancy, revenue, etc.).
dashboard.today· read-onlyOperator home snapshot: inbound messages in the last 24h, open tasks, urgent tasks, stays checking in/out today, and stays arriving in the next 7 days. Read-only.
deposit_settings
deposit_settings.get· read-onlyGet the current tenant's pre-arrival deposit (Kaution) setting: whether a deposit is requested from guests (`enabled`) and the amount in cents. Read-only.
deposit_settings.updateEnable or disable the pre-arrival deposit (Kaution) for the current tenant and set its amount in cents. When enabling, amountCents must be > 0. When disabling, the amount is preserved. Owner-only.
disclosure
disclosure.assemble· read-onlyAssemble the gated context an inbound caller (phone and/or email) is allowed to see, for the current tenant. Resolves the caller to a trust tier (B2) and returns ONLY the permitted items (internal guidelines, general info, wifi, own keybox, own booking), each tagged with its access (autonom|draft|deny). Deny categories are never fetched; keybox is scoped to the caller's own stays. Pass confidence 'high' only for a verified channel (spoofable caller-ID = 'low'). Read-only.
folio
folio.addLineAdd a charge line (room/extra/tax) to a stay's folio.
folio.addPaymentRecord a payment against a stay's folio.
folio.closeClose the folio for a stay by setting folio_closed_at to now(). Should only be called when balanceCents = 0. Throws folio_not_found if the stay is invisible to the caller's tenant (RLS).
folio.closeFolio· requires confirmationClose a stay's folio. Irreversible once balanced — no further edits. Requires confirmation.
folio.line.updateOverwrite the quantity and unit price (cents) of an existing folio line. totalCents is recomputed as qty × unitCents. RLS: a line outside the caller's tenant is invisible — throws folio_line_not_found.
folio.list· read-onlyList all folio charge lines for a stay, ordered by date then creation time. Returns room_charge (auto-seeded on check-in) and any operator-added extras. RLS: caller sees only lines belonging to their tenant. Read-only.
folio.listPayments· read-onlyFolio: list payments. Read-only query. See the input schema for argument details.
folio.payment.addRecord a payment against a stay folio. Supported methods: cash, card, bank_transfer, voucher, other. amount_cents must be > 0. An optional free-text note can be attached. RLS: only payments within the caller's tenant are visible.
folio.payment.list· read-onlyList all payments recorded against a stay folio, ordered by recorded_at descending. RLS: only payments within the caller's tenant are returned. Read-only.
folio.payment.removeDelete a folio payment by id. RLS silence: if the payment belongs to another tenant it is invisible — returns { deleted: false } without an error.
folio.removeLine· requires confirmationRemove a charge line from a folio.
folio.removePayment· requires confirmationRemove a recorded payment from a folio.
folio.resetReset a stay's auto-seeded folio lines (room_charge + city_tax, addedBy='system') to their computed original state, discarding manual edits. Operator-added extras are kept. Regenerates via folio-init. RLS: the stay must belong to the caller's tenant.
folio.summary· read-onlyReturn aggregated folio totals for a stay: subtotal (net of VAT), vatCents (total tax), totalCents (gross = subtotal + vat), and lineCount. VAT is back-calculated from each line's vatRatePct (totalCents already includes VAT). Read-only.
folio.updateLineEdit an existing folio charge line's description or amount.
fritzbox-calls
fritzbox-calls.contacts.list· read-onlyList all call contacts for this tenant, ordered by display name. Contacts enrich the call log (display name + category shown on each call row). Returns { contacts: Contact[] }. DRY: delegates to the shared listContacts() query (same as the tRPC router).
fritzbox-calls.contacts.upsertCreate or update a call contact for this tenant. Conflict key: (tenantId, phoneNumber) — unique per tenant, so calling with an existing phone number updates the display name and category. Returns the upserted contact.
fritzbox-calls.list· read-onlyList paginated FritzBox calls for this tenant. Supports filter (all/incoming/outgoing/missed), period (all/today/week/month), free-text search across phone number, guest name, FritzBox device name, and contact display name. Newest-first. DRY: delegates to the shared listCalls() query (same as the tRPC router).
fritzbox-calls.refreshTrigger a FritzBox call import for this tenant. Fetches the current call list from the FritzBox device and upserts any new calls into the database. Returns { imported, duplicates }.
fritzbox-calls.set-callbackSet or clear the callback status on a FritzBox call. 4 states: null=Offen (open), 'in_progress'=In Bearbeitung (in progress), 'called_back'=Zurückgerufen (returned), 'no_answer'=Kein Anschluss (no answer). Pass null to reset to open. Returns the updated row. 404 error if call not found (RLS-isolated).
fritzbox-calls.set-noteSet or clear the note on a FritzBox call. Empty / whitespace-only input clears the note (stored as null). Text is sanitized (NUL bytes removed) and truncated to 2000 characters. Returns the updated row. 404 error if call not found (RLS-isolated).
fritzbox-calls.stats· read-onlyAggregated call statistics for this tenant: today's total and missed calls, average call duration (seconds), and total call count across all time. DRY: delegates to the shared callStats() query (same as the tRPC router).
fritzbox-calls.status· read-onlyCheck the FritzBox connection status for this tenant. Returns { online: boolean; reason?: string }. reason is present when online=false (e.g. 'FRITZBOX_URL not configured').
fritzboxCalls
fritzboxCalls.listContacts· read-onlyFritzbox calls: list contacts. Read-only query. See the input schema for argument details.
fritzboxCalls.upsertContactFritzbox calls: upsert contact. Mutation — changes data. See the input schema for argument details.
guest-billing
guest-billing.deleteDelete a billing address by id (tenant-scoped, RLS-enforced). Returns { ok: true } or throws if not found. DRY: delegates to the shared deleteGuestBilling() function (same as the tRPC router).
guest-billing.list· read-onlyList all billing addresses for a guest (tenant-scoped, RLS-enforced). Returns { addresses } ordered by createdAt ASC. DRY: delegates to the shared listGuestBilling() query (same as the tRPC router).
guest-billing.upsertCreate or update a billing address for a guest. If id is provided and exists, updates the existing row; if id is provided but does not exist, inserts with that id; if id is omitted, inserts with auto-generated id. If isDefault:true, atomically clears all other defaults for the guest first (the clear + set run inside the same withTenant() transaction — partial-unique safe). Returns { address: GuestBillingRow }. DRY: delegates to the shared upsertGuestBilling() function (same as the tRPC router).
guests
guests.set-emailSet the canonical email (guests.canonical_email) for a guest. Tenant-scoped via RLS — only the guest's own tenant can update it. Returns { ok: true } or throws if guest not found. DRY: delegates to the shared setGuestEmail() function (same as the tRPC router).
guidelines
guidelines.delete· requires confirmationDelete a guideline by id (owner only).
guidelines.get· read-onlyGet one guideline (incl. markdown body) by id for the current tenant. Read-only.
guidelines.list· read-onlyList internal staff-handbook guidelines for the current tenant (id, title, type, category, tags, updatedAt). Read-only.
guidelines.upsertCreate or update a guideline (owner only). Provide id to update. Generates an embedding on save.
handover
handover.briefing· read-onlyHandover: briefing. Read-only query. See the input schema for argument details.
handover.getToday· read-onlyGet today's shift-handover note.
handover.getYesterday· read-onlyHandover: get yesterday. Read-only query. See the input schema for argument details.
handover.listRecent· read-onlyHandover: list recent. Read-only query. See the input schema for argument details.
handover.saveSave the shift-handover note for the day.
hospitable
hospitable.heal_messages· requires confirmationRecover this tenant's Hospitable MESSAGE backlog — messages the 15-min poll-reconcile can no longer reach because their reservation aged past its rolling 14-day lookback window (e.g. messages created between the historical backfill snapshot and live-capture go-live). Walks hospitable_property_mappings, pages reservations over a WIDE lookbackDays window, and — comparing each reservation's Hospitable last_message_at against the latest message Foyer has stored — re-ingests ONLY the drifted ones through the idempotent shared path (no AI replay, no duplicates). Pass dryRun=true to count drifted reservations without writing. Returns { ok:true, reservationsScanned, drifted, messagesRecovered, sample } or { ok:false, reason, message }. Mutating (unless dryRun) — requires _confirm: true.
hospitable.import_reservations· requires confirmationBackfill this tenant's Hospitable reservations into Foyer stays (+ minimal guests), so a newly connected hotel doesn't start with an empty calendar. Walks the tenant's hospitable_property_mappings and queries reservations per mapped property; unmapped properties are never imported. Idempotent on (tenant, ota_source='hospitable', reservation.code) — re-running updates rather than duplicates. Pass dryRun=true to count would-create/would-update without writing. Returns either { ok: true, ...counts, sample } or { ok: false, reason, message }. Mutating action (unless dryRun) — requires _confirm: true.
hospitable.resync_reservation· requires confirmationRe-pull ONE Hospitable reservation's messages into Foyer on demand — the targeted fix for a reservation the 15-min poll-reconcile can no longer reach (it aged past the rolling 14-day lookback). Fetches every message on the reservation and re-ingests through the idempotent shared path (no AI replay, no duplicates), so re-running is a no-op. Takes the reservation UUID (NOT the reservation code). Returns { ok:true, messagesSeen, messagesInserted, skipped } or { ok:false, reason, message }. Mutating — requires _confirm: true.
hotelFacts
hotelFacts.getInfoSections· read-onlyHotel facts: get info sections. Read-only query. See the input schema for argument details.
hotelFacts.getTimeSettings· read-onlyHotel facts: get time settings. Read-only query. See the input schema for argument details.
hotelFacts.updateInfoSectionHotel facts: update info section. Mutation — changes data. See the input schema for argument details.
hotelFacts.updateTimeSettingsHotel facts: update time settings. Mutation — changes data. See the input schema for argument details.
hotelFacts.upsertHotel facts: upsert. Mutation — changes data. See the input schema for argument details.
hotel_facts
hotel_facts.delete· requires confirmationPermanently delete a hotel fact by its key. All locale translations are removed. Destructive — requires _confirm: true. Owner-only.
hotel_facts.list· read-onlyList all hotel facts for the current tenant, ordered by category then key. Facts are key/value pairs used by the pre-arrival guest portal and the %fact:key% substitution renderer. Returns id, key, category, valueTranslations (locale→string map), description, usedBy, verifiedAt, and updatedAt for each fact. Read-only.
hotel_facts.updateUpsert a hotel fact's value for a given locale. If the fact key does not exist it is created; if it exists the locale is merged into the existing valueTranslations map. Category is inferred from the key prefix (e.g. "wifi.password" → category "wifi"). Default locale is "de". Owner-only. Returns the affected row id.
hotel_info_sections
hotel_info_sections.get· read-onlyRead all hotel info sections (wifi, parking, transit, house_rules, checkout, luggage) for the current tenant. Missing sections are returned with defaults (enabled: false, content: ''). Read-only.
hotel_info_sections.updateUpdate a single hotel info section. Merges the supplied key into the existing hotelInfoSections JSONB, preserving all other sections. Owner-only.
housekeeping
housekeeping.assignTaskAssign a housekeeping task to a staff member.
housekeeping.completeTaskMark a housekeeping task complete.
housekeeping.createManualTaskCreate an ad-hoc housekeeping task outside the normal schedule.
housekeeping.createRoomHousekeeping: create room. Mutation — changes data. See the input schema for argument details.
housekeeping.deleteTask· requires confirmationDelete a housekeeping task.
housekeeping.importRoomsFromStaysHousekeeping: import rooms from stays. Mutation — changes data. See the input schema for argument details.
housekeeping.listRooms· read-onlyHousekeeping: list rooms. Read-only query. See the input schema for argument details.
housekeeping.setRoomMaintenanceFlag or clear maintenance state on a room.
housekeeping.skipTaskHousekeeping: skip task. Mutation — changes data. See the input schema for argument details.
housekeeping.startTaskMark a housekeeping task as started (in progress).
housekeeping.tasks-window· read-onlyCleaning tasks across a date window for the calendar Tasks-view. Returns id, roomName (unit code), floor, date, taskType (checkout/midstay/deep_clean/manual), and status (pending/in_progress/completed/skipped). Read-only.
housekeeping.tasksForDate· read-onlyHousekeeping: tasks for date. Read-only query. See the input schema for argument details.
housekeeping.tasksForWindow· read-onlyHousekeeping: tasks for window. Read-only query. See the input schema for argument details.
housekeeping.todayOverview· read-onlyHousekeeping: today overview. Read-only query. See the input schema for argument details.
housekeeping.todayTasks· read-onlyHousekeeping: today tasks. Read-only query. See the input schema for argument details.
identity
identity.resolve· read-onlyResolve an inbound caller (phone and/or email) to a trust tier for the current tenant: a contact category (reinigung|rezeption|hausmeister|dienstleister|sonstig), 'gast' (a guest with an ACTIVE stay — stayIds included so callers can scope to the guest's own stay), or 'unbekannt'. Contact match beats guest. Read-only.
inbox
inbox.accept_draftApprove an AI-generated draft, swapping aiLayer to 'manual' (operator chain-of-custody). For stay-bound conversations, delivers the message via the channel dispatcher (real outbound send + message.sent event) and removes the draft row. For loose threads (no stay), flips the draft to state=sent in place (flip-only, no delivery). Optional bodyOverride lets the operator edit the suggestion before sending.
inbox.draft_replyRun the P2.2 AI pipeline (L0 sensitive / L1 rules / L2 LLM) for a given inbound message and persist a draft outbound message row. Returns the resulting draft. NOTE: This writes a draft (not pure read-only) — operators can then send it via inbox.accept_draft.
inbox.list_by_stay· read-onlyList all sent messages (inbound + outbound) for a stay's conversation, oldest-first. Excludes drafts. Read-only.
inbox.list_triage· read-onlyPaginated triage feed of messages across the tenant, newest first. Cursor is the ISO timestamp of the last item from the previous page. filter='all' is the only meaningful value in v1; other values currently return the same data (filter logic lands in P2.2).
inbox.list_unanswered· read-onlyList up to 50 inbound guest messages where no operator reply has been sent in the same conversation since the inbound. Newest-first. Read-only.
inbox.send_replySend an outbound reply for a stay's conversation. Channel auto-resolves from the latest message in the thread (email/whatsapp/hospitable). Persists the outbound message and emits the message.sent webhook.
invoices
invoices.cancel· requires confirmation**DESTRUCTIVE**: Mark an invoice as cancelled. The PDF is preserved as an audit record. Once cancelled, the invoice cannot be resent. Use `invoices.reissue` to create a corrected replacement. Requires _confirm: true.
invoices.create_requestMint a guest-facing invoice-request link for a reservation: creates a submission row (status pending, workflow offen) with a CSPRNG token and returns { submissionId, token, path } where path is the public form URL (/invoice-request/{token}) to send the guest. Throws 'reservation_not_found' if the reservation is not in this tenant.
invoices.get· read-onlyFetch a single Foyer-native invoice by UUID with joined reservation, address, tax-id and line-items. Throws 'invoice_not_found' if the row is missing or belongs to another tenant. Read-only.
invoices.list· read-onlyList Foyer-native invoices (operator inbox + history). All filters are optional: status (draft|created|sent|cancelled|reissued), reservationId (UUID), from/to (YYYY-MM-DD, matched against createdAt), limit (1-500, default 100), offset (default 0). Ordered by createdAt desc. Read-only.
invoices.list_requests· read-onlyList invoice requests (Anfragen): every invoice-eligible booking joined with its latest submission, showing the operator workflow status (offen|in_bearbeitung|versandbereit|erledigt, default offen) and completeness badges (hasAddress / hasTaxId / hasInvoice). Optional filters: workflowStatus, needsInvoice (bookings with no invoice yet), search (guest name/email/reservation code), limit (1-200, default 100), offset. Read-only.
invoices.reissue· requires confirmation**DESTRUCTIVE**: Mark an existing invoice as `reissued` and create a fresh draft for the same reservation, with a new sequential number and a `parent_invoice_id` link back to the original. The new draft starts without a PDF (placeholder file refs). Requires _confirm: true.
invoices.remove_request_billing· requires confirmationRemove billing parts from a reservation's invoice request (command-center 'Löschen'): set tax=true to soft-delete the tax-id (is_removed — none shows, survives the daily re-sync), email=true to hard-delete the billing email. Addresses have no delete. Returns the resulting billing. Mutating action — requires _confirm: true.
invoices.request_billing· read-onlyCollected billing data for a reservation's invoice request: the latest billing address (name/company, lines, postal code, city, country, isBusiness) and tax-id (value + kind: ust_idnr|steuernummer). Both nullable when the guest hasn't provided them. Read-only.
invoices.request_stats· read-onlyInvoice-request pipeline counts for the Anfragen tabs: total + per workflow status (offen, in_bearbeitung, versandbereit, erledigt) + needsInvoice (eligible bookings with no invoice yet). Read-only.
invoices.send· requires confirmationEmail the invoice to the guest. This is a real send over the configured channel. Requires confirmation.
invoices.send_smtp· requires confirmation**IRREVERSIBLE**: send a Foyer-native invoice PDF to the guest via email. Uses Postmark BYOK if the tenant has configured a token, else falls back to the Gmail SMTP relay. Marks the invoice as 'sent' on success. Once the remote MTA accepts the message there is no way to recall it. Mutating action — requires _confirm: true.
invoices.set_request_statusSet the operator workflow status (offen|in_bearbeitung|versandbereit|erledigt) for a reservation's invoice request. Lazily creates a submission row on first touch and logs the transition. Throws 'reservation_not_found' if the reservation is not in this tenant.
invoices.stats· read-onlyCounters for the operator dashboard stat-strip: total + per-status (draft, created, sent, cancelled, reissued) for the caller's tenant. Read-only.
invoices.submitFormInvoices: submit form. Mutation — changes data. See the input schema for argument details.
invoices.update_address· requires confirmationUpdate the billing address on a Foyer-native invoice. Inserts a new invoice_addresses row (append-only — old rows stay for audit) and repoints invoices.address_id at it. Use to correct typos / fix incomplete guest submissions. Mutating action — requires _confirm: true.
invoices.update_email· requires confirmationSet or replace the billing email for a reservation. Inserts a new invoice_emails row (append-only) — send-time logic resolves the latest email by reservation, so this cascades to all future invoices for that stay. Mutating action — requires _confirm: true.
invoices.update_request_billing· requires confirmationEdit the collected billing data for a reservation's invoice request (command-center 'Bearbeiten'): set the billing address (name/company + lines + postal code + city + country + isBusiness), the tax-id (value + kind: ust_idnr|steuernummer), and/or the billing email. Each part is optional; a provided part is appended (append-only, latest wins). Returns the resulting billing. Mutating action — requires _confirm: true.
invoices.update_tax_id· requires confirmationSet or replace the tax ID on a Foyer-native invoice. Inserts a new invoice_tax_ids row (append-only — old rows stay for audit) and repoints invoices.tax_id_id at it. `kind` distinguishes USt-IdNr (EU VAT) from Steuernummer (DE local). Mutating action — requires _confirm: true.
kassenbuch
kassenbuch.add_entry· requires confirmationAdd a single cash entry (income or expense) to the ledger. Type is 'income' or 'expense' (note: English, not 'einnahme'/'ausgabe'). If entryDate is omitted, today is used. amount must be > 0. reservationId links the entry to a stay UUID; reservationCode is the human-readable booking code (e.g. 'HM54KEHW5X'). Mutating — requires _confirm: true.
kassenbuch.balance· read-onlyAggregate cash-book balance: total income + expense over all-time, today's income + expense subtotal, and the timestamp of the most-recent entry. Use for 'wie viel ist drin?' summaries. Read-only.
kassenbuch.categories· read-onlyValid income + expense category labels accepted by the cash-book. Pre-context for any add-entry prompt — pick from these values. Read-only.
kassenbuch.delete_entry· requires confirmation**DESTRUCTIVE**: hard-delete a cash entry by UUID. No soft-delete — the row is gone. Used by the accountant for typo fixes. Mutating — requires _confirm: true.
kassenbuch.list_for_date· read-onlyCash-book entries for a single date (YYYY-MM-DD). Read-only. Useful for 'was war am 15.04.?' lookups.
kassenbuch.list_today· read-onlyToday's cash-book entries plus aggregated income / expense / net total for the day. Date is computed against the server's CURRENT_DATE (UTC in the DB; convert to Europe/Berlin client-side if needed). Read-only.
kassenbuch.report· read-onlyCash-book report for a date range (from/to inclusive, YYYY-MM-DD). Returns per-category breakdowns + period totals. Read-only.
lost-found
lost-found.createRecord a new lost-and-found item for this tenant. Defaults to status=held.
lost-found.list· read-onlyList lost-and-found items for this tenant, newest-first. Filter by status (held/returned/shipped/discarded).
lostFound
lostFound.discard· requires confirmationDiscard a lost & found item (marks it disposed of, not returned to a guest).
lostFound.markReturnedLost found: mark returned. Mutation — changes data. See the input schema for argument details.
lostFound.updatePhotoLost found: update photo. Mutation — changes data. See the input schema for argument details.
me
me.get· read-onlyReturns the current authenticated user's identity (userId, tenantId, role). Useful for verifying the auth context across all four surfaces (tRPC, MCP, REST).
members
members.invite· requires confirmationInvite a new tenant member (staff, reception, housekeeping, or maintenance). Provide either email OR phone (at least one required). Creates the user row; magic-link delivery is wired in later phases. Mutating action — requires _confirm: true.
members.list· read-onlyList all tenant members (owner, staff, housekeeping, maintenance) with their contact and locale. Used as context for task-assignment and scheduling. Read-only.
members.update· requires confirmationUpdate a tenant member's role and/or module permissions. `role` optional (owner/staff/reception/housekeeping/maintenance). `modulePermissions`: an array of module keys = explicit override (invalid keys dropped); null = reset to the role default; omit while setting a role = reset to that role's default. Blocks demoting the last owner of a tenant (last_owner). Mutating — requires _confirm: true.
messages
messages.listByStay· read-onlyList all messages for a single stay's conversation thread.
messages.listConversations· read-onlyList guest message conversations (inbox threads).
messages.listUnconfirmed· read-onlyMessages: list unconfirmed. Read-only query. See the input schema for argument details.
messages.markDeliveredMessages: mark delivered. Mutation — changes data. See the input schema for argument details.
messages.resyncReservationRe-pull a reservation's message history from Hospitable to heal a sync gap. Idempotent, read-mostly.
messages.send· requires confirmationSend a message to the guest on a reservation's conversation thread. This contacts the guest for real over the booking channel (Airbnb/Booking/email). Requires confirmation.
messaging-rules
messaging-rules.host-history· read-onlyCC-parity 'Verlauf': list ALL outbound Hospitable host messages in an optional date range (YYYY-MM-DD, tenant timezone), attributed to their source — a Foyer messaging rule (by name), Hospitable's own automation ('Automated (Hospitable)'), or a manual host send. Manual sends (included in 'all') are excluded by default (source='all'); pass source='manual' to see them, 'scheduler' for Foyer-rule sends only, or 'hospitable_auto' for Hospitable's automation only. Also returns KPI stats (sent/delivered/failed/tomorrow_planned/week_planned) for the same range. Read-only.
messaging-rules.preview-queue-item· read-onlyPreview a scheduled (pending) messaging-queue item: renders the message with the CURRENT rule template, custom codes, hotel facts and room overrides — exactly what the sender will produce at fire time. Returns language, subject, body and a skippedReason when the item would be skipped (rule disabled, stay missing, empty template). Read-only.
messaging-rules.send-queue-item-nowSend ONE pending scheduled-message queue item immediately instead of waiting for its scheduled time. Uses the exact same render+dispatch path as the cron sender. Fails with not_pending when the item is not in 'pending' state.
messagingRules
messagingRules.createRuleCreate a new automated messaging rule.
messagingRules.deleteCode· requires confirmationDelete a custom message short-code.
messagingRules.deleteRule· requires confirmationDelete an automated messaging rule.
messagingRules.getRule· read-onlyMessaging rules: get rule. Read-only query. See the input schema for argument details.
messagingRules.listCodes· read-onlyMessaging rules: list codes. Read-only query. See the input schema for argument details.
messagingRules.retryQueueItemRetry a failed queued outbound message.
messagingRules.updateRuleEdit an existing automated messaging rule.
messagingRules.upsertCodeMessaging rules: upsert code. Mutation — changes data. See the input schema for argument details.
messaging_rules
messaging_rules.cancel_queue_item· requires confirmationCancel a PENDING scheduled guest message so it is never sent. Fails if it is no longer pending. Requires confirmation.
messaging_rules.edit_queue_item· requires confirmationEdit a PENDING scheduled guest message before it is sent — override its subject, body, and/or scheduled time. Fails if the message is no longer pending. Requires confirmation.
messaging_rules.list_queue· read-onlyList scheduled + already-sent automatic guest messages across all stays (the queue), newest first, optionally filtered by status (pending|sent|skipped|failed|cancelled). Each item carries the rule name, stay + room, scheduled time, channel, rendered subject, and outcome. Read-only.
messaging_rules.list_rules· read-onlyList the tenant's automatic guest-message rules: name, whether enabled, priority, the trigger (reference event + offset in minutes), and the channel. Read-only.
messaging_rules.resend_queue_item· requires confirmationRe-send an already-processed scheduled guest message (sent|failed|cancelled): clones it to a fresh PENDING row (new instance key, scheduled now) which the sender re-renders from the current rule + stay and dispatches. Bypasses idempotency; the original history row is kept. Requires confirmation.
messaging_rules.scheduled_for_stay· read-onlyList the automatic guest messages scheduled for (and already sent to) one stay, ordered chronologically. Read-only. Each item carries the rule name, channel, scheduled time, status (pending|sent|skipped|failed|cancelled), rendered subject/body, and — when applicable — sent time and failure reason.
messaging_rules.seed_pre_arrival_defaultsIdempotent seed: creates the 'Pre-Arrival Portal' messaging rule for the current tenant if no rule with triggerReference=check_in and a negative offset exists yet. The rule sends guests a portal link by email 48 hours before arrival (−2880 min offset) with German and English templates containing the %checkin_url% placeholder. Returns { seeded: true } when created, { seeded: false, reason: 'already_exists' } when skipped.
notificationRules
notificationRules.byId· read-onlyNotification rules: by id. Read-only query. See the input schema for argument details.
notificationRules.createCreate a new notification rule.
notificationRules.delete· requires confirmationDelete a notification rule.
notificationRules.dryRunNotification rules: dry run. Mutation — changes data. See the input schema for argument details.
notificationRules.executions· read-onlyNotification rules: executions. Read-only query. See the input schema for argument details.
notificationRules.list· read-onlyNotification rules: list. Read-only query. See the input schema for argument details.
notificationRules.toggleNotification rules: toggle. Mutation — changes data. See the input schema for argument details.
notificationRules.trigger· requires confirmationManually fire a notification rule right now — sends the rule's real notification(s) immediately, out of band. Requires confirmation.
notificationRules.updateNotification rules: update. Mutation — changes data. See the input schema for argument details.
onboarding
onboarding.dismissOnboarding: dismiss. Mutation — changes data. See the input schema for argument details.
onboarding.state· read-onlyOnboarding: state. Read-only query. See the input schema for argument details.
orders
orders.list· read-onlyList in-stay orders for this tenant, newest-first. Filter by stayId (per-stay folio drill-down) or status (pending/confirmed/delivered/cancelled). Read-only.
orders.listCatalog· read-onlyOrders: list catalog. Read-only query. See the input schema for argument details.
orders.listCatalogByToken· read-onlyOrders: list catalog by token. Read-only query. See the input schema for argument details.
orders.listOrders· read-onlyOrders: list orders. Read-only query. See the input schema for argument details.
orders.placeOrderByTokenOrders: place order by token. Mutation — changes data. See the input schema for argument details.
orders.place_orderPlace an in-stay order on behalf of a guest. Verifies the catalog item belongs to this tenant + is active, inserts the stay_orders row, then writes a folio_lines charge (VAT 19% for in-stay extras). Best-effort: if the folio insert fails the order still exists with folioLineId=NULL.
orders.updateOrderStatusAdvance a guest order's status (received / preparing / delivered).
orders.update_status· requires confirmationTransition an order to confirmed / delivered / cancelled. Owner-only. Cancellation does NOT remove the associated folio_lines row — staff must reverse the charge manually if needed. Confirmation-gated.
orders.upsertCatalogItemOrders: upsert catalog item. Mutation — changes data. See the input schema for argument details.
plan
plan.entitlements· read-onlyPlan: entitlements. Read-only query. See the input schema for argument details.
properties
properties.byUuid· read-onlyProperties: by uuid. Read-only query. See the input schema for argument details.
properties.get· read-onlyFetch a single property's detail by its Hospitable property UUID (core fields, mapped local room, capacities, amenities, price/availability summary, house rules, upcoming reservations). DRY: delegates to getPropertyByUuid() (same as tRPC properties.byUuid).
rate-plans
rate-plans.list· read-onlyList all rate plans for the tenant. Returns id, name, isDefault, priority, refundable, cancellationWindowHours, minLeadTimeHours, maxLeadTimeDays, guestSegment, and inheritFromId. Ordered by priority then name.
rate-suggestions
rate-suggestions.act· requires confirmationAct on a rate suggestion: 'accepted' writes the suggested (or override) price into room_rates for that room-type/date, 'rejected' dismisses it, 'override' records a custom price. Writes pricing — requires confirmation.
rate-suggestions.get_auto_mode· read-onlyRead the current rate_suggestion_auto_mode setting for the tenant. Returns 'off' (no automation), 'suggest' (daily suggestions for operator review), or 'auto' (daily suggestions + auto-apply within ±20% guard). Read-only. Rate suggestions include a losHint field ({ minStay: number } | null) set when occupancy >= 75%; auto-mode writes minStay to rate_restrictions automatically.
rate-suggestions.get_benchmark· read-onlyGet anonymous cross-tenant benchmark rates for a specific date (p25/p50/p75 in cents). Returns null if fewer than 5 tenants are in the cohort (k-anonymity threshold). The cohort is determined by the tenant's country and room-count size band ('5-15' | '16-30' | '31-60' | '60+'). Data is refreshed daily at 03:00 UTC.
rate-suggestions.get_benchmark_opt_in· read-onlyGet the current tenant's benchmark opt-in status. When enabled, this tenant's room_rates contribute to the anonymous cross-tenant benchmark pool. Returns { enabled: boolean }.
rate-suggestions.list· read-onlyList AI-generated nightly rate suggestions in a date range — each with the suggested and current price (cents), a rationale, the LOS hint, and whether it was already acted on (accepted/rejected/override). Read-only.
rate-suggestions.set_auto_mode· requires confirmationUpdate the rate_suggestion_auto_mode setting for the tenant. 'off' disables automation; 'suggest' enables daily generation of rate suggestions for operator review; 'auto' additionally applies suggestions that fall within the ±20% guard automatically. Requires confirmation.
rate-suggestions.set_benchmark_opt_in· requires confirmationEnable or disable this tenant's participation in the anonymous rate benchmark pool. When enabled, the tenant's room_rates feed the aggregated benchmark that all opted-in tenants in the same country + size band can see. The benchmark only surfaces when >= 5 tenants are in the cohort. Requires confirmation.
rateSuggestions
rateSuggestions.generateRate suggestions: generate. Mutation — changes data. See the input schema for argument details.
rates
rates.blockRoomDatesRates: block room dates. Mutation — changes data. See the input schema for argument details.
rates.block_dates· requires confirmationBlock a date range for a unit (room id) so it cannot be booked — e.g. maintenance or owner use. Inserts the blocked nights (idempotent) and best-effort closes the dates on connected OTA channels. Dates are YYYY-MM-DD inclusive. Requires confirmation.
rates.bulk_setSet the same price across a date range for a given room type. Inserts or updates one row per night between dateFrom and dateTo (inclusive). Uses the tenant's default rate plan when ratePlanId is omitted. Returns the count of rows inserted/updated.
rates.createPlanCreate a new rate plan.
rates.deleteDelete a specific room rate by its UUID. Returns the deleted rate's id.
rates.deletePlan· requires confirmationDelete an existing rate plan.
rates.deleteRestriction· requires confirmationDelete a stay-length/date rate restriction.
rates.list· read-onlyList room rates for a date range. Optional filters: roomType and ratePlanId (defaults to the tenant's default rate plan if omitted). Returns one row per (roomType, date) with priceCents and currency.
rates.listBlockedDates· read-onlyRates: list blocked dates. Read-only query. See the input schema for argument details.
rates.listBulkEdits· read-onlyRates: list bulk edits. Read-only query. See the input schema for argument details.
rates.listChannelSync· read-onlyRates: list channel sync. Read-only query. See the input schema for argument details.
rates.listPlans· read-onlyList the property's rate plans.
rates.list_restrictions· read-onlyList min-stay / max-stay restrictions for a date range. Optional ratePlanId filter (defaults to tenant's default plan). Returns one row per (roomType, date) with stopSell, cta, ctd, minStay, maxStay flags.
rates.manualResyncRates: manual resync. Mutation — changes data. See the input schema for argument details.
rates.pushPriceRates: push price. Mutation — changes data. See the input schema for argument details.
rates.syncUnitCalendarRates: sync unit calendar. Mutation — changes data. See the input schema for argument details.
rates.unblockDatesRates: unblock dates. Mutation — changes data. See the input schema for argument details.
rates.undoBulkEditRates: undo bulk edit. Mutation — changes data. See the input schema for argument details.
rates.unit-calendar· read-onlyPer-unit nightly prices + availability mirrored from Hospitable's calendar for a date window. Returns room (unit code), date, priceCents, currency, available. Read-only; populated by the hospitable-calendar-sync worker.
rates.updatePlanEdit an existing rate plan.
rates.upsertSet the price for a specific room type on a specific date. Creates the row if it does not exist, or updates priceCents and currency if it does. Uses the tenant's default rate plan when ratePlanId is omitted.
rates.upsertRestrictionRates: upsert restriction. Mutation — changes data. See the input schema for argument details.
registration-settings
registration-settings.get· read-onlyRead the current tenant's guest-registration (Meldeschein) policy. Fields: registrationPolicy (auto = derive from the hotel's country, e.g. DE since BEG IV 2025 = foreign guests only | all_guests | foreign_only | none), registrationKurort (spa/health-resort flag — keeps the duty for ALL guests, only effective for DE tenants on 'auto'), idUploadMode (always | when_required | never — gates the ID-upload section in portal layout v2), country (ISO-2 hotel country) and effectiveRequirement (the live-resolved requirement the guest portal enforces). Read-only.
registration-settings.updateUpdate the tenant's guest-registration (Meldeschein) policy. `registrationPolicy` overrides the country default: auto (recommended — derive from the hotel's country), all_guests, foreign_only or none. `registrationKurort` marks a spa/health-resort with visitor's tax (keeps the duty for ALL guests; only effective for DE tenants on 'auto'). `idUploadMode` gates the ID-upload section in portal layout v2: always, when_required (only when a Meldeschein is required for the guest) or never. Retention/deletion of already collected registration data always follows the country's law, regardless of this policy. Owner-only.
reports
reports.revenue_stats· read-onlyRevenue + occupancy KPIs over a 7/30/90-day window: occupancy %, ADR, RevPAR, total revenue (cents), a daily revenue series, and a per-room-type breakdown. Read-only. Revenue is sourced from folio_lines (Foyer-native authoritative).
reports.summary· read-onlyReports: summary. Read-only query. See the input schema for argument details.
review-requests
review-requests.list· read-onlyList review requests sent for this tenant. Returns stayId, channel, status, sentAt.
ring
ring.connection.delete· requires confirmationDelete a Ring connection by id. Tenant-scoped. Cascade-deletes its doorbells.
ring.connection.upsert· requires confirmationCreate or update a Ring account connection. `ringType` is 'mock' (placeholder) or 'ring' (real cloud). `credentials.refreshToken` is stored encrypted. Pass `id` to update, omit to insert.
ring.doorbell.delete· requires confirmationDelete a Ring doorbell by id. Tenant-scoped.
ring.doorbell.upsert· requires confirmationCreate or update a Ring doorbell behind a connection. `deviceId` is the Ring camera id. Pass `id` to update, omit to insert.
ring.list· read-onlyList Ring doorbells for this tenant (id, name, location, active). Credentials and device ids are NOT returned — view/edit via the operator settings UI.
security-access-log
security-access-log.list· read-onlyList recent camera access-audit entries (who viewed which camera when) for this tenant, newest first. Owner-only.
security-cameras
security-cameras.camera.delete· requires confirmationDelete a camera by id. Tenant-scoped.
security-cameras.camera.upsert· requires confirmationCreate or update a camera behind a connection. `streamId` is the go2rtc source name. Pass `id` to update, omit to insert.
security-cameras.connection.delete· requires confirmationDelete a go2rtc connection by id. Tenant-scoped. Cascade-deletes the cameras behind it.
security-cameras.connection.upsert· requires confirmationCreate or update a go2rtc connection (the property's camera gateway). Pass `id` to update, omit to insert. `credentials` (optional username/password/token) is stored encrypted.
security-cameras.list· read-onlyList security cameras for this tenant (id, name, location, active). Credentials and stream ids are NOT returned — view/edit via the operator settings UI.
security-events
security-events.list· read-onlyList recent security events (Ring doorbell ding / motion) for this tenant, newest first.
smart-locks
smart-locks.delete· requires confirmationDelete a smart-lock assignment by id. Tenant-scoped: only locks owned by the current tenant can be deleted. Cascade-deletes any access_codes rows for that lock.
smart-locks.doors· read-onlyList the tenant's configured doors (id, name, provider, enabled). Use a door's id with smart-locks.unlock.
smart-locks.list· read-onlyList smart-lock assignments for this tenant. Returns per-room lock metadata (type, label, active). Credentials are NOT returned by this tool — use the operator settings UI to edit them.
smart-locks.unlock· requires confirmationOpen one of the tenant's configured doors now (any provider — Nuki Web API, TTLock Cloud). Pass doorId (see smart-locks.doors) or omit it to open the default door. Audit-logged.
smart-locks.upsert· requires confirmationCreate or update a smart-lock assignment for a room. Pass `id` to update an existing lock, or omit it to insert (unique per tenant+room — upsert on conflict).
smartLocks
smartLocks.doors.createSmart locks: doors create. Mutation — changes data. See the input schema for argument details.
smartLocks.doors.delete· requires confirmationDelete a door mapping from the smart-lock registry.
smartLocks.doors.list· read-onlySmart locks: doors list. Read-only query. See the input schema for argument details.
smartLocks.doors.listProviderLocksSmart locks: doors list provider locks. Mutation — changes data. See the input schema for argument details.
smartLocks.doors.updateSmart locks: doors update. Mutation — changes data. See the input schema for argument details.
smartLocks.listActiveCodes· read-onlySmart locks: list active codes. Read-only query. See the input schema for argument details.
smartLocks.nukiGetConfig· read-onlySmart locks: nuki get config. Read-only query. See the input schema for argument details.
smartLocks.ttlockGetConfig· read-onlySmart locks: ttlock get config. Read-only query. See the input schema for argument details.
stayAccess
stayAccess.clearOverride· requires confirmationClear an assistant access-code override for a stay.
stayAccess.getResolved· read-onlyStay access: get resolved. Read-only query. See the input schema for argument details.
stayAccess.setOverrideSet an assistant access-code override for a stay.
stays
stays.booking-panel· read-onlyRead-only assembly of a booking's two inbox side-panels: reservation summary, guest, mapped property (address/rules/capacity), host+guest financial breakdown, messaging activity, and linked tasks. Returns null if the stay does not exist. Read-only.
stays.byId· read-onlyGet full detail for a single stay/reservation by id.
stays.cancel_and_refund· requires confirmationCancel a DIRECT (Stripe) booking and refund per the cancellation-window policy. forceRefund=true issues an operator courtesy refund regardless of the window. Only direct bookings with a payment can be refunded here. Owner-only, IRREVERSIBLE, requires confirmation.
stays.cardDetail· read-onlyStays: card detail. Read-only query. See the input schema for argument details.
stays.createWalkInCreate a walk-in booking directly (no OTA) — for a guest arriving without a prior reservation.
stays.create_booking· requires confirmationCreate a booking: inserts a guest and a stay. Dates are YYYY-MM-DD; checkout must be after check-in. If status='checked_in', the smart-lock check-in lifecycle fires. Requires confirmation.
stays.forWindow· read-onlyList stays overlapping a given date window, for calendar/occupancy-style views.
stays.get· read-onlyFetch a single stay with its guest details and a summary of the linked conversation (message count, last-message timestamp, conversation id). Read-only.
stays.list· read-onlyList stays/reservations, optionally filtered (date range, guest, status).
stays.list_active· read-onlyList stays whose check_out is today or later. Includes pending and confirmed. Read-only.
stays.list_for_guest· read-onlyList other stays of a single guest at this tenant, newest-first. excludeStayId is the current stay (so a returning-guest prompt can skip the active visit and focus on history). Read-only.
stays.perform_checkout· requires confirmationCheck out a stay: sets status → checked_out, emits the stay.checked_out webhook, schedules the post-stay review request, and revokes any smart-lock codes. Idempotent if already checked out. Requires confirmation.
stays.prior_stays· read-onlyList a guest's prior stays, newest-first. Optionally exclude a stayId (the current one). Read-only.
stays.reset-all-room-overrides· requires confirmationClear ALL room-swap overrides for this tenant, restoring every swapped booking to its originally booked room(s). Owner-only, IRREVERSIBLE, requires confirmation.
stays.reset-room-overrideClear a single booking's room-swap override, restoring its originally booked room(s).
stays.set-room-overrideManually swap a booking's room (guest wish, maintenance issue, …). fromRoom must be one of the booking's current effective rooms; toRoom must exist and be free for the stay's dates (considering other bookings' own overrides) unless allowConflict is set — then the room is DELIBERATELY double-occupied. fromRoom === toRoom clears that mapping.
stays.today· read-onlyList stays that are arriving, departing, or in-house today.
stays.update_dates· requires confirmationMove or extend a booking (new check-in/out dates, optionally a different unit). Only manual/direct bookings without an OTA reservation id are editable — OTA reservations are owned by the channel and rejected. Requires confirmation.
taskRules
taskRules.byId· read-onlyTask rules: by id. Read-only query. See the input schema for argument details.
taskRules.createCreate a new task automation rule.
taskRules.delete· requires confirmationDelete a task automation rule.
taskRules.dryRunTask rules: dry run. Mutation — changes data. See the input schema for argument details.
taskRules.executions· read-onlyTask rules: executions. Read-only query. See the input schema for argument details.
taskRules.list· read-onlyTask rules: list. Read-only query. See the input schema for argument details.
taskRules.toggleTask rules: toggle. Mutation — changes data. See the input schema for argument details.
taskRules.trigger· requires confirmationManually fire a task rule right now — creates its real task(s) immediately, out of band. Requires confirmation.
taskRules.updateTask rules: update. Mutation — changes data. See the input schema for argument details.
tasks
tasks.add_photoAttach a photo (image/jpeg, image/png, image/webp) to a task as completion evidence. Body is base64-encoded. Stored under the tenant's photo bucket; URL returned for embedding in chat.
tasks.assign· requires confirmationReassign a task to a different worker (or unassign by passing null). Mutating action — the MCP client must include _confirm: true.
tasks.byId· read-onlyTasks: by id. Read-only query. See the input schema for argument details.
tasks.calendarGrid· read-onlyTasks: calendar grid. Read-only query. See the input schema for argument details.
tasks.counts· read-onlyTasks: counts. Read-only query. See the input schema for argument details.
tasks.createCreate a manual task. Mirrors the operator UI's manual-create form. If assignedToUserId is set, status starts at 'assigned'; otherwise 'open'.
tasks.get· read-onlyGet a single task with its full event timeline and photo/document attachments. Returns null if the task isn't visible (RLS) or doesn't exist.
tasks.historySearch· read-onlyTasks: history search. Read-only query. See the input schema for argument details.
tasks.listFiltered· read-onlyList tasks filtered by status, date, assignee, or kind.
tasks.listForMe· read-onlyList tasks assigned to the current (owner) user.
tasks.list_assignable_users· read-onlyList tenant members in the housekeeping or maintenance pools — used as context when picking an assignee for a new task. Read-only.
tasks.list_open· read-onlyList tasks not yet completed (open + assigned + in_progress) across the tenant. Newest-first. Read-only.
tasks.list_unassigned· read-onlyList open tasks that have no assignee yet. The operator's triage view: what's hanging in the queue. Newest-first. Read-only.
tasks.mark_doneMark a task as done. Sets status='done', completed_at=now, emits the task.completed webhook.
tasks.reassign· requires confirmationReassign a task to a different worker. Pass userId=null to move it back to the unassigned pool. Equivalent to tasks.assign — exposed as a separate tool so prompts like 'reassign X to Y' resolve naturally. Mutating action — requires _confirm: true.
tasks.updateStatusChange a task's status (open / in progress / done / etc.).
team
team.byId· read-onlyTeam: by id. Read-only query. See the input schema for argument details.
team.createTeam: create. Mutation — changes data. See the input schema for argument details.
team.list· read-onlyTeam: list. Read-only query. See the input schema for argument details.
team.listForRecipients· read-onlyTeam: list for recipients. Read-only query. See the input schema for argument details.
team.listRooms· read-onlyTeam: list rooms. Read-only query. See the input schema for argument details.
team.me· read-onlyTeam: me. Read-only query. See the input schema for argument details.
team.preferredRooms.list· read-onlyTeam: preferred rooms list. Read-only query. See the input schema for argument details.
team.preferredRooms.setTeam: preferred rooms set. Mutation — changes data. See the input schema for argument details.
team.sendInviteResend a team member's invite email.
team.softDelete· requires confirmationDeactivate (soft-delete) a team member, revoking their access.
team.updateTeam: update. Mutation — changes data. See the input schema for argument details.
tenants
tenants.connectStatus· read-onlyTenants: connect status. Read-only query. See the input schema for argument details.
tenants.getArrivalGuideSettings· read-onlyTenants: get arrival guide settings. Read-only query. See the input schema for argument details.
tenants.getBrandVoice· read-onlyTenants: get brand voice. Read-only query. See the input schema for argument details.
tenants.getPortalLayoutVersion· read-onlyTenants: get portal layout version. Read-only query. See the input schema for argument details.
tenants.getReviewLinks· read-onlyTenants: get review links. Read-only query. See the input schema for argument details.
tenants.getReviewRequestSettings· read-onlyTenants: get review request settings. Read-only query. See the input schema for argument details.
tenants.get_brand_voice_stats· read-onlyReturns brand-voice training readiness stats for the tenant: number of manual outbound messages eligible as style anchors (length ≥ 30 chars, within 90-day lookback), last anchor timestamp, per-channel breakdown (whatsapp / email / hospitable), and the voiceTrainingEnabled flag. Read-only — no side effects.
tenants.get_channel_import_meta· read-onlyRead the current Hospitable (and future channel) import status for the tenant. Returns status ('idle' | 'running' | 'done' | 'error'), lastRunAt, importedCount, and errorMessage if the last run failed. Use this to check import progress before triggering a new import.
tenants.get_email_import_meta· read-onlyRead the current email (Postmark inbound) import status for the tenant. Returns status ('idle' | 'running' | 'done' | 'error'), lastRunAt, importedCount, and errorMessage if the last run failed. Use this to check email import progress before triggering a new import via triggerEmailImport.
tenants.get_faq_detection_mode· read-onlyRead the tenant's FAQ detection mode: 'lexical' (trigger-phrase matching, default), 'openai', or 'voyage' (semantic embeddings). Read-only.
tenants.healHospitableMessagesTenants: heal hospitable messages. Mutation — changes data. See the input schema for argument details.
tenants.importHospitableHistoryTenants: import hospitable history. Mutation — changes data. See the input schema for argument details.
tenants.previewHospitableImportTenants: preview hospitable import. Mutation — changes data. See the input schema for argument details.
tenants.setReviewRequestSettingsTenants: set review request settings. Mutation — changes data. See the input schema for argument details.
tenants.setVoiceTrainingEnabledTenants: set voice training enabled. Mutation — changes data. See the input schema for argument details.
tenants.set_faq_detection_modeSet the tenant's FAQ detection mode ('lexical' | 'openai' | 'voyage'). Semantic modes need the provider's API key in the server env and embeddings computed via ai_questions.regenerate_embeddings. Owner-only, mutating.
tenants.toggleHospitableRateSyncTenants: toggle hospitable rate sync. Mutation — changes data. See the input schema for argument details.
tenants.triggerEmailImportTenants: trigger email import. Mutation — changes data. See the input schema for argument details.
tenants.triggerHospitableImportTenants: trigger hospitable import. Mutation — changes data. See the input schema for argument details.
tenants.triggerHospitableReservationImportTenants: trigger hospitable reservation import. Mutation — changes data. See the input schema for argument details.
tenants.update-arrival-guide-settings· requires confirmationReplace the tenant's arrival-guide settings wholesale (address, entrance/keybox code names, wifi ssid/password, and per-step enabled/bodyTranslations/helpTranslations/photoKey/videoUrl for the 7 guide steps). videoUrl must be http(s). Owner-only, mutating — replaces the whole JSONB (read-modify-write happens caller-side).
tenants.updateBrandVoiceTenants: update brand voice. Mutation — changes data. See the input schema for argument details.
tenants.updatePortalLayoutVersionTenants: update portal layout version. Mutation — changes data. See the input schema for argument details.
tenants.updateReviewLinksTenants: update review links. Mutation — changes data. See the input schema for argument details.
tenants.update_rooms· requires confirmationUpdate the tenant's room count. Sockel is 30€/mo for ≤2 rooms; each additional room is 10€/mo. The matching Stripe extra-room line item is synced best-effort; the next webhook reconciliation catches any drift. Mutating action — requires _confirm: true.
till
till.addEntryTill: add entry. Mutation — changes data. See the input schema for argument details.
till.balance· read-onlyTill: balance. Read-only query. See the input schema for argument details.
till.categories· read-onlyTill: categories. Read-only query. See the input schema for argument details.
till.count· read-onlyTill: count. Read-only query. See the input schema for argument details.
till.deleteEntry· requires confirmationDelete a cash-book (Kassenbuch) entry.
till.forDate· read-onlyTill: for date. Read-only query. See the input schema for argument details.
till.report· read-onlyTill: report. Read-only query. See the input schema for argument details.
till.today· read-onlyTill: today. Read-only query. See the input schema for argument details.
upsell
upsell.delete_offer· requires confirmationHard-delete an upsell offer. ON DELETE CASCADE on upsell_bookings.offer_id removes any pending booking trails. Destructive — requires confirmation.
upsell.list_bookings· read-onlyList upsell booking trail for a stay (offered, offered_no_send, accepted, declined, charged, expired). When stayId is omitted, returns the latest 50 across the tenant.
upsell.list_offers· read-onlyList configured upsell offers for this tenant (active + inactive). Used by the operator to inspect what would be offered to guests 2h before check-in.
upsell.setBookingStatusUpsell: set booking status. Mutation — changes data. See the input schema for argument details.
upsell.upsert_offerCreate or update an upsell offer. Pass id to update an existing row; omit it to create a new one. Price is in cents (integer).
users
users.icalToken.emailUsers: ical token email. Mutation — changes data. See the input schema for argument details.
users.icalToken.status· read-onlyUsers: ical token status. Read-only query. See the input schema for argument details.
users.notificationPrefs.get· read-onlyUsers: notification prefs get. Read-only query. See the input schema for argument details.
users.notificationPrefs.setUsers: notification prefs set. Mutation — changes data. See the input schema for argument details.
users.uploadProfileImageUsers: upload profile image. Mutation — changes data. See the input schema for argument details.
voice
voice.config.get· read-onlyRead the VAPI voice bot configuration for the current tenant. Returns null if not yet configured. API key is excluded. Read-only.
voice.config.updateUpdate voice bot settings: enabled toggle, language, or greeting name. API key is excluded from this surface for security — use the Operator Settings UI instead.
voice-availability
voice-availability.check· read-onlyCheck live availability and nightly rate for a date range. Designed for the VAPI voice-agent tool-call surface — returns a spoken-friendly `spokenRate` string per option. Inventory is grouped by room type. Returns available:false if no inventory remains for the full stay window.
voice-calls
voice-calls.get· read-onlyFetch a single voice-AI-agent call by id, with its full action timeline (every MCP tool the agent invoked during the call, oldest-first). RLS blocks cross-tenant reads — unknown id returns an empty actions list and call:null.
voice-calls.list· read-onlyList voice-AI-agent calls for this tenant, newest-first. Default window: last 30 days. Optionally filter by outcome (hold_created/info_only/transferred/dropped/failed). Used by external agents + operator MCP clients to inspect recent voice activity.
voice-facts
voice-facts.lookup· read-onlyLook up hotel facts (WiFi, parking, breakfast, check-in hours, etc.) by keyword for the VAPI voice-agent. Searches across fact key, category, description, and translated values. Returns up to 5 matches with a spoken-friendly answer per match (de → en → first-locale fallback). Read-only, tenant-scoped, reuses the ε.1.5 hotel_facts table.
voice-hold
voice-hold.createPlace a 30-minute soft-hold on a room and send the caller an SMS with the confirmation link. Designed for the VAPI voice-agent — call after the guest verbally accepts a rate from voice-availability.check. Returns stayId + payLinkUrl + holdExpiresAt; the agent reads the expiry back to the guest.
voiceCalls
voiceCalls.byId· read-onlyVoice calls: by id. Read-only query. See the input schema for argument details.
webhooks
webhooks.list· read-onlyRead-only list of webhook subscriptions: URL, events, active flag, description, last-delivered-at, last-failed-at. Secrets are never returned via MCP — they exist only on the original web-UI create-flow.
webhooks.list_deliveries· read-onlyRecent delivery attempts for a single webhook subscription. Helpful for debugging '405 from receiver' or 'last failed at...' situations via Claude. Read-only.