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.configure

    Agents: configure. Mutation — changes data. See the input schema for argument details.

  • agents.list · read-only

    List all registered agents with their per-tenant config (enabled, schedule, guardrails) and last run status.

  • agents.proposals.list · read-only

    List agent proposals awaiting human review. Defaults to pending proposals only.

  • agents.proposals.review · requires confirmation

    Approve or reject an agent proposal. Approved proposals are logged; execution is handled by the application layer.

  • agents.runs.list · read-only

    Agents: runs list. Read-only query. See the input schema for argument details.

  • agents.trigger · requires confirmation

    Manually trigger an agent run. The agent will run asynchronously; check agents.runs.list for status.

ai

  • ai.acceptDraft · requires confirmation

    Accept 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_draft

    Discard an AI-generated draft reply. Deletes the draft message and logs the discard for trust-ramp acceptance-rate accounting.

  • ai.latestDraftForConversation · read-only

    Ai: latest draft for conversation. Read-only query. See the input schema for argument details.

  • ai.metrics · read-only

    AI 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.previewVoiceStyle

    Ai: preview voice style. Mutation — changes data. See the input schema for argument details.

  • ai.set_mode · requires confirmation

    Flip 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.create

    Ai questions: create. Mutation — changes data. See the input schema for argument details.

  • aiQuestions.delete · requires confirmation

    Delete a custom AI question/FAQ entry.

  • aiQuestions.get · read-only

    Ai questions: get. Read-only query. See the input schema for argument details.

  • aiQuestions.installDefaultPack

    Ai questions: install default pack. Mutation — changes data. See the input schema for argument details.

  • aiQuestions.list · read-only

    Ai questions: list. Read-only query. See the input schema for argument details.

  • aiQuestions.setEnabled

    Ai questions: set enabled. Mutation — changes data. See the input schema for argument details.

  • aiQuestions.testMatch · read-only

    Ai questions: test match. Read-only query. See the input schema for argument details.

  • aiQuestions.update

    Ai 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_positive

    Mark 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-only

    Read-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-only

    Answer 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-only

    Check 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-only

    Read-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.confirm

    Breakfast: confirm. Mutation — changes data. See the input schema for argument details.

  • breakfast.getSettings · read-only

    Breakfast: get settings. Read-only query. See the input schema for argument details.

  • breakfast.listForDate · read-only

    Breakfast: list for date. Read-only query. See the input schema for argument details.

  • breakfast.setSettings

    Breakfast: set settings. Mutation — changes data. See the input schema for argument details.

cannedResponses

  • cannedResponses.create

    Canned responses: create. Mutation — changes data. See the input schema for argument details.

  • cannedResponses.delete · requires confirmation

    Delete a canned response template.

  • cannedResponses.get · read-only

    Canned responses: get. Read-only query. See the input schema for argument details.

  • cannedResponses.list · read-only

    Canned responses: list. Read-only query. See the input schema for argument details.

  • cannedResponses.update

    Canned responses: update. Mutation — changes data. See the input schema for argument details.

channels

  • channels.activate_ota · requires confirmation

    Set 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 confirmation

    Add 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 confirmation

    Remove 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-only

    List 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-only

    List 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-only

    List 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 confirmation

    Remove 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 confirmation

    Manually 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 confirmation

    Pause 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 confirmation

    Add 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-only

    Return 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 confirmation

    Enable 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-only

    Checkin: active for stay. Read-only query. See the input schema for argument details.

  • checkin.clear_waiver

    Clear 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.create

    Start a new online check-in session for a stay.

  • checkin.extract_id_ocr

    Extract 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-only

    Get a single check-in session's detail.

  • checkin.getMeldescheinEntry · read-only

    Checkin: get meldeschein entry. Read-only query. See the input schema for argument details.

  • checkin.getPortalMeldeschein · read-only

    Checkin: get portal meldeschein. Read-only query. See the input schema for argument details.

  • checkin.get_meldeschein · read-only

    Get 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-only

    List check-in sessions, optionally filtered by stay/status.

  • checkin.list_guest_id_uploads · read-only

    List 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.markVerified

    Mark a guest's submitted check-in / ID as operator-verified.

  • checkin.revokeForStay · requires confirmation

    Revoke the online check-in session for a stay. Requires confirmation.

  • checkin.upcoming_without_session · read-only

    List 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.upsertMeldescheinEntry

    Create or update a guest's Meldeschein (German registration) entry.

cityTaxSettings

  • cityTaxSettings.get · read-only

    City tax settings: get. Read-only query. See the input schema for argument details.

  • cityTaxSettings.update

    City tax settings: update. Mutation — changes data. See the input schema for argument details.

city_tax

  • city_tax.get · read-only

    Read 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.update

    Upsert 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.add

    Concierge: add. Mutation — changes data. See the input schema for argument details.

  • concierge.delete · requires confirmation

    Delete a concierge recommendation item.

  • concierge.list · read-only

    Concierge: list. Read-only query. See the input schema for argument details.

contacts

  • contacts.delete

    Delete a contact by id. Phones cascade via FK. Returns { ok: true } or throws if not found.

  • contacts.get · read-only

    Fetch 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-only

    Get a single guest profile by id (name, email, phone, locale). DRY: delegates to getGuestById() (same as tRPC contacts.guests.byId).

  • contacts.guestBilling.delete · requires confirmation

    Delete a guest's billing/invoice address.

  • contacts.guestBilling.list · read-only

    Contacts: guest billing list. Read-only query. See the input schema for argument details.

  • contacts.guestBilling.upsert

    Contacts: guest billing upsert. Mutation — changes data. See the input schema for argument details.

  • contacts.guests.byId · read-only

    Contacts: guests by id. Read-only query. See the input schema for argument details.

  • contacts.guests.setEmail

    Contacts: guests set email. Mutation — changes data. See the input schema for argument details.

  • contacts.invoice-guests · read-only

    List 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-only

    List 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-only

    Search 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.upsert

    Create 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-only

    Dashboard: ai analytics. Read-only query. See the input schema for argument details.

  • dashboard.summary · read-only

    Get the operator dashboard's summary KPIs (occupancy, revenue, etc.).

  • dashboard.today · read-only

    Operator 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-only

    Get 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.update

    Enable 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-only

    Assemble 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.addLine

    Add a charge line (room/extra/tax) to a stay's folio.

  • folio.addPayment

    Record a payment against a stay's folio.

  • folio.close

    Close 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 confirmation

    Close a stay's folio. Irreversible once balanced — no further edits. Requires confirmation.

  • folio.line.update

    Overwrite 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-only

    List 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-only

    Folio: list payments. Read-only query. See the input schema for argument details.

  • folio.payment.add

    Record 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-only

    List 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.remove

    Delete 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 confirmation

    Remove a charge line from a folio.

  • folio.removePayment · requires confirmation

    Remove a recorded payment from a folio.

  • folio.reset

    Reset 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-only

    Return 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.updateLine

    Edit an existing folio charge line's description or amount.

fritzbox-calls

  • fritzbox-calls.contacts.list · read-only

    List 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.upsert

    Create 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-only

    List 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.refresh

    Trigger 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-callback

    Set 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-note

    Set 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-only

    Aggregated 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-only

    Check 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-only

    Fritzbox calls: list contacts. Read-only query. See the input schema for argument details.

  • fritzboxCalls.upsertContact

    Fritzbox calls: upsert contact. Mutation — changes data. See the input schema for argument details.

guest-billing

  • guest-billing.delete

    Delete 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-only

    List 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.upsert

    Create 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-email

    Set 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 confirmation

    Delete a guideline by id (owner only).

  • guidelines.get · read-only

    Get one guideline (incl. markdown body) by id for the current tenant. Read-only.

  • guidelines.list · read-only

    List internal staff-handbook guidelines for the current tenant (id, title, type, category, tags, updatedAt). Read-only.

  • guidelines.upsert

    Create or update a guideline (owner only). Provide id to update. Generates an embedding on save.

handover

  • handover.briefing · read-only

    Handover: briefing. Read-only query. See the input schema for argument details.

  • handover.getToday · read-only

    Get today's shift-handover note.

  • handover.getYesterday · read-only

    Handover: get yesterday. Read-only query. See the input schema for argument details.

  • handover.listRecent · read-only

    Handover: list recent. Read-only query. See the input schema for argument details.

  • handover.save

    Save the shift-handover note for the day.

hospitable

  • hospitable.heal_messages · requires confirmation

    Recover 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 confirmation

    Backfill 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 confirmation

    Re-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-only

    Hotel facts: get info sections. Read-only query. See the input schema for argument details.

  • hotelFacts.getTimeSettings · read-only

    Hotel facts: get time settings. Read-only query. See the input schema for argument details.

  • hotelFacts.updateInfoSection

    Hotel facts: update info section. Mutation — changes data. See the input schema for argument details.

  • hotelFacts.updateTimeSettings

    Hotel facts: update time settings. Mutation — changes data. See the input schema for argument details.

  • hotelFacts.upsert

    Hotel facts: upsert. Mutation — changes data. See the input schema for argument details.

hotel_facts

  • hotel_facts.delete · requires confirmation

    Permanently delete a hotel fact by its key. All locale translations are removed. Destructive — requires _confirm: true. Owner-only.

  • hotel_facts.list · read-only

    List 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.update

    Upsert 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-only

    Read 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.update

    Update a single hotel info section. Merges the supplied key into the existing hotelInfoSections JSONB, preserving all other sections. Owner-only.

housekeeping

  • housekeeping.assignTask

    Assign a housekeeping task to a staff member.

  • housekeeping.completeTask

    Mark a housekeeping task complete.

  • housekeeping.createManualTask

    Create an ad-hoc housekeeping task outside the normal schedule.

  • housekeeping.createRoom

    Housekeeping: create room. Mutation — changes data. See the input schema for argument details.

  • housekeeping.deleteTask · requires confirmation

    Delete a housekeeping task.

  • housekeeping.importRoomsFromStays

    Housekeeping: import rooms from stays. Mutation — changes data. See the input schema for argument details.

  • housekeeping.listRooms · read-only

    Housekeeping: list rooms. Read-only query. See the input schema for argument details.

  • housekeeping.setRoomMaintenance

    Flag or clear maintenance state on a room.

  • housekeeping.skipTask

    Housekeeping: skip task. Mutation — changes data. See the input schema for argument details.

  • housekeeping.startTask

    Mark a housekeeping task as started (in progress).

  • housekeeping.tasks-window · read-only

    Cleaning 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-only

    Housekeeping: tasks for date. Read-only query. See the input schema for argument details.

  • housekeeping.tasksForWindow · read-only

    Housekeeping: tasks for window. Read-only query. See the input schema for argument details.

  • housekeeping.todayOverview · read-only

    Housekeeping: today overview. Read-only query. See the input schema for argument details.

  • housekeeping.todayTasks · read-only

    Housekeeping: today tasks. Read-only query. See the input schema for argument details.

