viator-mcp
MCP server for the Viator Partner API (v2, Basic Access affiliate tier) — search the
Viator catalog of 300k+ tours, activities and experiences, get product details, availability
schedules and pricing, browse attractions and destinations, all over stdio. Read-only: this
tier cannot make bookings; every product result carries a productUrl for booking on viator.com.
Setup
Option A — npx (recommended)
Add to .mcp.json in your project or ~/.claude/mcp.json:
{
"mcpServers": {
"viator": {
"command": "npx",
"args": ["-y", "@chrischall/viator-mcp"],
"env": {
"VIATOR_API_KEY": "your-viator-partner-api-key"
}
}
}
}
Get a key by signing up as a Viator affiliate at partnerresources.viator.com — the Basic Access tier is free.
Option B — from source
git clone https://github.com/chrischall/viator-mcp
cd viator-mcp
npm install && npm run build
Then point .mcp.json at dist/index.js with VIATOR_API_KEY in env.
Workflow
- Find the destination id —
vt_search_freetextwithsearch_types: ["DESTINATIONS"](orvt_list_destinationsfor the full taxonomy). - Search products —
vt_search_productswith the destination id plus filters (price, dates, rating, duration, tags viavt_list_product_tags, flags likeFREE_CANCELLATION). Results are already slim while browsing — see Response shape. - Drill in —
vt_get_productfor full details;vt_get_availability_schedulefor seasons/start times/pricing (supplier currency — convert withvt_get_exchange_rates). - Attractions —
vt_search_attractions/vt_get_attractionfor landmark-centric browsing; each attraction lists its mapped product codes.
Tools
| Area | Tools |
|---|---|
| Products | vt_search_products, vt_get_product, vt_list_product_tags |
| Search | vt_search_freetext |
| Attractions | vt_search_attractions, vt_get_attraction |
| Availability | vt_get_availability_schedule |
| Reference | vt_list_destinations, vt_get_locations, vt_get_exchange_rates |
| Health | vt_healthcheck — is this connector working? Reports whether VIATOR_API_KEY resolved, whether Viator accepted it, and what to fix. Start here when another tool fails: an empty result can mean "no products" or "never authenticated". |
Response shape
Every read tool — all ten of them — takes view: "compact" | "full", and
compact is the default, so the smaller payload is what you get without
asking for it. Pass view: "full" for Viator's untouched record.
What compact does differs by tool, because only two of them have a field
projection written against Viator's documented shapes:
vt_search_productsandvt_search_freetextproject each ProductSummary down to its product code, title, from-price and currency, rating, review count, duration, confirmation type, flags, booking URL and cover image — and nothing else. (vt_search_freetextprojects only its PRODUCTS block; its attraction and destination results are media-stripped instead.) If Viator's shape drifts, the projection falls back to the raw response, media-stripped, rather than emitting an empty one.- The other eight —
vt_get_product,vt_list_product_tags,vt_search_attractions,vt_get_attraction,vt_get_availability_schedule,vt_list_destinations,vt_get_locationsandvt_get_exchange_rates— strip image and avatar URLs and do nothing else. Every other field comes back as Viator sent it.
vt_healthcheck takes no view: it reports a verdict it assembles itself, not
a Viator payload, and a rung that cannot change anything is worse than no
parameter.
(This replaced an opt-in compact: true flag. Passing compact now does
nothing — zod drops the unknown key and you get the compact rung regardless,
which is what the flag used to ask for.)
Notes
- Prices from
vt_search_products/vt_search_freetextare in the requestedcurrency; prices fromvt_get_availability_scheduleare in the supplier's currency. - Viator rate-limits per endpoint on a rolling 10s window; the server caches identical
reads (
VIATOR_CACHE_TTL, default 60s) and retries once honoringRetry-After. - Booking URLs (
productUrl,attractionUrl) must be used verbatim for affiliate attribution; passcampaign_valueto tag them.
