Developer Docs
Give your AI agent live DACH hotel availability: search 80,000+ properties, then read real rooms, EUR prices, cancellation terms, room photos and a dated booking link from each hotel's own booking engine.
Connect your agent
Bluerails402 is a plain MCP server — streamable HTTP, JSON-RPC 2.0 — so any MCP-compatible client can connect to it. No local config file, no API key, no sign-in. Point your client at the endpoint:
https://402.bluerails.com/mcp- Claude
- Settings → Connectors → Add custom connector, then paste the endpoint. Claude also discovers the server from
402.bluerails.com/.well-known/mcp.json. - ChatGPT
- Turn on Developer mode under Settings → Security and login, then add a new connection and enter the endpoint — see OpenAI's own instructions. The results card renders inline in ChatGPT as well as in Claude.
- VS Code, and anything else
- Use the ready-made server config at /.well-known/mcp.json, or just POST JSON-RPC to the endpoint yourself.
Authentication
None. list_hotels is public and read-only, so the connector above works immediately with no API key and no sign-in prompt. The other verticals — publishers, ecommerce stores, SaaS companies — are served over the REST API rather than as MCP tools; see openapi.json.
Tool reference
One tool. list_hotels searches DACH properties and, when you pass a stay, prices them in the same call.
list_hotels
Search DACH hotel properties, and price them for a stay in the same call. Pass city with any place name — a village or resort works as well as a city — and results come back nearest first with distanceKm. Add checkIn, checkOut and adults and the answer splits in two: priced holds the hotels whose live rates were read, every room with its EUR price for the whole stay, its cancellation terms, its photos in imageUrls and its other rate plans in ratePlans, each with a booking link carrying the dates; unpriced holds the rest with their plain links, and a null bookingUrl there means we hold no booking link at all — websiteUrl is the property's own site, never a way to book. priced is returned on page 1 only, and holds the hotels we could actually get a rate for, drawn from your whole filter set rather than from this page. limit is the ceiling across both groups. maxPricePerNight filters: priced then holds only the hotels and rooms at or under the budget, and dearer hotels come back only when not one fits, in aboveBudget. An empty priced alongside an empty aboveBudget means the rates could NOT be read — unknown, never sold out. A property whose engine stated it is full for the stay is left out of the answer entirely, and hint says how many. No count of the whole match is returned: you get the page you asked for. Every link in the answer — bookingUrl and websiteUrl alike — is a 402.bluerails.com/go/ redirect that 302s to the real destination, so hand it to the guest as-is. language renders the labels on the results card in German or English; room names, rate plans and cancellation terms always stay in the booking engine’s own words.
Signature
list_hotels(
city?: string, radius?: { value: number, unit: "km" | "mi" },
query?: string, country?: "de" | "at" | "ch",
starRating?: "3-star" | "4-star" | "5-star" | "boutique",
checkIn?: string, checkOut?: string, adults?: number,
childrenAges?: number[], maxPricePerNight?: number, language?: string,
page?: number, // 1-2, default 1
limit?: number, // 1-20, default 10
) → {
unpriced: Hotel[], // the only field always present
priced?: PricedHotel[], aboveBudget?: PricedHotel[],
place?: string, radiusUsedKm?: number, stay?: Stay,
language?: string, hint?: string,
// when nothing was found, or the input was rejected
placeNotRecognised?: string, nearestBeyondRadiusKm?: number | null,
nearestSearchedToKm?: number, requestedRadiusKm?: number,
maxRadiusKm?: number, error?: string,
}
// page and limit out of range are JSON-RPC -32602 errors, never clamped.
// radius is two checks: value must be 1-100 whatever the unit, and the
// converted distance must be <= 100 km. The first is a -32602; the second
// is NOT — 63 mi is a normal 200 carrying error, requestedRadiusKm and
// maxRadiusKm, so handle it as data, not as a thrown exception.Example call
list_hotels({
city: "Bremen",
radius: { value: 3, unit: "km" },
checkIn: "2026-09-20",
checkOut: "2026-09-22",
adults: 2,
limit: 20,
})Example response
// A real response, trimmed: one of the 9 priced hotels with one of its 4 rooms, and 2 of
// the 11 unpriced ones — the second holding no booking link at all.
{
"place": "Bremen",
"radiusUsedKm": 3,
"stay": {
"checkIn": "2026-09-20",
"checkOut": "2026-09-22",
"adults": 2,
"children": 0
},
"priced": [
{
"slug": "hotel-edel-weiss",
"name": "Hotel Edel Weiss",
"shortDescription": "Hotel Edel Weiss is a 4-star hotel in bremen, DE.",
"tags": ["de", "bremen", "Heinz Vesecky", "wifi", "4-star", "mid-range"],
"websiteUrl": "https://402.bluerails.com/go/dUKHiE78uA1G52v_",
"listing": {
"starRating": "4-star",
"guestRating": 4.5,
"address": {
"street": "Bahnhofsplatz 8",
"postalCode": "28195",
"city": "Bremen",
"countryCode": "de"
},
"city": "Bremen",
"country": "de",
"amenities": ["bremen", "Heinz Vesecky", "wifi"]
},
"distanceKm": 0.7753051258616253,
"distanceApproximate": false,
"rooms": [
{
"name": "Economy Doppelzimmer ",
"eurPrice": 191.2,
"cancelTerms": "100% (191.2 EUR)",
"soldOut": false,
"ratePlanName": "nicht kostenfrei Stornierbar",
"breakfastIncluded": false,
"bookingUrl": "https://402.bluerails.com/go/PAW3xVPfgBK4A9AL",
"imageUrls": [
"https://cdn.dirs21.de/v1/cdn/images/81426/1000041578.jpg?h=500",
"https://cdn.dirs21.de/v1/cdn/images/81426/1000041579.jpg?h=500"
],
"ratePlans": [
{
"ratePlanName": "Standardrate",
"eurPrice": 201,
"cancelTerms": "100% (201 EUR)",
"soldOut": false,
"breakfastIncluded": false,
"bookingUrl": "https://402.bluerails.com/go/P7LJOKLBwSbUT7oc"
},
{
"ratePlanName": "Experience Bremen: a 3-day mini-break",
"eurPrice": 222.03,
"cancelTerms": "100% (222.03 EUR)",
"soldOut": false,
"breakfastIncluded": true,
"bookingUrl": "https://402.bluerails.com/go/-1HTu1Z5F5Jdl7Jj"
}
]
}
],
"stayTotalEur": 191.2,
"pricePerNightEur": 96,
"bookingUrl": "https://402.bluerails.com/go/XGG8-qKrft7n0GYX",
"bookingEngine": "dirs21",
"isOta": false,
"availabilitySource": "dirs21-ibe",
"datesApplied": true,
"partyApplied": true
}
],
"unpriced": [
{
"slug": "hotel-classico-Bremen",
"name": "Hotel Classico",
"shortDescription": "Hotel Classico is a boutique hotel in Bremen, DE.",
"websiteUrl": "https://402.bluerails.com/go/ttR9Is3Zd8r_OD-p",
"tags": ["de", "Bremen", "boutique", "independent", "business", "4-star", "mid-range"],
"distanceKm": 0.07897485301717645,
"distanceApproximate": false,
"bookingUrl": "https://402.bluerails.com/go/yCaELM9k0BHlK6pa",
"listing": {
"starRating": "boutique",
"guestRating": 4.5,
"address": {
"street": "Hinter dem Schütting 1 A",
"postalCode": "28195",
"city": "Bremen",
"countryCode": "de"
},
"city": "Bremen",
"country": "de",
"propertyType": "business",
"chain": "independent",
"amenities": ["Bremen"]
},
"datesApplied": false,
"partyApplied": false
},
{
"slug": "hotel-hanseatic",
"name": "Hotel Hanseatic",
"shortDescription": "Hotel Hanseatic is a 3-star hotel in bremen, DE.",
"websiteUrl": "https://402.bluerails.com/go/UfGTZkFVVWnzFIuL",
"tags": ["de", "bremen", "3-star", "independent", "business", "mid-range"],
"distanceKm": 0.33778274072368647,
"distanceApproximate": false,
"bookingUrl": null,
"listing": {
"starRating": "3-star",
"city": "bremen",
"country": "de",
"propertyType": "business",
"chain": "independent",
"amenities": ["bremen"]
}
}
]
}