identity

  • identity.resolve · read-only

    Resolve 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_draft

    Approve 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_reply

    Run 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-only

    List all sent messages (inbound + outbound) for a stay's conversation, oldest-first. Excludes drafts. Read-only.

  • inbox.list_triage · read-only

    Paginated 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-only

    List 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_reply

    Send 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_request

    Mint 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-only

    Fetch 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-only

    List 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-only

    List 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 confirmation

    Remove 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-only

    Collected 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-only

    Invoice-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 confirmation

    Email 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_status

    Set 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-only

    Counters for the operator dashboard stat-strip: total + per-status (draft, created, sent, cancelled, reissued) for the caller's tenant. Read-only.

  • invoices.submitForm

    Invoices: submit form. Mutation — changes data. See the input schema for argument details.

  • invoices.update_address · requires confirmation

    Update 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 confirmation

    Set 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 confirmation

    Edit 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 confirmation

    Set 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 confirmation

    Add 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-only

    Aggregate 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-only

    Valid 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-only

    Cash-book entries for a single date (YYYY-MM-DD). Read-only. Useful for 'was war am 15.04.?' lookups.

  • kassenbuch.list_today · read-only

    Today'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-only

    Cash-book report for a date range (from/to inclusive, YYYY-MM-DD). Returns per-category breakdowns + period totals. Read-only.

lost-found

  • lost-found.create

    Record a new lost-and-found item for this tenant. Defaults to status=held.

  • lost-found.list · read-only

    List lost-and-found items for this tenant, newest-first. Filter by status (held/returned/shipped/discarded).

lostFound

  • lostFound.discard · requires confirmation

    Discard a lost & found item (marks it disposed of, not returned to a guest).

  • lostFound.markReturned

    Lost found: mark returned. Mutation — changes data. See the input schema for argument details.

  • lostFound.updatePhoto

    Lost found: update photo. Mutation — changes data. See the input schema for argument details.

me

  • me.get · read-only

    Returns 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 confirmation

    Invite 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-only

    List 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 confirmation

    Update 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-only

    List all messages for a single stay's conversation thread.

  • messages.listConversations · read-only

    List guest message conversations (inbox threads).

  • messages.listUnconfirmed · read-only

    Messages: list unconfirmed. Read-only query. See the input schema for argument details.

  • messages.markDelivered

    Messages: mark delivered. Mutation — changes data. See the input schema for argument details.

  • messages.resyncReservation

    Re-pull a reservation's message history from Hospitable to heal a sync gap. Idempotent, read-mostly.

  • messages.send · requires confirmation

    Send 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-only

    CC-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-only

    Preview 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-now

    Send 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.createRule

    Create a new automated messaging rule.

  • messagingRules.deleteCode · requires confirmation

    Delete a custom message short-code.

  • messagingRules.deleteRule · requires confirmation

    Delete an automated messaging rule.

  • messagingRules.getRule · read-only

    Messaging rules: get rule. Read-only query. See the input schema for argument details.

  • messagingRules.listCodes · read-only

    Messaging rules: list codes. Read-only query. See the input schema for argument details.

  • messagingRules.retryQueueItem

    Retry a failed queued outbound message.

  • messagingRules.updateRule

    Edit an existing automated messaging rule.

  • messagingRules.upsertCode

    Messaging rules: upsert code. Mutation — changes data. See the input schema for argument details.

messaging_rules

  • messaging_rules.cancel_queue_item · requires confirmation

    Cancel 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 confirmation

    Edit 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-only

    List 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-only

    List 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 confirmation

    Re-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-only

    List 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_defaults

    Idempotent 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-only

    Notification rules: by id. Read-only query. See the input schema for argument details.

  • notificationRules.create

    Create a new notification rule.

  • notificationRules.delete · requires confirmation

    Delete a notification rule.

  • notificationRules.dryRun

    Notification rules: dry run. Mutation — changes data. See the input schema for argument details.

  • notificationRules.executions · read-only

    Notification rules: executions. Read-only query. See the input schema for argument details.

  • notificationRules.list · read-only

    Notification rules: list. Read-only query. See the input schema for argument details.

  • notificationRules.toggle

    Notification rules: toggle. Mutation — changes data. See the input schema for argument details.

  • notificationRules.trigger · requires confirmation

    Manually fire a notification rule right now — sends the rule's real notification(s) immediately, out of band. Requires confirmation.

  • notificationRules.update

    Notification rules: update. Mutation — changes data. See the input schema for argument details.

onboarding

  • onboarding.dismiss

    Onboarding: dismiss. Mutation — changes data. See the input schema for argument details.

  • onboarding.state · read-only

    Onboarding: state. Read-only query. See the input schema for argument details.

orders

  • orders.list · read-only

    List 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-only

    Orders: list catalog. Read-only query. See the input schema for argument details.

  • orders.listCatalogByToken · read-only

    Orders: list catalog by token. Read-only query. See the input schema for argument details.

  • orders.listOrders · read-only

    Orders: list orders. Read-only query. See the input schema for argument details.

  • orders.placeOrderByToken

    Orders: place order by token. Mutation — changes data. See the input schema for argument details.

  • orders.place_order

    Place 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.updateOrderStatus

    Advance a guest order's status (received / preparing / delivered).

  • orders.update_status · requires confirmation

    Transition 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.upsertCatalogItem

    Orders: upsert catalog item. Mutation — changes data. See the input schema for argument details.

plan

  • plan.entitlements · read-only

    Plan: entitlements. Read-only query. See the input schema for argument details.

properties

  • properties.byUuid · read-only

    Properties: by uuid. Read-only query. See the input schema for argument details.

  • properties.get · read-only

    Fetch 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-only

    List 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 confirmation

    Act 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-only

    Read 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-only

    Get 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-only

    Get 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-only

    List 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 confirmation

    Update 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 confirmation

    Enable 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.generate

    Rate suggestions: generate. Mutation — changes data. See the input schema for argument details.

rates

  • rates.blockRoomDates

    Rates: block room dates. Mutation — changes data. See the input schema for argument details.

  • rates.block_dates · requires confirmation

    Block 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_set

    Set 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.createPlan

    Create a new rate plan.

  • rates.delete

    Delete a specific room rate by its UUID. Returns the deleted rate's id.

  • rates.deletePlan · requires confirmation

    Delete an existing rate plan.

  • rates.deleteRestriction · requires confirmation

    Delete a stay-length/date rate restriction.

  • rates.list · read-only

    List 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-only

    Rates: list blocked dates. Read-only query. See the input schema for argument details.

  • rates.listBulkEdits · read-only

    Rates: list bulk edits. Read-only query. See the input schema for argument details.

  • rates.listChannelSync · read-only

    Rates: list channel sync. Read-only query. See the input schema for argument details.

  • rates.listPlans · read-only

    List the property's rate plans.

  • rates.list_restrictions · read-only

    List 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.manualResync

    Rates: manual resync. Mutation — changes data. See the input schema for argument details.

  • rates.pushPrice

    Rates: push price. Mutation — changes data. See the input schema for argument details.

  • rates.syncUnitCalendar

    Rates: sync unit calendar. Mutation — changes data. See the input schema for argument details.

  • rates.unblockDates

    Rates: unblock dates. Mutation — changes data. See the input schema for argument details.

  • rates.undoBulkEdit

    Rates: undo bulk edit. Mutation — changes data. See the input schema for argument details.

  • rates.unit-calendar · read-only

    Per-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.updatePlan

    Edit an existing rate plan.

  • rates.upsert

    Set 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.upsertRestriction

    Rates: upsert restriction. Mutation — changes data. See the input schema for argument details.

registration-settings

  • registration-settings.get · read-only

    Read 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.update

    Update 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-only

    Revenue + 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-only

    Reports: summary. Read-only query. See the input schema for argument details.

review-requests

  • review-requests.list · read-only

    List review requests sent for this tenant. Returns stayId, channel, status, sentAt.

ring

  • ring.connection.delete · requires confirmation

    Delete a Ring connection by id. Tenant-scoped. Cascade-deletes its doorbells.

  • ring.connection.upsert · requires confirmation

    Create 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 confirmation

    Delete a Ring doorbell by id. Tenant-scoped.

  • ring.doorbell.upsert · requires confirmation

    Create or update a Ring doorbell behind a connection. `deviceId` is the Ring camera id. Pass `id` to update, omit to insert.

  • ring.list · read-only

    List 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-only

    List recent camera access-audit entries (who viewed which camera when) for this tenant, newest first. Owner-only.

