Appearance
search_hotels
The primary tool for hotel discovery and data fetching. Supports multiple search methods, configurable data blocks, semantic filtering, and pagination.
Search parameters
Provide exactly one of these (mutually exclusive):
| Parameter | Type | Description |
|---|---|---|
queries | string[] (1-3) | Location or hotel name. E.g., ["Amsterdam"], ["Hilton London"] |
latitude + longitude | number | Coordinate-based search |
nearMe | boolean | Search near user's location (requires geo context in _meta) |
address | string | Geocoded address/landmark search |
Date parameters
| Parameter | Type | Description |
|---|---|---|
checkIn | string | Check-in date (YYYY-MM-DD) |
checkOut | string | Check-out date (alternative to nights) |
nights | number | Stay duration in nights (default: 3) |
dayDistance | number | Days from today for check-in (e.g., 7 for next week) |
Provide checkIn or dayDistance (not both). If no dates are provided, defaults to check-in 15 days from today for 3 nights.
Data control
include array
Controls which data blocks are returned. Default: ['location', 'rating', 'classification', 'media', 'offers'].
Available blocks: location, rating, classification, facility, media, policy, offer, room, review, faq, insight, analytic
See Data Types for the schema of each block.
Offer options
json
{
"offers": {
"mode": "top_offers",
"sort": "price:total_asc",
"filters": {
"freeCancellation": "included",
"mealIncluded": "included",
"mealTypes": ["breakfast"]
}
}
}| Field | Values | Default |
|---|---|---|
mode | cheapest, top_offers (curated selection), all (available offers from Vio and external providers, cheapest first) | top_offers |
sort | price:total_asc, price:base_asc, price:with_tax_asc — curated modes only; ignored in all (fixed cheapest-first order) | price:total_asc |
filters.freeCancellation | any, included, excluded | any |
filters.mealIncluded | any, included, excluded | any |
filters.mealTypes | Array of meal types | - |
filters.payLater | any, included, excluded | any |
Meal and cancellation filters (mealIncluded, mealTypes, freeCancellation) apply in every mode. Counts and the cheapest rate describe the matching offers returned. filters.payLater applies to the curated modes only and is rejected with mode: "all". No-op values (any) are accepted everywhere.
With mode: "all", offer links open the hotel's page on Vio with the search dates and guests, where users select a deal.
mode: "all" and the room include are heavier requests. Keep the defaults when browsing, and pair mode: "all" with pageSize: 1 when you want the full rate list for one named hotel — that combination is optimized for exactly this case.
Review options
json
{
"reviews": {
"max": 10,
"sortBy": "recency",
"ratings": [8, 9, 10],
"searchTerms": ["breakfast", "location"]
}
}Media options
json
{
"media": {
"maxImages": 5
}
}Filters
json
{
"filters": {
"starRatings": [4, 5],
"guestRating": [8, 9, 10],
"minPrice": 50,
"maxPrice": 200,
"facilities": ["pool", "gym", "pet friendly"],
"propertyTypes": ["hotel"],
"excludePropertyTypes": ["hostel"],
"themes": ["beach", "romantic"]
}
}Filter logic:
- Different filter types combine with AND
- Values within
starRatings,guestRating,propertyTypes,themesuse OR - Values within
facilitiesuse AND (hotel must have all listed facilities) facilities,propertyTypes, andthemesuse semantic matching (natural language terms)
Room optimization
| Parameter | Type | Default |
|---|---|---|
optimizeRooms | boolean | false |
When enabled, the server searches across different room configurations for the same total occupancy to find the best deal. For example, a request for 6 adults will compare offers for:
- 6 adults in 1 room
- 3 + 3 (two rooms)
- 2 + 2 + 2 (three rooms)
Each hotel returns offers for only the configuration with the best price. Use this for large groups where room split flexibility could yield better rates.
Price mode
| Parameter | Values | Default |
|---|---|---|
priceMode | total, nightly | total |
total— Prices represent the entire stay (default).nightly— Prices are divided by the number of nights for per-night rates.
Search mode
| Parameter | Values | Default |
|---|---|---|
searchMode | fast, deep | fast |
fast— Returns offers quickly. May return partial results from a subset of providers.deep— Exhaustive search across all providers. Complete results, but slower response time.
offers.mode: "all" automatically uses deep, even if searchMode is fast. roomsComplete: false indicates that room rates may be incomplete.
Use deep when the user needs a comprehensive price comparison across all providers. Use fast (default) for responsive search experiences where speed matters more than completeness.
Sorting
| Parameter | Values |
|---|---|
sortField | popularity, price, guestRating, starRating, distance |
sortOrder | ascending, descending |
Pagination
| Parameter | Type | Default | Description |
|---|---|---|---|
pageSize | number | 10 | Hotels per page (1-100) |
offsets | number[] | [0] | Starting positions per location (one offset per query) |
Response fields
| Field | Type | Description |
|---|---|---|
hasMoreResults | boolean | Whether more results are available. Do not paginate when false. |
nextOffsets | number[] | Offsets to pass in the next request. Omitted if no more results. |
totalResults | number | Total hotels matching the search criteria |
How pagination works
Pass nextOffsets from the response as offsets in your next request to fetch the next page:
json
// First request
{"queries": ["Amsterdam"], "pageSize": 5}
// Response includes: "nextOffsets": [5], "hasMoreResults": true
// Second request
{"queries": ["Amsterdam"], "pageSize": 5, "offsets": [5]}Multi-query pagination
When searching multiple locations, offsets has one entry per query. Each location paginates independently:
json
// First request
{"queries": ["Manhattan", "Brooklyn"], "pageSize": 5}
// Response includes: "nextOffsets": [5, 5], "hasMoreResults": true
// Second request — advances both locations
{"queries": ["Manhattan", "Brooklyn"], "pageSize": 5, "offsets": [5, 5]}Example request
json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_hotels",
"arguments": {
"queries": ["Amsterdam"],
"checkIn": "2026-04-01",
"nights": 3,
"rooms": [{"adults": 2}],
"include": ["location", "rating", "classification", "media", "offer", "insight"],
"filters": {
"starRatings": [4, 5],
"facilities": ["pool", "gym"]
},
"offers": {
"mode": "top_offers",
"filters": {
"freeCancellation": "included"
}
},
"pageSize": 5,
"sortField": "guestRating",
"sortOrder": "descending"
}
}
}Response fields
In addition to hotels, pagination fields, and resolved dates, the response includes:
| Field | Type | Description |
|---|---|---|
priceScope | string | "per_room" — prices are per room. "all_rooms_combined" — prices cover all rooms in the configuration. |
appliedFilters | object | Shows the resolved filter terms that were matched via semantic search. Contains facilities, propertyTypes, excludePropertyTypes, and themes arrays with id and name for each matched term. |
anchorHotelIds | string[] | When searching by hotel name (e.g., "Hilton London"), contains the IDs of the specifically matched hotels. These hotels have isAnchorHotel: true in the response and appear alongside similar alternatives. |
placeDisplayName | string | Display name of the resolved search location (e.g., "Amsterdam, Netherlands") |
placeId | string | Place identifier for the resolved location |
Example response
json
{
"include": ["location", "rating", "classification", "media", "offer", "insight"],
"language": "en",
"currency": "EUR",
"checkIn": "2026-04-01",
"checkOut": "2026-04-04",
"nights": 3,
"roomConfiguration": [{"adults": 2}],
"priceScope": "per_room",
"totalResults": 142,
"hasMoreResults": true,
"nextOffsets": [5],
"placeDisplayName": "Amsterdam, Netherlands",
"appliedFilters": {
"starRatings": [4, 5],
"facilities": [{"id": "123", "name": "Swimming Pool"}, {"id": "456", "name": "Gym"}]
},
"hotels": [
{
"id": "hotel_abc123",
"name": "Grand Hotel Amsterdam",
"url": "https://vio.com/Hotel/abc123?checkIn=2026-04-01&checkOut=2026-04-04",
"location": {
"address": "Dam 9, 1012 JS Amsterdam",
"displayName": "Amsterdam",
"latitude": 52.3731,
"longitude": 4.8932
},
"rating": {
"overall": 8.7,
"reviewCount": 2341
},
"classification": {
"starRating": 5,
"propertyType": {"id": "1", "name": "Hotel"}
},
"media": {
"images": ["https://...optimized-image.webp"],
"imagesAvailable": 45
},
"offers": {
"items": [
{
"id": "offer_xyz",
"url": "https://...",
"currency": "EUR",
"rate": {"base": 450, "taxes": 45, "hotelFees": 15},
"providerName": "Booking.com",
"roomName": "Deluxe King Room",
"tags": ["cheapest_offer", "free_cancellation"]
}
],
"cheapestRate": {"base": 450, "taxes": 45, "hotelFees": 15}
},
"insights": {
"overall": "Guests love the central location and excellent service...",
"categories": [
{"category": "Location", "title": "Perfect Location", "summary": "Steps from Dam Square..."},
{"category": "Service", "title": "Outstanding Staff", "summary": "Consistently praised..."}
]
}
}
]
}