get_experience_details
Retrieve availability, venue information, and images for specific experiences on tickadoo® to support booking decisions.
Instructions
Get detailed availability, venue details, and images for a specific tickadoo® experience. Prefer passing the tickadoo slug or booking URL path; provider and provider_id are legacy fallback inputs.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| slug | No | Preferred: tickadoo slug or path, e.g. 'london-dungeon-tickets' or '/london/london-dungeon-tickets' | |
| provider | No | Legacy fallback only: hidden provider name used internally | |
| provider_id | No | Legacy fallback only: hidden provider-specific product ID | |
| days | No | Number of days of availability to fetch (default 30, max 180) | |
| language | No | Reserved for future language-aware API support | en |
Implementation Reference
- src/shared/server.ts:201-248 (handler)The implementation of the `get_experience_details` MCP tool, which resolves an experience from a slug or ID and fetches its detailed data.
server.tool( "get_experience_details", "Get detailed availability, venue details, and images for a specific tickadoo® experience. Prefer passing the tickadoo slug or booking URL path; provider and provider_id are legacy fallback inputs.", { slug: z.string().optional().describe("Preferred: tickadoo slug or path, e.g. 'london-dungeon-tickets' or '/london/london-dungeon-tickets'"), provider: z.string().optional().describe("Legacy fallback only: hidden provider name used internally"), provider_id: z.string().optional().describe("Legacy fallback only: hidden provider-specific product ID"), days: z.number().int().min(1).max(180).optional().default(30).describe("Number of days of availability to fetch (default 30, max 180)"), language: z.string().optional().default("en").describe("Reserved for future language-aware API support"), }, READ_ONLY_TOOL_ANNOTATIONS, async ({ slug, provider, provider_id, days, language }) => { try { let resolved: ResolvedProduct | undefined; let providerName = provider; let providerId = provider_id; if (slug?.trim()) { resolved = await resolveProductBySlug(slug, language); providerName = resolved.product.provider; providerId = resolved.product.providerId; } else if (!providerName || !providerId) { return createTextResponse("Error: Provide a tickadoo slug (preferred) or both provider and provider_id.", { isError: true }); } const details = await getExperienceDetails(providerName, providerId, days); return createTextResponse( [ resolved ? `🎭 ${resolved.product.title}` : "", formatExperienceDetails(days, details), resolved ? ` 🔗 ${buildBookingUrl(resolved.bookingPath)}` : "", ].filter(Boolean).join("\n"), { structuredContent: { source: "tickadoo", slug: resolved?.product.slug, tickadooProductId: resolved?.product.id, bookingUrl: resolved ? buildBookingUrl(resolved.bookingPath) : undefined, days, details, }, }, ); } catch (error) { return createTextResponse(`Error: ${getErrorMessage(error)}`, { isError: true }); } }, ); - src/shared/api.ts:236-246 (handler)The underlying API function that fetches the structured experience data from the backend.
export async function getExperienceDetails( provider: string, providerId: string, days: number, ): Promise<StructuredDataResponse> { return fetchJson<StructuredDataResponse>("/api/products/structured-data", { Provider: normalizeProviderName(provider), Id: providerId, Days: days.toString(), }); }