search_activities
Find tours, attractions, and experiences in any city for your travel dates. Filter by category to plan day activities or fill your itinerary.
Instructions
Search tours, experiences, attractions, sightseeing, and things to do via Viator (200K+ activities worldwide). Filter by city, date range, and category (food tours, walking tours, museums, snorkeling, sailing, hiking, sunset cruises, cooking classes, day trips, etc.). Returns activities with photos, ratings, durations, and per-person pricing. Use this when the user wants to plan day activities, find tours, book experiences, fill a trip itinerary, or pick attractions.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| city | Yes | City name (e.g., 'New York', 'Tokyo', 'Paris') | |
| date_from | Yes | Start date (YYYY-MM-DD) | |
| date_to | No | Optional end date (YYYY-MM-DD). Defaults to date_from for single-day searches. | |
| category | No | Optional category filter (e.g., 'food', 'culture', 'adventure', 'nightlife', 'wellness') |
Implementation Reference
- src/server.ts:760-772 (handler)The main handler for the 'search_activities' tool. It destructures args (city, date_from, date_to, category), builds a query string, calls the API at POST /v1/activities/search with query params, then trims the response using trimActivityResponse helper.
case "search_activities": { const { city, date_from, date_to, category } = args as { city: string; date_from: string; date_to?: string; category?: string; }; const qs = new URLSearchParams(); qs.set("city", city); qs.set("date_from", date_from); if (date_to) qs.set("date_to", date_to); if (category) qs.set("category", category); const result = await apiCall("POST", `/v1/activities/search?${qs.toString()}`); const trimmed = trimActivityResponse(result); return { content: [{ type: "text", text: JSON.stringify(trimmed, null, 2) }] }; } - src/server.ts:272-286 (schema)Input schema definition for the 'search_activities' tool. Defines properties: city (string, required), date_from (string, required), date_to (optional string), category (optional string).
{ name: "search_activities", description: "Search tours, experiences, attractions, sightseeing, and things to do via Viator (200K+ activities worldwide). Filter by city, date range, and category (food tours, walking tours, museums, snorkeling, sailing, hiking, sunset cruises, cooking classes, day trips, etc.). Returns activities with photos, ratings, durations, and per-person pricing. Use this when the user wants to plan day activities, find tours, book experiences, fill a trip itinerary, or pick attractions.", inputSchema: { type: "object" as const, properties: { city: { type: "string", description: "City name (e.g., 'New York', 'Tokyo', 'Paris')" }, date_from: { type: "string", description: "Start date (YYYY-MM-DD)" }, date_to: { type: "string", description: "Optional end date (YYYY-MM-DD). Defaults to date_from for single-day searches." }, category: { type: "string", description: "Optional category filter (e.g., 'food', 'culture', 'adventure', 'nightlife', 'wellness')" }, }, required: ["city", "date_from"], }, }, - src/server.ts:272-285 (registration)The tool is registered in the ALL_TOOLS array with name 'search_activities', its description (searching tours/experiences via Viator), and the inputSchema. This array is exposed via ListToolsRequestSchema handler.
{ name: "search_activities", description: "Search tours, experiences, attractions, sightseeing, and things to do via Viator (200K+ activities worldwide). Filter by city, date range, and category (food tours, walking tours, museums, snorkeling, sailing, hiking, sunset cruises, cooking classes, day trips, etc.). Returns activities with photos, ratings, durations, and per-person pricing. Use this when the user wants to plan day activities, find tours, book experiences, fill a trip itinerary, or pick attractions.", inputSchema: { type: "object" as const, properties: { city: { type: "string", description: "City name (e.g., 'New York', 'Tokyo', 'Paris')" }, date_from: { type: "string", description: "Start date (YYYY-MM-DD)" }, date_to: { type: "string", description: "Optional end date (YYYY-MM-DD). Defaults to date_from for single-day searches." }, category: { type: "string", description: "Optional category filter (e.g., 'food', 'culture', 'adventure', 'nightlife', 'wellness')" }, }, required: ["city", "date_from"], }, - src/server.ts:676-693 (helper)The trimActivityResponse helper function that processes the raw API response for activities. Slices data to limit (default 20), maps each activity to a compact object with product_id, name, category, duration, price_usd, rating, reviews_count, thumbnail, and description.
function trimActivityResponse(raw: any, limit = 20): any { const data = Array.isArray(raw?.data) ? raw.data : []; const trimmed = data.slice(0, limit).map((a: any) => ({ product_id: a.product_id || a.id, name: a.name || a.title, category: a.category, duration: a.duration || (a.duration_hours ? `${a.duration_hours}h` : null), price_usd: a.price_usd || a.price, rating: a.rating, reviews_count: a.reviews_count || 0, thumbnail: a.thumbnail || (a.photos?.[0]?.url) || (typeof a.photos?.[0] === "string" ? a.photos[0] : null), description: (a.description || "").replace(/<[^>]*>/g, "").slice(0, 320), })); return { data: trimmed, meta: { count: trimmed.length, total_returned: data.length, trimmed_for_llm: data.length > limit }, }; } - src/server.ts:509-510 (registration)Annotation registration for search_activities in TOOL_ANNOTATIONS: title 'Search Activities & Experiences', with readOnlyHint=true, destructiveHint=false, idempotentHint=true, openWorldHint=true.
search_activities: { title: "Search Activities & Experiences", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }, search_events: { title: "Search Live Events & Tickets", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },