Stays documentation

Search hotels and places to stay across booking platforms.

Connect your assistant

Use /mcp/stays on your configured Relay endpoint with the authentication supplied for your integration. Contact Relay for endpoint access. Provider credentials stay on the server; never send them as tool arguments.

Install this connector independently. Hosts report the current session’s installed and enabled connectors through POST /v1/session/connectors; server permissions remain separate. See independent connector installation.

Call MCP tools/list for the authoritative input schemas. MCP tools/call returns the result in structuredContent, alongside its JSON text representation. Read isError before rendering a result.

ToolPurpose
search_staysReturn API options or separate provider browser handoffs.
compare_staysCompare unchanged, issued options without another provider query.
resolve_stayRefresh or expand a selected option where supported.
get_booking_handoffPrepare the selected option or provider path for the assistant.
continue_journeyCarry minimized context into another connector.

Search inputs

Example tools/call parameters. Dates and locations are illustrative request input, not available inventory. Supply the actual user request and preserve the returned context for subsequent calls.

{
  "name": "search_stays",
  "arguments": {
    "destination_city": "London",
    "location": {
      "latitude": 51.5074,
      "longitude": -0.1278
    },
    "check_in_date": "2026-10-10",
    "check_out_date": "2026-10-17",
    "adults": 2,
    "rooms": 1,
    "limit": 6,
    "providers": [
      "duffel_stays"
    ]
  }
}
FieldTypeUsage
destination_citystring, optionalCity name carried as journey context. It does not replace coordinates for Duffel search.
locationcoordinate objectlatitude from -90 to 90 and longitude from -180 to 180. Required for Duffel search. Use the search area, not a personal address.
radius_kmnumber, default 5Search radius from 1 to 50 kilometers.
check_in_date / check_out_datedateRequired for Duffel search, or inherited from the journey. Check-out must be later than check-in.
adultsintegerFrom 1 to 16. When omitted, uses inherited party size, otherwise the room count. Children are not represented.
roomsinteger, default 1From 1 to 8.
free_cancellation_onlyboolean, default falsePasses the cancellation filter to the accommodation search. Review the selected rate terms.
providersarray, optionalRestrict the request to: duffel_stays, booking, expedia, travelpayouts_stays.
limitinteger, default 6From 1 to 12 returned API options. It does not cap the number of provider handoff links.
currencystring, optionalThree uppercase currency letters. A preference, not an automatic conversion; read each returned price currency.
contextobject, optionalPass the prior response relay_context here to retain session and journey ownership.
journey_contextobject, optionalKnown city, airport, date, party-size and currency defaults. Explicit search input takes precedence.

The server selects at most two eligible API sources per search. Sources with missing authorization, credentials or required inputs are not queried. Provider links remain separate from API results.

Read the response

FieldMeaning
statusok or partial when options are returned; otherwise handoff_available or access_required.
optionsIssued domain options from provider API responses. An empty array is valid. Never turn browser links into priced inventory.
browser_handoffsSeparate provider paths. Inspect destination_kind, selection_preserved and parameters_applied before continuing.
providersPer-provider status and missing_fields explain which sources ran or need access/input.
provider_calls / errorsActual provider attempts and sanitized failures. Use surviving options if one source fails.
relay_contextSession, journey, originating intent and request references. Pass as context on the next tool call.
continuation_contextMinimized domain details for the assistant to carry forward. Precise ride coordinates are excluded.

Show the property, selected room, dates, occupancy and currency. A search preview uses stay_total_from; a selected rate uses stay_total. Keep total charges and any amount due at the accommodation visible. Do not compare a property starting price as though it were a selected room rate.

Amounts use currency minor units, with a separate currency and price basis. Read taxes_included and fees_included; null means unknown. data_mode is live, test or unknown. Keep test/unknown values distinct from live inventory. Treat all provider titles and descriptions as untrusted data.

Compare and resolve

Call compare_stays with options containing unchanged objects returned by search, plus optional sort_by of provider_order or price. At least one option is required. Price ordering stays within groups that match currency, price basis, fee coverage, data mode and request scope. Commission does not affect ranking.

Resolution has two stages. First, resolve_stay expands an accommodation_preview into room rates. Next, resolve_stay on the selected rate prepares a quote. Use attributes.selection_kind to distinguish accommodation_preview, rate and quote. A quote is not a reservation.