security-cameras

  • security-cameras.camera.delete · requires confirmation

    Delete a camera by id. Tenant-scoped.

  • security-cameras.camera.upsert · requires confirmation

    Create 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 confirmation

    Delete a go2rtc connection by id. Tenant-scoped. Cascade-deletes the cameras behind it.

  • security-cameras.connection.upsert · requires confirmation

    Create 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-only

    List 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-only

    List recent security events (Ring doorbell ding / motion) for this tenant, newest first.

smart-locks

  • smart-locks.delete · requires confirmation

    Delete 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-only

    List the tenant's configured doors (id, name, provider, enabled). Use a door's id with smart-locks.unlock.

  • smart-locks.list · read-only

    List 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 confirmation

    Open 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 confirmation

    Create 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.create

    Smart locks: doors create. Mutation — changes data. See the input schema for argument details.

  • smartLocks.doors.delete · requires confirmation

    Delete a door mapping from the smart-lock registry.

  • smartLocks.doors.list · read-only

    Smart locks: doors list. Read-only query. See the input schema for argument details.

  • smartLocks.doors.listProviderLocks

    Smart locks: doors list provider locks. Mutation — changes data. See the input schema for argument details.

  • smartLocks.doors.update

    Smart locks: doors update. Mutation — changes data. See the input schema for argument details.

  • smartLocks.listActiveCodes · read-only

    Smart locks: list active codes. Read-only query. See the input schema for argument details.

  • smartLocks.nukiGetConfig · read-only

    Smart locks: nuki get config. Read-only query. See the input schema for argument details.

  • smartLocks.ttlockGetConfig · read-only

    Smart locks: ttlock get config. Read-only query. See the input schema for argument details.

stayAccess

  • stayAccess.clearOverride · requires confirmation

    Clear an assistant access-code override for a stay.

  • stayAccess.getResolved · read-only

    Stay access: get resolved. Read-only query. See the input schema for argument details.

  • stayAccess.setOverride

    Set an assistant access-code override for a stay.

stays

  • stays.booking-panel · read-only

    Read-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-only

    Get full detail for a single stay/reservation by id.

  • stays.cancel_and_refund · requires confirmation

    Cancel 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-only

    Stays: card detail. Read-only query. See the input schema for argument details.

  • stays.createWalkIn

    Create a walk-in booking directly (no OTA) — for a guest arriving without a prior reservation.

  • stays.create_booking · requires confirmation

    Create 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-only

    List stays overlapping a given date window, for calendar/occupancy-style views.

  • stays.get · read-only

    Fetch 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-only

    List stays/reservations, optionally filtered (date range, guest, status).

  • stays.list_active · read-only

    List stays whose check_out is today or later. Includes pending and confirmed. Read-only.

  • stays.list_for_guest · read-only

    List 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 confirmation

    Check 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-only

    List a guest's prior stays, newest-first. Optionally exclude a stayId (the current one). Read-only.

  • stays.reset-all-room-overrides · requires confirmation

    Clear 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-override

    Clear a single booking's room-swap override, restoring its originally booked room(s).

  • stays.set-room-override

    Manually 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-only

    List stays that are arriving, departing, or in-house today.

  • stays.update_dates · requires confirmation

    Move 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-only

    Task rules: by id. Read-only query. See the input schema for argument details.

  • taskRules.create

    Create a new task automation rule.

  • taskRules.delete · requires confirmation

    Delete a task automation rule.

  • taskRules.dryRun

    Task rules: dry run. Mutation — changes data. See the input schema for argument details.

  • taskRules.executions · read-only

    Task rules: executions. Read-only query. See the input schema for argument details.

  • taskRules.list · read-only

    Task rules: list. Read-only query. See the input schema for argument details.

  • taskRules.toggle

    Task rules: toggle. Mutation — changes data. See the input schema for argument details.

  • taskRules.trigger · requires confirmation

    Manually fire a task rule right now — creates its real task(s) immediately, out of band. Requires confirmation.

  • taskRules.update

    Task rules: update. Mutation — changes data. See the input schema for argument details.

