Skip to main content
Glama
README.md
# HotelZero

An MCP (Model Context Protocol) server that searches hotels on Booking.com using Playwright browser automation. Features 80+ filter options for precise hotel searches.

## Features

- **Comprehensive Filtering**: 80+ filters covering property types, amenities, accessibility, activities, and more
- **Real Booking.com Data**: Uses actual Booking.com filter codes reverse-engineered from their URL parameters
- **Sponsored Ad Filtering**: Automatically excludes paid/promoted listings (native ads with `nad_` tracking)
- **Smart Scoring**: Results are scored and ranked by how well they match your criteria
- **Match Transparency**: Each result shows why it matched your filters

## Installation

```bash
npm install -g hotelzero

# Install Playwright browser (Chromium)
npx playwright install chromium
```

Or run directly with npx:

```bash
npx hotelzero
```

## Proxy Support

For heavy usage or to avoid IP blocks, you can configure a proxy server via the `HOTELZERO_PROXY` environment variable:

```bash
# HTTP proxy
HOTELZERO_PROXY=http://proxy.example.com:8080 npx hotelzero

# HTTP proxy with authentication
HOTELZERO_PROXY=http://user:pass@proxy.example.com:8080 npx hotelzero

# SOCKS5 proxy
HOTELZERO_PROXY=socks5://proxy.example.com:1080 npx hotelzero

# SOCKS5 proxy with authentication
HOTELZERO_PROXY=socks5://user:pass@proxy.example.com:1080 npx hotelzero
```

When a proxy is configured, you'll see confirmation in the startup logs:
```
Proxy enabled: http://proxy.example.com:8080
HotelZero v1.8.0 running on stdio
```

## Logging