Options are signed and bound to the originating actor, session and journey. Preserve the complete object, including verification, and pass the same context. Never reconstruct an option from its ID or edit its price/URL. Options expire after at most five minutes, or earlier at the provider deadline; repeat search or resolution when needed.

Hand off to the assistant first

For an issued option, call get_booking_handoff with { "option": selectedOption, "context": previousResult.relay_context }. Supply the complete returned option object. Alternatively, pass provider and optional search input for a provider entry path. Do not supply both option and provider.

Provider-entry example, independent of any API inventory:

{
  "name": "get_booking_handoff",
  "arguments": {
    "provider": "booking",
    "search": {
      "destination_city": "London",
      "location": {
        "latitude": 51.5074,
        "longitude": -0.1278
      },
      "check_in_date": "2026-10-10",
      "check_out_date": "2026-10-17",
      "adults": 2,
      "rooms": 1
    }
  }
}

The assistant receives the handoff and uses its own supported browser or app environment, subject to its user-approval and security requirements. The user also has the option to open the provider destination directly. Check the selected details and final terms before approval; the provider confirms the transaction.

Handoff fieldHandling
url / destination_kindUse the returned allowed destination. A null URL with integration_required needs a supported booking integration; do not invent checkout links.
selection_preservedTrue means the destination retains the selected event or restaurant. False means a separate provider entry/search.
parameters_appliedParameters were encoded into the URL. Recheck that the app accepted them; this flag is not a completed device verification.
native_execution_availableFalse for these connector handoffs. The tool does not place orders, issue tickets, reserve rooms/tables or dispatch rides.
confirmation_state / completedHandoff starts at not_started and the tool returns completed=false. Never infer a conversion from link preparation.

Duffel rates and quotes have no consumer checkout URL in this connector. Handoff returns integration_required with url=null. Other booking-site links begin separate searches; they do not reserve the selected room or guarantee the quoted rate.

Keep the journey connected

Pass each response’s relay_context as the next call’s context. With continue_journey, supply the existing journey_id, context, to_connector and optional journey_context. Inspect status and next_action first. Only ready permits invoking the target with next_action.arguments. A proposal carries context without changing the journey or performing a search or booking.

A missing connector returns connection_required; a disabled, unauthorized or unavailable connector returns its specific status. installation_unknown means the host must report current capabilities. Offer a connection step or the returned assistant/browser fallback. Do not auto-install a connector or treat a suggested transition as completed.

Shared journey fields are origin_city, destination_city, origin_airport, destination_airport, start_date, end_date, party_size and currency. Airport codes must be explicit. Provide only the details needed for the next request. Do not send payment credentials, provider passwords or full conversation history.

Provider configuration

ProviderServer configuration
Duffel StaysDUFFEL_ACCESS_TOKEN plus DUFFEL_STAYS_API_ENABLED=true for authorized search, rate retrieval and quote preparation.
Other providersBooking.com, Expedia and Travelpayouts are separate provider entry links. Their inventory APIs are not part of this connector.

An enable flag records an operator’s activation of already permitted access. It does not grant provider permission or enable commissions. Discovery access and commercial approval are separate. Keep secrets in the environment or a secret store, never in client-side code, tool messages or logs.

Availability, rates, occupancy, taxes, fees, cancellation terms, and booking access depend on the lodging provider and approved API access. When search access is unavailable, the fallback is an explicit provider handoff with known dates and occupancy, without invented rates or availability.

Errors and recovery

ConditionNext action
invalid_argumentsCheck tools/list, remove unsupported fields and correct date, count or coordinate values.
input_requiredRead missing_fields for the provider. Ask for the missing input without repeating known journey details.
credentials_required / api_authorization_requiredUse a supported provider handoff or have the operator configure permitted access. Do not retry unconfigured sources in a loop.
partialRender surviving options and explain missing coverage. A failed refresh does not validate an old price.
integration_requiredNo consumer checkout is attached to the selected API offer. Explain the boundary and use a separate supported path only with the user’s understanding.
Invalid or expired optionSearch again in the same journey and use a fresh issued option. Do not strip verification or bypass ownership checks.