Skip to main content
Glama

Bluerails Hotels

hotel_reserve

Destructive

Book a hotel room. Works for ANY offer list_hotels gave you an offerId for — there is no separate check to make first, so pass the offer the guest chose. Pass that offer’s offerId exactly as you were given it — it names the hotel, room, rate, stay and price, which is why none of those are separate arguments. It expires after 30 minutes; if it has expired or the hotel has raised the price since, nothing is booked — get a fresh one by calling list_hotels with that same offerId, which re-prices just that room rather than showing the guest the whole property again. TWO OUTCOMES, and the reply tells you which. confirmationNumber means the room is booked: give the guest the number and tell them they pay the hotel at the desk — nothing has been charged. paymentUrl means the room is NOT held yet: give the guest that link to pay, their card is HELD rather than charged, and the booking is placed once they have paid. Set acceptedTerms only after the guest has agreed to book this rate. Show them that rate’s cancellation terms where list_hotels gave any; where its cancelTerms was null we hold none, so say so and that the hotel’s own terms apply, then set it once they agree on that basis — a blank is NOT a reason to refuse the booking. Ask the guest for their own phone number and billing address — the hotel puts them on the reservation and uses them to reach the guest. Never invent them. If a call comes back ambiguous, do NOT call again — a reservation may already exist.

Input Schema

NameRequiredDescriptionDefault
offerIdYesThe `offerId` of the exact room and rate the guest chose, copied from `list_hotels` unchanged. It names the hotel, the room, the rate, the stay, the party and the price the guest was shown, so none of those are passed separately. It is valid for 30 minutes — if the guest takes longer to decide, call `list_hotels` with this same `offerId` to get a fresh one: it re-prices that one room and nothing else, so the guest is not shown the whole property a second time. Never edit it or build one yourself.
guestCityYes
guestEmailYesThe hotel sends its confirmation here. It is the guest's own address, never yours. An example or placeholder address such as name@example.com is refused and nothing is reserved: ask the guest for the address they actually use.
guestPhoneYesThe guest's phone number, in any format the guest gives it.
guestPostalYesPostal code.
guestStreetYesStreet and house number.
guestCountryYesTwo-letter country code, e.g. DE, AT, CH. The country the guest lives in, not the one they are travelling to.
acceptedTermsYesTRUE only when the guest has agreed to book this rate. Where `list_hotels` gave that rate cancellation terms, show them first and get the agreement to those. Where its `cancelTerms` was null WE HOLD NONE — tell the guest plainly that we do not have this rate’s cancellation terms and that the hotel’s own terms apply and reach them with the hotel’s confirmation, then set this once they have said to go ahead knowing that. Never assume it on their behalf, and never treat a blank as a reason not to book.
guestLastNameYes
guestStreetNoNoHouse number, when the guest gives it separately from the street.
guestGivenNameYes
guestSalutationNoHow the guest is addressed, in their own words. Only pass what the guest told you; never guess from a name.

Output Schema

NameRequiredDescriptionDefault
errorNoPresent ONLY when nothing was booked. It carries the reason in words a guest can hear and, on a refusal you can recover from, the call to make next. Give the guest the reason; act on the rest yourself.
hotelNoThe property that took the booking.
reasonNoMachine-readable cause of a refusal: terms-not-accepted, guest-email-placeholder, offer-malformed, offer-bad-signature, offer-expired, offer-not-enabled, offer-not-bookable, listing-not-found, not-configured, not-recorded, room-not-offered, rate-not-offered, availability-unreadable, price-unreadable, price-moved-up, guest-details-incomplete, no-booking-identity, dry-run, ambiguous, not-confirmed, unexpected-error.
checkInNo
paymentNoWhat the guest owes and to whom. Nothing is ever charged here.
checkOutNo
paymentUrlNoOUR payment page, and the room is NOT reserved until the guest has paid. Their card is HELD, not charged. Present only when nothing was booked yet and payment is what gets it booked.
tellTheGuestNoWording meant for the guest rather than for you. On an ambiguous outcome it says NOT to book again — pass that on rather than retrying.
bookingReferenceNoOUR reference for this booking — the number the guest quotes to US. Different from `confirmationNumber`, which is the hotel’s and is what they quote at the property. Absent only when the booking could not be recorded.
confirmationNumberNoPresent ONLY when a room was actually booked. The hotel’s own reference — give it to the guest and tell them to keep it.

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Well beyond the annotations (readOnly=false, destructive=true, openWorld=true), it discloses the 30-minute offer expiry, that an expired or re-priced offer means nothing is booked, the two mutually exclusive success shapes (`confirmationNumber` vs `paymentUrl`), that payment is held at the desk or via link rather than charged now, and the ambiguity/idempotency hazard. These are exactly the side-effect details a mutation tool needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose and the offerId handoff, then the two outcomes, then the terms/guest-details rules. It is long and repeats some offerId expiry and acceptedTerms guidance already present in the schema property descriptions, but no sentence is filler and the ordering follows the call flow.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter, 10-required booking mutation with an output schema, the description covers everything an agent needs to execute and narrate correctly: offer lifecycle, outcome interpretation, payment timing, consent gating, and the double-booking guard. Return values need little explanation since an output schema exists, yet the two response shapes are still made actionable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 75%, and the description supplies the business meaning the schema can't: why hotel/room/rate/stay/price are absent (all encoded in `offerId`), why a stripped offerId must never be edited or rebuilt, and how `acceptedTerms` must be set relative to the rate's `cancelTerms`, including the explicit rule that a null `cancelTerms` is not a reason to refuse. It also states guestPhone and billing fields must come from the guest and never be invented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ("Book a hotel room") and immediately scopes it to offers produced by the sibling `list_hotels`, so the agent can tell the two apart without opening either schema. It also names the exact identifier (offerId) that ties this tool to the sibling's output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states there is no separate check to make first, tells the agent to pass the chosen offer's `offerId` unchanged, and routes back to `list_hotels` with that same `offerId` when the offer expired rather than re-listing the property. It also gives an explicit when-NOT-to-call rule: on an ambiguous response, do not call again because a reservation may already exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources