MCP Tool Contract - Viator Experiences

This document defines the behavior, field requirements, invocation rules, and expected specifications for the Viator search_experiences and get_experience_details MCP tools. These instructions guide the model on when and how to use each tool, what inputs are required, and how to manage ambiguity.

Table of Contents

Base URL & Setup

The MCP server is available at:

https://exp-app-mcp.prod.ep.viator.com/mcp

Configure this as the server URL in your MCP client.

Tools

search_experiences

Retrieves a curated list of Viator experiences based on required trip context and travel dates.

Supports both low-intent ("things to do in London this weekend") and high-intent ("kid-friendly cooking classes in Rome in July") queries.

The model may re-issue refined search calls when the user adds additional criteria.

When to Use

Invoke this tool whenever the user is asking for activities, experiences, or things to do in a destination and enough context is available or can be clarified.

Examples that should invoke the tool:

When NOT to Use

Do NOT invoke the tool when the user:

The model should ask clarifying questions when query or dates are missing or ambiguous.

Required Behavior Rules

Request Fields

Field Type Required Description
searchTerm string Y The full user search query string. Destination, preferences, and activity type can all be expressed here (e.g. "kid-friendly cooking classes in Rome").
startDate string Y First available date in ISO-8601 format (YYYY-MM-DD). LLM must convert natural language to a concrete date.
endDate string N Last available date in ISO-8601 format (YYYY-MM-DD). Defaults to startDate if the user provides a single-day query.
duration integer N Maximum experience duration in minutes.
fromPrice number N Lowest per person price.
toPrice number N Highest per person price.
currency string N Currency code for price filtering and display (e.g. USD, EUR).
locale string N Language/region code (e.g. en-US). Defaults to en-US.
limit integer N Number of products to return (1-10). Defaults to 5.
sessionId string Y Session identifier. Generate on first call and reuse throughout the session.

Request example

{
  "searchTerm": "kid-friendly things to do in Paris",
  "startDate": "2025-06-01",
  "endDate": "2025-06-07",
  "limit": 5,
  "sessionId": "550e8400-e29b-41d4-a716-446655440000"
}

Response Fields

The tool returns a JSON object with:

Field Type Required Description
sessionId string Y Conversation identifier; echoes the request sessionId when provided, otherwise a server-generated value to reuse on follow-up calls.
experiences array Y List of experience summaries. Each element has:
experiences[].title string Y Human-readable name of the experience.
experiences[].code string Y Experience internal code. Pass this to get_experience_details for full detail.
experiences[].thumbnail string Y URL of the lead image. To be used in product cards or lists.
experiences[].freeCancellation boolean Y Whether free cancellation is available for this experience.
experiences[].fromPrice number Y Advertised per-person starting price in the search currency context.
experiences[].fromPriceBeforeDiscount number N Strikethrough or pre-discount price when shown; may be omitted or null.
experiences[].clickOffToLander string Y Outbound URL to the Viator lander for this experience.
experiences[].rating number N Average customer rating when the API supplies it; may be omitted or null.
experiences[].reviewCount number N Total review count when available; may be omitted or null.
experiences[].duration object N Length hints in minutes; may be omitted or null. When present, each sub-field may still be null:
experiences[].duration.fixedDurationInMinutes number N Fixed duration for single-length experiences.
experiences[].duration.variableDurationFromMinutes number N Lower bound when duration is a range.
experiences[].duration.variableDurationToMinutes number N Upper bound when duration is a range.
experiences[].keyAttributes object N Display-oriented experience metadata. May be omitted or null.
experiences[].keyAttributes.features array N Feature tags (e.g. KID_FRIENDLY).
experiences[].keyAttributes.mainCategory string N Primary category label for the experience when returned.

Response example

{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "experiences": [
    {
      "title": "Example Walking Tour",
      "code": "12345P7",
      "thumbnail": "https://example.com/image.jpg",
      "rating": 4.8,
      "reviewCount": 1200,
      "freeCancellation": true,
      "fromPrice": 49.0,
      "fromPriceBeforeDiscount": 59.0,
      "clickOffToLander": "https://example.com/lander",
      "duration": {
        "fixedDurationInMinutes": 120,
        "variableDurationFromMinutes": null,
        "variableDurationToMinutes": null
      },
      "keyAttributes": {
        "features": ["KID_FRIENDLY"],
        "mainCategory": "Walking Tours"
      }
    }
  ]
}

MCP App

This tool includes an MCP App that can be used to display the experiences in an interactive UI.

The application is hosted as a resource on this MCP server and can be accessed by the model using the URI provided in this tools response metadata.

get_experience_details

Retrieves enriched details for a specific Viator product, including description, highlights, images, inclusions/exclusions, insider tips, pricing, and booking URL.

