Skip to main content
Glama
RobertoReale

hotel-rates-mcp

by RobertoReale
README.md
# hotel-rates-mcp

A small [MCP](https://modelcontextprotocol.io) server that gives an
MCP client **one deterministic tool** for verified, bookable hotel prices.

It exists to close a gap in the budget-travel pipeline: when verification is a
free-text instruction ("check the real price before recommending"), an agent can
quietly skip it and hand back a Google Hotels **teaser** that collapses at checkout.
As a *tool*, the verification always runs — every total it returns is the
tax-inclusive `total_rate`, tax-exclusive providers are flagged, and each result
carries a durable Booking.com fallback link.

The price logic is a library port of the standalone script in
[RobertoReale/travel-search](https://github.com/RobertoReale/travel-search).

## Tool

### `verified_hotel_prices`

| Arg | Default | Meaning |
|---|---|---|
| `location` | — | city/area query, e.g. `"Barceloneta, Barcelona"` |
| `checkin` / `checkout` | — | `YYYY-MM-DD` |
| `adults` | 2 | occupancy |
| `currency` | `EUR` | ISO code |
| `top` | 8 | how many cheapest properties to deep-resolve |
| `providers` | — | optional OTA whitelist, e.g. `"Booking.com,Expedia.com"` |
| `check_links` | false | HEAD-validate booking links and drop dead ones |

Returns JSON: each result has the verified all-in headline provider, every provider
with its `tax_status` (`ok` / `warn` / `na`), and a durable `stable_link`. Ranking is
always on the tax-inclusive total; when the cheapest provider excludes taxes, the tool
steps up to the cheapest genuinely all-in provider, so the number you compare is a true
final total. Tourist tax is paid at the property, is in no online
total, and is deliberately **not** estimated.

## Setup

```bash
# get a free SerpAPI key (250 searches/month, no card): https://serpapi.com
export SERPAPI_KEY=your_key_here     # PowerShell: $env:SERPAPI_KEY="your_key_here"

# with uv
uv sync
uv run hotel-rates-mcp

# or with pip
pip install -e .
hotel-rates-mcp
```

### Wire it into an MCP client

Add to your project's `.mcp.json`:

```json
{
  "mcpServers": {
    "hotel-rates": {
      "command": "uv",
      "args": ["run", "--directory", "C:\\\\Users\\\\Admin\\\\Downloads\\\\hotel-rates-mcp", "hotel-rates-mcp"],
      "env": { "SERPAPI_KEY": "your_key_here" }
    }
  }
}
```

## Tests

```bash
uv run pytest -q        # or: pytest -q
```

Tests cover the pure parsing/ranking/tax/link helpers — no network calls.

## Two kinds of tax

1. **OTA taxes & fees (VAT, service)** — the comparability problem. Handled by
   ranking on `total_rate` and flagging/stepping past tax-exclusive providers.
2. **Tourist tax** — a flat local levy paid in cash at the
   property, in no online total, identical across providers, so it never changes the
   ranking. Deliberately **not** estimated (rates vary by municipality and star
   class); confirm it locally and budget for it as a separate cash cost.

## License

MIT