UNPKG

tripadvisor-mcp-node

Version:

MCP server for TripAdvisor restaurant search

156 lines (155 loc) 6.42 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; const TRIPADVISOR_API_KEY = process.env.TRIPADVISOR_API_KEY || ''; const BASE_URL = 'https://api.content.tripadvisor.com/api/v1'; const REFERER = process.env.TRIPADVISOR_REFERER || ''; const ORIGIN = process.env.TRIPADVISOR_ORIGIN || ''; async function makeApiRequest(endpoint, params = {}) { if (!TRIPADVISOR_API_KEY) { throw new Error('Tripadvisor API key is missing. Please set TRIPADVISOR_API_KEY environment variable.'); } const url = new URL(`${BASE_URL}/${endpoint}`); params.key = TRIPADVISOR_API_KEY; Object.entries(params).forEach(([k, v]) => { if (v !== undefined && v !== null) url.searchParams.append(k, String(v)); }); const res = await fetch(url.toString(), { headers: { accept: 'application/json', referer: REFERER, origin: ORIGIN } }); if (!res.ok) throw new Error(await res.text()); return res.json(); } // 创建 MCP server const server = new Server({ name: 'Tripadvisor Content API MCP', version: '1.0.0' }, { capabilities: { tools: {} } }); // 定义搜索地点的参数schema const searchLocationsSchema = z.object({ searchQuery: z.string(), language: z.string().default('en'), category: z.string().optional(), phone: z.string().optional(), address: z.string().optional(), latLong: z.string().optional() }); // 定义搜索附近地点的参数schema const searchNearbyLocationsSchema = z.object({ latitude: z.number(), longitude: z.number(), language: z.string().default('en'), category: z.string().optional() }); // 定义地点详情的参数schema const locationDetailsSchema = z.object({ locationId: z.union([z.string(), z.number()]), language: z.string().default('en') }); // 监听工具列表请求 server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'search_locations', description: 'Search for locations on TripAdvisor', inputSchema: zodToJsonSchema(searchLocationsSchema) }, { name: 'search_nearby_locations', description: 'Search for nearby locations on TripAdvisor', inputSchema: zodToJsonSchema(searchNearbyLocationsSchema) }, { name: 'get_location_details', description: 'Get detailed information about a specific location', inputSchema: zodToJsonSchema(locationDetailsSchema) }, { name: 'get_location_reviews', description: 'Get reviews for a specific location', inputSchema: zodToJsonSchema(locationDetailsSchema) }, { name: 'get_location_photos', description: 'Get photos for a specific location', inputSchema: zodToJsonSchema(locationDetailsSchema) } ] }; }); // 监听工具调用请求 server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'search_locations': { const { searchQuery, language, category, phone, address, latLong } = searchLocationsSchema.parse(args); const params = { searchQuery, language }; if (category) params.category = category; if (phone) params.phone = phone; if (address) params.address = address; if (latLong) params.latLong = latLong; const data = await makeApiRequest('location/search', params); return { content: [{ type: 'json', json: data }] }; } case 'search_nearby_locations': { const { latitude, longitude, language, category } = searchNearbyLocationsSchema.parse(args); const params = { latLong: `${latitude},${longitude}`, language }; if (category) params.category = category; const data = await makeApiRequest('location/search', params); return { content: [{ type: 'json', json: data }] }; } case 'get_location_details': { const { locationId, language } = locationDetailsSchema.parse(args); const params = { language }; const location_id_str = String(locationId); const data = await makeApiRequest(`location/${location_id_str}/details`, params); return { content: [{ type: 'json', json: data }] }; } case 'get_location_reviews': { const { locationId, language } = locationDetailsSchema.parse(args); const params = { language }; const location_id_str = String(locationId); const data = await makeApiRequest(`location/${location_id_str}/reviews`, params); return { content: [{ type: 'json', json: data }] }; } case 'get_location_photos': { const { locationId, language } = locationDetailsSchema.parse(args); const params = { language }; const location_id_str = String(locationId); const data = await makeApiRequest(`location/${location_id_str}/photos`, params); return { content: [{ type: 'json', json: data }] }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { throw new Error(`Error calling tool ${name}: ${error instanceof Error ? error.message : String(error)}`); } }); // 启动 MCP server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('Tripadvisor MCP Server running on stdio'); } main().catch(console.error);