Used when the user selects a product or explicitly asks for more information about one previously shown.

When to Use

Invoke this tool when the user:

If the user's reference is ambiguous (e.g. "the museum tour" after showing several), ask which one they mean before calling.

When NOT to Use

Request Fields

Field Type Required Description
code string Y Unique identifier of the Viator experience. Must be previously returned by search_experiences.
locale string N Language/region code (e.g. en-US). Defaults to en-US unless the user specifies or context implies another.
sessionId string Y A unique identifier for the current user-session. Re-used from the search_experiences response.

Request example

{
  "code": "12345P7",
  "locale": "en-US",
  "sessionId": "550e8400-e29b-41d4-a716-446655440000"
}

Response Fields

The tool returns a JSON object with:

Field Type Required Description
sessionId string Y Conversation identifier; echoes the request sessionId when provided, otherwise a server-generated value to reuse on follow-up calls.
experienceDetails object Y Detailed data for the selected experience.
experienceDetails.code string Y Experience internal code.
experienceDetails.title string Y Human-readable name of the experience.
experienceDetails.thumbnail string Y URL of the lead image. To be used in product cards or lists.
experienceDetails.freeCancellation boolean Y Whether free cancellation is available for this experience.
experienceDetails.fromPrice number Y Advertised per-person starting price in the search currency context.
experienceDetails.fromPriceBeforeDiscount number N Strikethrough or pre-discount price when shown; may be omitted or null.
experienceDetails.clickOffToPDP string Y Outbound URL to the Viator lander for this experience.
experienceDetails.rating number N Average customer rating when the API supplies it; may be omitted or null.
experienceDetails.reviewCount number N Total review count when available; may be omitted or null.
experienceDetails.duration object N Length hints in minutes; may be omitted or null. When present, each sub-field may still be null:
experienceDetails.duration.fixedDurationInMinutes number N Fixed duration for single-length experiences.
experienceDetails.duration.variableDurationFromMinutes number N Lower bound when duration is a range.
experienceDetails.duration.variableDurationToMinutes number N Upper bound when duration is a range.
experienceDetails.keyAttributes object N Display-oriented experience metadata. May be omitted or null.
experienceDetails.keyAttributes.features array N Feature tags (e.g. KID_FRIENDLY).
experienceDetails.keyAttributes.mainCategory string N Primary category label for the experience when returned.
experienceDetails.description string N Main experience description text.
experienceDetails.insiderTips string N Extra tips when available. May be omitted or not.

Response example

{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "experienceDetails": {
    "code": "12345P7",
    "title": "Example Walking Tour",
    "description": "Explore the city with a local expert guide.",
    "insiderTips": "Wear comfortable shoes.",
    "thumbnail": "https://example.com/image.jpg",
    "rating": 4.8,
    "reviewCount": 1200,
    "freeCancellation": true,
    "clickOffToPDP": "https://example.com/pdp"
  }
}

Error & Ambiguity Handling

Error Handling Rules

Empty results behaviour

If the tool returns zero results, the model must proactively guide the user toward a successful refinement. It should review the parameters used in the failed request and recommend the most appropriate based on the proposed logic below:

Rate Limiting

The API enforces rate limits to ensure reliable service across all consumers. Limits are generous and designed to accommodate standard conversational usage patterns, most integrations won't need to think about this at all.

If you do hit a limit, the server responds with the error message “Rate limit exceeded. Please retry after X seconds." Exponential backoff is also a safe default strategy.

If your use case involves unusually high call volumes, please reach out to the team before going live.

End-to-end example

Here's a complete flow from a user message through to a detail request:

User: "Find me kid-friendly things to do in Paris next weekend."

Step 1: Model resolves the date (assuming today is 2025-05-28): "next weekend" = startDate: 2025-06-07, endDate: 2025-06-08.

Step 2: Call search_experiences

{
  "searchTerm": "kid-friendly things to do in Paris next weekend",
  "startDate": "2025-06-07",
  "endDate": "2025-06-08",
  "limit": 5
}

Step 3: Server returns results including (among others):

{
  "sessionId": "550e8400-e29b-41d4-a716-446655440000",
  "experiences": [
    {
      "title": "Paris Catacombs Skip-the-Line Tour for Families",
      "code": "12345P7",
      "rating": 4.8,
      "reviewCount": 1200,
      "freeCancellation": true,
      "fromPrice": 49.0,
      "clickOffToLander": "https://viator.com/..."
    }
  ]
}

User: "Tell me more about the Catacombs tour."

Step 4: Call get_experience_details

{
  "code": "12345P7",
  "locale": "en-US",
  "sessionId": "550e8400-e29b-41d4-a716-446655440000"
}

Step 5: Server returns enriched product detail, which the model uses to present highlights, inclusions, pricing, and a booking link to the user.