HotelZero uses structured logging via [pino](https://github.com/pinojs/pino). Logs are written to stderr to avoid interfering with the MCP stdio transport.

### Log Level

Control log verbosity with the `HOTELZERO_LOG_LEVEL` environment variable:

```bash
# Available levels: trace, debug, info, warn, error, fatal, silent
# Default: info

# Debug mode - verbose output for troubleshooting
HOTELZERO_LOG_LEVEL=debug npx hotelzero

# Silent mode - no logs
HOTELZERO_LOG_LEVEL=silent npx hotelzero

# Error only - minimal output
HOTELZERO_LOG_LEVEL=error npx hotelzero
```

### Log Output

Logs are JSON-formatted for easy parsing:

```json
{"level":"info","time":"2026-02-15T12:00:00.000Z","service":"hotelzero","module":"server","version":"1.11.0","transport":"stdio","msg":"HotelZero server started"}
{"level":"info","time":"2026-02-15T12:00:01.000Z","service":"hotelzero","module":"browser","msg":"Browser initialized"}
{"level":"info","time":"2026-02-15T12:00:02.000Z","service":"hotelzero","module":"browser","destination":"Paris","msg":"Starting hotel search"}
```

## Session Persistence

HotelZero automatically saves browser session data (cookies, localStorage) to reduce bot detection and avoid repeated CAPTCHA challenges.

### How It Works

- Sessions are automatically saved after each successful request
- On startup, the previous session is loaded if available
- Default session location: `~/.hotelzero/session.json`

### Custom Session Path

Use `HOTELZERO_SESSION_PATH` to specify a custom location:

```bash
# Custom session file location
HOTELZERO_SESSION_PATH=/path/to/session.json npx hotelzero

# Disable session persistence (use empty string)
HOTELZERO_SESSION_PATH="" npx hotelzero
```

### Clearing Sessions

If you experience issues, you can delete the session file:

```bash
rm ~/.hotelzero/session.json
```

## Quick Start

### Run as MCP Server

Add to your MCP client configuration (e.g., Claude Desktop, OpenCode):

```json
{
  "mcpServers": {
    "hotelzero": {
      "command": "npx",
      "args": ["hotelzero"]
    }
  }
}
```

## Available Tools

### `find_hotels`

Search for hotels with comprehensive filtering. This is the primary tool with all 80+ filter options.

**Example:**
```json
{
  "destination": "San Juan, Puerto Rico",
  "checkIn": "2026-03-07",
  "checkOut": "2026-03-14",
  "beachfront": true,
  "freeWifi": true,
  "fitness": true,
  "minRating": 8
}
```

### `search_hotels`

Basic hotel search without filters. Use this for simple queries when you don't need specific criteria.

**Example:**
```json
{
  "destination": "Paris, France",
  "checkIn": "2026-06-01",
  "checkOut": "2026-06-05",
  "guests": 2,
  "rooms": 1
}
```

### `get_hotel_details`

Get detailed information about a specific hotel including full amenity list, description, and photos.

**Example:**
```json
{
  "url": "https://www.booking.com/hotel/pr/condado-vanderbilt.html"
}
```

---

## Complete Filter Reference

### Basic Search Parameters

| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `destination` | string | Yes | City or location (e.g., "San Juan, Puerto Rico") |
| `checkIn` | string | Yes | Check-in date (YYYY-MM-DD) |
| `checkOut` | string | Yes | Check-out date (YYYY-MM-DD) |
| `guests` | number | No | Number of guests (default: 2) |
| `rooms` | number | No | Number of rooms (default: 1) |
| `currency` | string | No | Currency code (USD, EUR, GBP, JPY, etc.) Default: USD |
| `sortBy` | enum | No | Sort results: `popularity`, `price_lowest`, `price_highest`, `rating`, `distance` |

### Rating & Price

| Filter | Type | Description |
|--------|------|-------------|
| `minRating` | number | Minimum review score: 6=Pleasant, 7=Good, 8=Very Good, 9=Wonderful |
| `minPrice` | number | Minimum price per night |
| `maxPrice` | number | Maximum price per night |

### Property Type

| Filter | Type | Options |
|--------|------|---------|
| `propertyType` | enum | `hotel`, `apartment`, `resort`, `villa`, `vacation_home`, `hostel`, `bnb`, `guesthouse`, `homestay`, `motel`, `inn`, `lodge`, `chalet`, `campground`, `glamping`, `boat`, `capsule`, `ryokan`, `riad`, `country_house`, `farm_stay` |
| `starRating` | number | 1, 2, 3, 4, or 5 stars |

### Beach & Location

| Filter | Type | Description |
|--------|------|-------------|
| `beachfront` | boolean | Property is directly on the beach |
| `beachAccess` | boolean | Property has beach access |
| `oceanView` | boolean | Room with ocean/sea view |
| `maxDistanceFromCenter` | enum | `half_mile`, `1_mile`, `2_miles` |

### Hotel Facilities

| Filter | Description |
|--------|-------------|
| `freeWifi` | Free WiFi throughout property |
| `pool` | Swimming pool |
| `spa` | Spa/wellness center |
| `fitness` | Fitness center/gym |
| `parking` | Parking available |
| `restaurant` | On-site restaurant |
| `bar` | On-site bar/lounge |
| `roomService` | 24-hour front desk/room service |
| `airportShuttle` | Airport shuttle service |
| `hotTub` | Hot tub/Jacuzzi |
| `sauna` | Sauna |
| `garden` | Garden |
| `terrace` | Terrace |
| `nonSmokingRooms` | Non-smoking rooms available |
| `familyRooms` | Family rooms |
| `evCharging` | Electric vehicle charging station |
| `casino` | Casino |
| `golf` | Golf course nearby (within 2 miles) |
| `tennis` | Tennis court |
| `bbqFacilities` | BBQ facilities |
| `laundry` | Laundry service |
| `concierge` | Concierge service |
| `businessCenter` | Business center |

### Room Facilities

| Filter | Description |
|--------|-------------|
| `airConditioning` | Air conditioning |
| `kitchen` | Kitchen or kitchenette |
| `balcony` | Private balcony |
| `privatePool` | Private pool |
| `privateBathroom` | Private bathroom |
| `bath` | Bathtub |
| `tv` | Television |
| `minibar` | Minibar |
| `safe` | In-room safe |
| `washingMachine` | Washing machine in unit |
| `soundproofing` | Soundproofed rooms |

### Bed Type

| Filter | Options |
|--------|---------|
| `bedType` | `king`, `queen`, `double`, `twin`, `single` |

### Meal Plans

| Filter | Description |
|--------|-------------|
| `breakfast` | Breakfast included in rate |
| `allInclusive` | All-inclusive package |
| `selfCatering` | Self-catering with kitchen amenities |

### Stay Type & Policies

| Filter | Description |
|--------|-------------|
| `petFriendly` | Pets allowed |
| `adultsOnly` | Adults-only property |
| `lgbtqFriendly` | LGBTQ+ friendly (Booking.com Travel Proud) |
| `freeCancellation` | Free cancellation available |
| `noPrepayment` | No prepayment required |
| `noBookingFee` | Book without credit card |

### Sustainability

| Filter | Description |
|--------|-------------|
| `sustainabilityCertified` | Has sustainability certification |

### Activities

| Filter | Description |
|--------|-------------|
| `snorkeling` | Snorkeling available |
| `diving` | Diving/scuba available |
| `fishing` | Fishing available |
| `hiking` | Hiking trails nearby |
| `cycling` | Cycling/biking available |
| `skiing` | Skiing nearby |
| `waterSports` | Water sports available |
| `horseRiding` | Horse riding available |

### Accessibility - Property Level

| Filter | Description |
|--------|-------------|
| `grabRails` | Grab rails in bathroom |
| `raisedToilet` | Raised toilet |
| `loweredSink` | Lowered sink |
| `braille` | Braille signage |
| `tactileSigns` | Tactile signs |
| `auditoryGuidance` | Auditory guidance |

### Accessibility - Room Level

| Filter | Description |
|--------|-------------|
| `wheelchairAccessible` | Entire unit wheelchair accessible |
| `groundFloor` | Ground floor unit available |
| `elevatorAccess` | Upper floors accessible by elevator |
| `walkInShower` | Walk-in shower |
| `rollInShower` | Roll-in shower (wheelchair accessible) |
| `showerChair` | Shower chair available |

### Hotel Chains

| Filter | Options |
|--------|---------|
| `hotelChain` | `marriott`, `hilton`, `hyatt`, `ihg`, `wyndham`, `best_western`, `accor`, `choice`, `radisson`, `ritz_carlton`, `four_seasons`, `fairmont`, `sheraton`, `westin`, `w_hotels`, `courtyard`, `residence_inn`, `hampton`, `embassy_suites`, `doubletree` |

---

## Example Queries

### Beach Vacation in Puerto Rico

```json
{
  "destination": "San Juan, Puerto Rico",
  "checkIn": "2026-03-07",
  "checkOut": "2026-03-14",
  "beachfront": true,
  "freeWifi": true,
  "fitness": true,
  "pool": true,
  "minRating": 8
}
```

### Luxury Ski Resort

```json
{
  "destination": "Aspen, Colorado",
  "checkIn": "2026-01-15",
  "checkOut": "2026-01-22",
  "propertyType": "resort",
  "starRating": 5,
  "skiing": true,
  "spa": true,
  "hotTub": true,
  "minRating": 9
}
```

### Family Beach Trip with All-Inclusive

```json
{
  "destination": "Cancun, Mexico",
  "checkIn": "2026-07-01",
  "checkOut": "2026-07-08",
  "guests": 4,
  "rooms": 2,
  "beachfront": true,
  "allInclusive": true,
  "familyRooms": true,
  "pool": true,
  "freeCancellation": true
}
```

### Accessible City Center Hotel

```json
{
  "destination": "London, UK",
  "checkIn": "2026-04-01",
  "checkOut": "2026-04-05",
  "maxDistanceFromCenter": "half_mile",
  "wheelchairAccessible": true,
  "elevatorAccess": true,
  "walkInShower": true,
  "freeWifi": true
}
```

### Pet-Friendly Road Trip Stop

```json
{
  "destination": "Portland, Oregon",
  "checkIn": "2026-05-10",
  "checkOut": "2026-05-12",
  "petFriendly": true,
  "parking": true,
  "freeCancellation": true,
  "maxPrice": 200
}
```

### Digital Nomad Long Stay

```json
{
  "destination": "Lisbon, Portugal",
  "checkIn": "2026-06-01",
  "checkOut": "2026-06-30",
  "propertyType": "apartment",
  "kitchen": true,
  "freeWifi": true,
  "washingMachine": true,
  "maxDistanceFromCenter": "1_mile",
  "maxPrice": 150
}
```

### Romantic Getaway

```json
{
  "destination": "Santorini, Greece",
  "checkIn": "2026-09-15",
  "checkOut": "2026-09-20",
  "adultsOnly": true,
  "oceanView": true,
  "privatePool": true,
  "breakfast": true,
  "spa": true,
  "minRating": 9
}
```

### Japanese Cultural Experience

```json
{
  "destination": "Kyoto, Japan",
  "checkIn": "2026-04-01",
  "checkOut": "2026-04-07",
  "propertyType": "ryokan",
  "breakfast": true,
  "minRating": 8
}
```

### Eco-Friendly Adventure

```json
{
  "destination": "Costa Rica",
  "checkIn": "2026-02-01",
  "checkOut": "2026-02-08",
  "sustainabilityCertified": true,
  "hiking": true,
  "snorkeling": true,
  "diving": true
}
```

### Golf Trip

```json
{
  "destination": "Scottsdale, Arizona",
  "checkIn": "2026-03-01",
  "checkOut": "2026-03-05",
  "propertyType": "resort",
  "golf": true,
  "spa": true,
  "restaurant": true,
  "bar": true
}
```

---

## How It Works

### Server-Side Filtering

Filters are applied via Booking.com's `nflt` URL parameter using reverse-engineered filter codes. For example:

- `beachfront: true` adds `ht_beach=1`
- `freeWifi: true` adds `hotelfacility=107`
- `fitness: true` adds `popular_activities=11`
- `minRating: 8` adds `review_score=80`

### Client-Side Scoring

After fetching results, each hotel is scored based on how well it matches your criteria:

- **+20 points**: Beach-related filters when property mentions beach
- **+15 points**: Rating 9.0+ ("Excellent")
- **+10 points**: Each matched amenity (WiFi, pool, gym, etc.)
- **+5 points**: 500+ reviews (trustworthiness bonus)

Results are sorted by match score, so the best matches appear first.

### Sponsored Ad Filtering

Booking.com injects paid "native ads" into search results. These are identified and excluded by:

1. Detecting `nad_` (native ad tracking) in the hotel card HTML or links
2. Checking for explicit "Ad", "Sponsored", or "Promoted" labels

This ensures you only see organic results, not paid placements.

---

## Output Format

Each hotel result includes:

```
1. Hotel Name
   Price: $XXX per night
   Rating: X.X/10 Rating Text (XXX reviews)
   Location: X.X miles from center
   Amenities: Pool, Free WiFi, Gym, ...
   Match Score: XX
   Why it matches: Near beach, Has WiFi, Has gym, ...
   Book: https://www.booking.com/hotel/...
```

---

## Technical Details

### Architecture

```
src/
├── index.ts      # MCP server with tool definitions
├── browser.ts    # Playwright automation & filter mappings
└── test*.ts      # Test scripts
```

### Dependencies

- `@modelcontextprotocol/sdk` - MCP server SDK
- `playwright` - Browser automation
- `zod` - Schema validation

### Browser Configuration

- **Headless Mode**: Runs without visible browser window
- **Anti-Detection**: Custom user agent and disabled automation flags
- **User Agent Rotation**: Randomly selects from 14 realistic browser profiles (Chrome, Firefox, Safari, Edge) on each session
- **Auto-Scrolling**: Loads more results by scrolling the page
- **Popup Handling**: Automatically dismisses cookie banners and sign-in modals

### Filter Code Mappings

All Booking.com filter codes are mapped in `browser.ts`:

```typescript
const FILTER_CODES = {
  propertyType: { hotel: "ht_id=204", resort: "ht_id=206", ... },
  hotelfacility: { freeWifi: 107, pool: 433, spa: 54, ... },
  roomfacility: { airConditioning: 11, kitchen: 999, ... },
  popularActivities: { fitness: 11, golf: 12, skiing: 13, ... },
  chaincode: { marriott: 1080, hilton: 1078, ... },
  // ... 20+ filter categories
};
```

---

## Limitations

- **Rate Limiting**: Booking.com may rate-limit or block automated requests
- **Results Cap**: Returns ~25 results per search (first page + scroll load)
- **Price Accuracy**: Prices may vary based on availability and timing
- **Filter Availability**: Some filters may not apply to all destinations

---

## Troubleshooting

### "Browser not initialized"

Run `npx playwright install chromium` to install the browser.

```bash
npx playwright install chromium
```

If that doesn't work, try forcing a reinstall:
```bash
npx playwright install chromium --force
```

### No results returned

- **Check dates**: Ensure check-in/check-out dates are in the future
- **Verify destination**: Try more specific locations like "Paris, France" instead of just "Paris"
- **Reduce filters**: Too many filters can result in zero matches - try removing some
- **Check availability**: Some destinations may have no availability for your dates

### CAPTCHA or Access Denied

If you encounter CAPTCHA challenges:

1. **Wait 5-10 minutes** before retrying
2. **Check your session**: Delete the session file and try again
   ```bash
   rm ~/.hotelzero/session.json
   ```
3. **Use a proxy**: Consider configuring a proxy server (see [Proxy Support](#proxy-support))
4. **Reduce request frequency**: Avoid making many rapid requests

### Blocked by Booking.com

- **Rate limiting**: Wait a few minutes before retrying
- **Session issues**: Clear the session file (`rm ~/.hotelzero/session.json`)
- **IP blocked**: Use a proxy server or try from a different network
- **User agent rotation**: HotelZero rotates user agents automatically, but excessive use from one IP can still trigger blocks

### Proxy not working

- **Verify accessibility**: Test the proxy with `curl` first
  ```bash
  curl -x http://proxy:8080 https://www.booking.com
  ```
- **Check credentials**: Ensure username/password are URL-encoded if they contain special characters
- **Protocol support**: Ensure the proxy supports HTTPS connections
- **Connection timeout**: Some proxies may be slow - try a different one

### Prices or Data Missing

- **Dynamic loading**: Some data loads asynchronously; try increasing timeouts
- **Currency issues**: Specify currency explicitly with `currency: "USD"`
- **Regional differences**: Some properties may not show prices for certain regions

### Session Issues

If you experience inconsistent behavior:

```bash
# Clear the session and start fresh
rm ~/.hotelzero/session.json

# Or disable session persistence entirely
HOTELZERO_SESSION_PATH="" npx hotelzero
```

### Debug Mode

Enable debug logging to see detailed information:

```bash
HOTELZERO_LOG_LEVEL=debug npx hotelzero
```

This will show:
- URL being requested
- Filters being applied
- Number of results found
- Any errors or warnings

### Tests Failing

If you're running the test suite and tests fail:

1. **Network issues**: Tests hit live Booking.com - check your connection
2. **Rate limiting**: Wait a few minutes between test runs
3. **Selector changes**: Booking.com may have updated their HTML structure

---

## API Response Schema

### HotelResult (from `find_hotels` / `search_hotels`)

```typescript
interface HotelResult {
  name: string;                    // Hotel name
  price: number | null;            // Price per night as number (null if not shown)
  priceDisplay: string;            // Formatted price string (e.g., "$199")
  rating: number | null;           // Review score 0-10 (null if no reviews)
  ratingText: string;              // Rating description (e.g., "Excellent", "Very Good")
  reviewCount: number | null;      // Number of reviews (null if not shown)
  location: string;                // Neighborhood/area name
  distanceToCenter: string;        // Distance from center (e.g., "0.5 miles from center")
  amenities: string[];             // Detected amenities (e.g., ["Pool", "Free WiFi", "Spa"])
  highlights: string[];            // Special highlights (e.g., ["Free Cancellation"])
  link: string;                    // Full Booking.com URL for the hotel
  thumbnailUrl: string | null;     // Hotel thumbnail image URL (null if not available)
  availability: string | null;     // Availability status (e.g., "Only 2 rooms left!")
  matchScore?: number;             // Relevance score based on filters (only with filters)
  matchReasons?: string[];         // Why this hotel matched (only with filters)
}
```

### HotelDetails (from `get_hotel_details` / `compare_hotels`)

```typescript
interface HotelDetails {
  name: string;                    // Hotel name
  url: string;                     // Booking.com URL
  rating: number | null;           // Review score 0-10
  ratingText: string;              // Rating description
  reviewCount: number | null;      // Total number of reviews
  starRating: number | null;       // Official star rating 1-5
  address: string;                 // Full address
  description: string;             // Hotel description text
  highlights: string;              // Property highlights summary
  pricePerNight: number | null;    // Price per night as number
  priceDisplay: string;            // Formatted price per night
  totalPrice: string;              // Total stay price (formatted)
  checkInTime: string;             // Check-in time (e.g., "15:00")
  checkOutTime: string;            // Check-out time (e.g., "11:00")
  popularFacilities: string[];     // Top facilities list
  allFacilities: string[];         // Complete facilities list
  roomTypes: string[];             // Available room type names
  photos: string[];                // Photo URLs
  nearbyAttractions: string[];     // Nearby points of interest
  guestReviewHighlights: string[]; // Notable review excerpts
  locationInfo: string;            // Location description
}
```

### AvailabilityResult (from `check_availability`)

```typescript
interface AvailabilityResult {
  available: boolean;              // Whether rooms are available
  hotelName: string;               // Hotel name
  checkIn: string;                 // Check-in date (YYYY-MM-DD)
  checkOut: string;                // Check-out date (YYYY-MM-DD)
  guests: number;                  // Number of guests searched
  rooms: number;                   // Number of rooms searched
  roomOptions: RoomOption[];       // Available room types
  lowestPrice: number | null;      // Lowest price found
  lowestPriceDisplay: string;      // Formatted lowest price
  message: string;                 // Status message
  url: string;                     // Booking URL with dates
}

interface RoomOption {
  name: string;                    // Room type name
  price: number | null;            // Price as number
  priceDisplay: string;            // Formatted price
  sleeps: number | null;           // Maximum occupancy
  features: string[];              // Room features
  bedType: string;                 // Bed configuration
  cancellation: string;            // Cancellation policy
  breakfast: string;               // Meal plan info
}
```

### ReviewsResult (from `get_reviews`)

```typescript
interface ReviewsResult {
  hotelName: string;               // Hotel name
  overallRating: number | null;    // Overall score 0-10
  totalReviews: number;            // Total review count
  ratingBreakdown: RatingBreakdown; // Scores by category
  reviews: Review[];               // Individual reviews
  url: string;                     // Hotel URL
}

interface RatingBreakdown {
  staff: number | null;            // Staff rating
  facilities: number | null;       // Facilities rating
  cleanliness: number | null;      // Cleanliness rating
  comfort: number | null;          // Comfort rating
  valueForMoney: number | null;    // Value rating
  location: number | null;         // Location rating
  freeWifi: number | null;         // WiFi rating
}

interface Review {
  title: string;                   // Review title
  rating: number | null;           // Individual score 0-10
  date: string;                    // Review date
  travelerType: string;            // Traveler type (e.g., "Couple", "Family")
  country: string;                 // Reviewer's country
  stayDate: string;                // When they stayed
  roomType: string;                // Room they booked
  nightsStayed: string;            // Length of stay
  positive: string;                // Positive comments
  negative: string;                // Negative comments
}
```

### PriceCalendarResult (from `get_price_calendar`)

```typescript
interface PriceCalendarResult {
  hotelName: string;               // Hotel name
  startDate: string;               // Calendar start (YYYY-MM-DD)
  endDate: string;                 // Calendar end (YYYY-MM-DD)
  nights: number;                  // Number of nights checked
  currency: string;                // Currency code
  prices: DatePrice[];             // Price for each date
  lowestPrice: number | null;      // Lowest price in range
  lowestPriceDate: string | null;  // Date with lowest price
  highestPrice: number | null;     // Highest price in range
  highestPriceDate: string | null; // Date with highest price
  averagePrice: number | null;     // Average price
  url: string;                     // Hotel URL
}

interface DatePrice {
  date: string;                    // Date (YYYY-MM-DD)
  price: number | null;            // Price as number
  priceDisplay: string;            // Formatted price
  available: boolean;              // Whether available
  currency: string;                // Currency code
}
```

### Error Response

When an error occurs, the response includes:

```typescript
interface ErrorResponse {
  content: [{
    type: "text";
    text: string;                  // Error message with code and help text
  }];
  isError: true;
}
```

Error codes:
- `BROWSER_NOT_INITIALIZED` - Call init() first
- `NAVIGATION_FAILED` - Page load failed
- `RATE_LIMITED` - Too many requests
- `CAPTCHA_DETECTED` - CAPTCHA challenge encountered
- `NO_RESULTS` - Search returned no results
- `DESTINATION_NOT_FOUND` - Invalid destination
- `NETWORK_ERROR` - Connection issue
- `TIMEOUT` - Request timed out
- `BLOCKED` - Access denied by Booking.com

---

## License

MIT

TDQS

A4.1/5.0

Scored across 7 tools

Disambiguation4/5

Most tools have clearly distinct purposes (search, details, compare, availability, reviews, price calendar). The main overlap is between find_hotels and search_hotels, but the descriptions clarify that find_hotels is the filtered version and search_hotels is basic, making the distinction manageable.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern: find_hotels, search_hotels, get_hotel_details, compare_hotels, check_availability, get_reviews, get_price_calendar. No mixed conventions or vague verbs.

Tool Count5/5

Seven tools is well within the ideal 3-15 range. Each tool covers a distinct aspect of the hotel search and comparison workflow, and none feel redundant or unnecessary.

Completeness4/5

The tool surface covers the core hotel discovery and planning workflow: searching, filtering, detailed views, comparisons, availability checks, reviews, and price trends. The only notable gap is the lack of a booking/reservation tool, but the server's purpose may be limited to research and comparison rather than booking.

Maintenance

ActivityInactive
ResponsivenessNo issues