tasks

  • tasks.add_photo

    Attach 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 confirmation

    Reassign a task to a different worker (or unassign by passing null). Mutating action — the MCP client must include _confirm: true.

  • tasks.byId · read-only

    Tasks: by id. Read-only query. See the input schema for argument details.

  • tasks.calendarGrid · read-only

    Tasks: calendar grid. Read-only query. See the input schema for argument details.

  • tasks.counts · read-only

    Tasks: counts. Read-only query. See the input schema for argument details.

  • tasks.create

    Create a manual task. Mirrors the operator UI's manual-create form. If assignedToUserId is set, status starts at 'assigned'; otherwise 'open'.

  • tasks.get · read-only

    Get 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-only

    Tasks: history search. Read-only query. See the input schema for argument details.

  • tasks.listFiltered · read-only

    List tasks filtered by status, date, assignee, or kind.

  • tasks.listForMe · read-only

    List tasks assigned to the current (owner) user.

  • tasks.list_assignable_users · read-only

    List 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-only

    List tasks not yet completed (open + assigned + in_progress) across the tenant. Newest-first. Read-only.

  • tasks.list_unassigned · read-only

    List open tasks that have no assignee yet. The operator's triage view: what's hanging in the queue. Newest-first. Read-only.

  • tasks.mark_done

    Mark a task as done. Sets status='done', completed_at=now, emits the task.completed webhook.

  • tasks.reassign · requires confirmation

    Reassign 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.updateStatus

    Change a task's status (open / in progress / done / etc.).

team

  • team.byId · read-only

    Team: by id. Read-only query. See the input schema for argument details.

  • team.create

    Team: create. Mutation — changes data. See the input schema for argument details.

  • team.list · read-only

    Team: list. Read-only query. See the input schema for argument details.

  • team.listForRecipients · read-only

    Team: list for recipients. Read-only query. See the input schema for argument details.

  • team.listRooms · read-only

    Team: list rooms. Read-only query. See the input schema for argument details.

  • team.me · read-only

    Team: me. Read-only query. See the input schema for argument details.

  • team.preferredRooms.list · read-only

    Team: preferred rooms list. Read-only query. See the input schema for argument details.

  • team.preferredRooms.set

    Team: preferred rooms set. Mutation — changes data. See the input schema for argument details.

  • team.sendInvite

    Resend a team member's invite email.

  • team.softDelete · requires confirmation

    Deactivate (soft-delete) a team member, revoking their access.

  • team.update

    Team: update. Mutation — changes data. See the input schema for argument details.

tenants

  • tenants.connectStatus · read-only

    Tenants: connect status. Read-only query. See the input schema for argument details.

  • tenants.getArrivalGuideSettings · read-only

    Tenants: get arrival guide settings. Read-only query. See the input schema for argument details.

  • tenants.getBrandVoice · read-only

    Tenants: get brand voice. Read-only query. See the input schema for argument details.

  • tenants.getPortalLayoutVersion · read-only

    Tenants: get portal layout version. Read-only query. See the input schema for argument details.

  • tenants.getReviewLinks · read-only

    Tenants: get review links. Read-only query. See the input schema for argument details.

  • tenants.getReviewRequestSettings · read-only

    Tenants: get review request settings. Read-only query. See the input schema for argument details.

  • tenants.get_brand_voice_stats · read-only

    Returns 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-only

    Read 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-only

    Read 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-only

    Read the tenant's FAQ detection mode: 'lexical' (trigger-phrase matching, default), 'openai', or 'voyage' (semantic embeddings). Read-only.

  • tenants.healHospitableMessages

    Tenants: heal hospitable messages. Mutation — changes data. See the input schema for argument details.

  • tenants.importHospitableHistory

    Tenants: import hospitable history. Mutation — changes data. See the input schema for argument details.

  • tenants.previewHospitableImport

    Tenants: preview hospitable import. Mutation — changes data. See the input schema for argument details.

  • tenants.setReviewRequestSettings

    Tenants: set review request settings. Mutation — changes data. See the input schema for argument details.

  • tenants.setVoiceTrainingEnabled

    Tenants: set voice training enabled. Mutation — changes data. See the input schema for argument details.

  • tenants.set_faq_detection_mode

    Set 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.toggleHospitableRateSync

    Tenants: toggle hospitable rate sync. Mutation — changes data. See the input schema for argument details.

  • tenants.triggerEmailImport

    Tenants: trigger email import. Mutation — changes data. See the input schema for argument details.

  • tenants.triggerHospitableImport

    Tenants: trigger hospitable import. Mutation — changes data. See the input schema for argument details.

  • tenants.triggerHospitableReservationImport

    Tenants: trigger hospitable reservation import. Mutation — changes data. See the input schema for argument details.

  • tenants.update-arrival-guide-settings · requires confirmation

    Replace 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.updateBrandVoice

    Tenants: update brand voice. Mutation — changes data. See the input schema for argument details.

  • tenants.updatePortalLayoutVersion

    Tenants: update portal layout version. Mutation — changes data. See the input schema for argument details.

  • tenants.updateReviewLinks

    Tenants: update review links. Mutation — changes data. See the input schema for argument details.

  • tenants.update_rooms · requires confirmation

    Update 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.addEntry

    Till: add entry. Mutation — changes data. See the input schema for argument details.

  • till.balance · read-only

    Till: balance. Read-only query. See the input schema for argument details.

  • till.categories · read-only

    Till: categories. Read-only query. See the input schema for argument details.

  • till.count · read-only

    Till: count. Read-only query. See the input schema for argument details.

  • till.deleteEntry · requires confirmation

    Delete a cash-book (Kassenbuch) entry.

  • till.forDate · read-only

    Till: for date. Read-only query. See the input schema for argument details.

  • till.report · read-only

    Till: report. Read-only query. See the input schema for argument details.

  • till.today · read-only

    Till: today. Read-only query. See the input schema for argument details.

upsell

  • upsell.delete_offer · requires confirmation

    Hard-delete an upsell offer. ON DELETE CASCADE on upsell_bookings.offer_id removes any pending booking trails. Destructive — requires confirmation.

  • upsell.list_bookings · read-only

    List 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-only

    List 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.setBookingStatus

    Upsell: set booking status. Mutation — changes data. See the input schema for argument details.

  • upsell.upsert_offer

    Create 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.email

    Users: ical token email. Mutation — changes data. See the input schema for argument details.

  • users.icalToken.status · read-only

    Users: ical token status. Read-only query. See the input schema for argument details.

  • users.notificationPrefs.get · read-only

    Users: notification prefs get. Read-only query. See the input schema for argument details.

  • users.notificationPrefs.set

    Users: notification prefs set. Mutation — changes data. See the input schema for argument details.

  • users.uploadProfileImage

    Users: upload profile image. Mutation — changes data. See the input schema for argument details.

voice

  • voice.config.get · read-only

    Read the VAPI voice bot configuration for the current tenant. Returns null if not yet configured. API key is excluded. Read-only.

  • voice.config.update

    Update 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-only

    Check 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-only

    Fetch 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-only

    List 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-only

    Look 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.create

    Place 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-only

    Voice calls: by id. Read-only query. See the input schema for argument details.

webhooks

  • webhooks.list · read-only

    Read-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-only

    Recent delivery attempts for a single webhook subscription. Helpful for debugging '405 from receiver' or 'last failed at...' situations via Claude. Read-only.