place-search
Find campgrounds and outdoor accommodations with specific amenities, availability dates, and location filters for camping trips.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Number of places to return. Default is 50, max is 1000. | |
| startDate | No | Start date for availability search. Format: YYYY-MM-DD | |
| endDate | No | End date for availability search. Format: YYYY-MM-DD | |
| adults | No | Number of adults. Default is 1. | |
| children | No | Number of children. Default is 0. | |
| latitude | No | Latitude to filter by. | |
| longitude | No | Longitude to filter by. | |
| radius | No | Radius to filter by (in km). | |
| filters | No | Filter out places that have specific tags. | |
| campgroundDescription | No | Describe the campground you are looking for. Note: not the location, but something about the campground like "has a pool" or "near a lake" or "has a playground" |
Implementation Reference
- src/tools/place_search.ts:74-98 (handler)The handler function that builds query parameters from inputs and fetches search results from the Campertunity API endpoint `/place/search`, returning JSON or error.async ({ limit, startDate, endDate, adults, children, latitude, longitude, radius, filters, campgroundDescription }) => { try { const params = new URLSearchParams(); if (limit) params.set('limit', limit.toString()); if (startDate) params.set('startDate', startDate); if (endDate) params.set('endDate', endDate); if (adults) params.set('adults', adults.toString()); if (children) params.set('children', children.toString()); if (latitude) params.set('latitude', latitude.toString()); if (longitude) params.set('longitude', longitude.toString()); if (radius) params.set('radius', radius.toString()); if (filters) params.set('filters', filters.join(',')); if (campgroundDescription) params.set('campgroundDescription', campgroundDescription); const places = await campertunityClient.get(`/place/search?${params.toString()}`); return { content: [{ type: 'text', text: JSON.stringify(places), mimeType: 'application/json' }], }; } catch (error) { return { content: [{ type: 'text', text: 'Error: ' + (error as Error).message }], isError: true, }; } }
- src/tools/place_search.ts:62-73 (schema)Zod input schema defining parameters for the place search tool, including limits, dates, location filters, and tags.{ limit: z.number().default(50).optional().describe('Number of places to return. Default is 50, max is 1000.'), startDate: z.string().optional().describe('Start date for availability search. Format: YYYY-MM-DD'), endDate: z.string().optional().describe('End date for availability search. Format: YYYY-MM-DD'), adults: z.number().optional().describe('Number of adults. Default is 1.'), children: z.number().optional().describe('Number of children. Default is 0.'), latitude: z.number().optional().describe('Latitude to filter by.'), longitude: z.number().optional().describe('Longitude to filter by.'), radius: z.number().optional().default(20).describe('Radius to filter by (in km).'), filters: z.array(z.enum(Object.values(Tag) as [string, ...string[]])).optional().describe('Filter out places that have specific tags.'), campgroundDescription: z.string().optional().describe('Describe the campground you are looking for. Note: not the location, but something about the campground like "has a pool" or "near a lake" or "has a playground"'), },
- src/tools/place_search.ts:60-99 (registration)The server.tool call that registers the 'place-search' tool with its schema and handler function.server.tool( 'place-search', { limit: z.number().default(50).optional().describe('Number of places to return. Default is 50, max is 1000.'), startDate: z.string().optional().describe('Start date for availability search. Format: YYYY-MM-DD'), endDate: z.string().optional().describe('End date for availability search. Format: YYYY-MM-DD'), adults: z.number().optional().describe('Number of adults. Default is 1.'), children: z.number().optional().describe('Number of children. Default is 0.'), latitude: z.number().optional().describe('Latitude to filter by.'), longitude: z.number().optional().describe('Longitude to filter by.'), radius: z.number().optional().default(20).describe('Radius to filter by (in km).'), filters: z.array(z.enum(Object.values(Tag) as [string, ...string[]])).optional().describe('Filter out places that have specific tags.'), campgroundDescription: z.string().optional().describe('Describe the campground you are looking for. Note: not the location, but something about the campground like "has a pool" or "near a lake" or "has a playground"'), }, async ({ limit, startDate, endDate, adults, children, latitude, longitude, radius, filters, campgroundDescription }) => { try { const params = new URLSearchParams(); if (limit) params.set('limit', limit.toString()); if (startDate) params.set('startDate', startDate); if (endDate) params.set('endDate', endDate); if (adults) params.set('adults', adults.toString()); if (children) params.set('children', children.toString()); if (latitude) params.set('latitude', latitude.toString()); if (longitude) params.set('longitude', longitude.toString()); if (radius) params.set('radius', radius.toString()); if (filters) params.set('filters', filters.join(',')); if (campgroundDescription) params.set('campgroundDescription', campgroundDescription); const places = await campertunityClient.get(`/place/search?${params.toString()}`); return { content: [{ type: 'text', text: JSON.stringify(places), mimeType: 'application/json' }], }; } catch (error) { return { content: [{ type: 'text', text: 'Error: ' + (error as Error).message }], isError: true, }; } } );
- src/index.ts:26-26 (registration)Invocation of placeSearchTool to register the tool on the MCP server.placeSearchTool(server, campertunityClient);
- src/tools/place_search.ts:5-57 (helper)Enum defining all possible tags for filtering places, used in the schema for filters parameter.export enum Tag { // SiteType tent = 'tent', rv = 'rv', lodging = 'lodging', glamping = 'glamping', cabin = 'cabin', // AccessType driveIn = 'driveIn', walkIn = 'walkIn', equestrian = 'equestrian', boat = 'boat', // Activities biking = 'biking', boating = 'boating', fishing = 'fishing', hiking = 'hiking', horsebackRiding = 'horsebackRiding', paddling = 'paddling', windSports = 'windSports', surfing = 'surfing', swimming = 'swimming', whitewaterPaddling = 'whitewaterPaddling', wildlifeWatching = 'wildlifeWatching', // Amenities picnicTable = 'picnicTable', fires = 'fires', toilets = 'toilets', outhouse = 'outhouse', potableWater = 'potableWater', petFriendly = 'petFriendly', rvHookup = 'rvHookup', rvSanitation = 'rvSanitation', trash = 'trash', showers = 'showers', wifi = 'wifi', handicap = 'handicap', // Terrain beach = 'beach', cave = 'cave', desert = 'desert', forest = 'forest', hotSpring = 'hotSpring', lake = 'lake', river = 'river', swimmingHole = 'swimmingHole', waterfall = 'waterfall', creek = 'creek', }