places-search
Search for places using text queries with location and radius parameters to find relevant results from Google Maps data.
Instructions
Search for places using text query
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The search query | |
| location | No | Bias results around this location (e.g., 'lat,lng') | |
| radius | No | Search radius in meters |
Implementation Reference
- src/maps.ts:261-329 (handler)The main handler function for the 'places-search' tool. It uses Google Maps Text Search API to find places matching the query, optionally biased by location and radius. Formats up to 5 results using formatPlacesToMarkdown and returns as MCP content.
export async function placesSearch( params: z.infer<typeof placesSearchSchema>, extra?: any ) { const apiKey = process.env.GOOGLE_MAPS_API_KEY; if (!apiKey) { throw new Error("GOOGLE_MAPS_API_KEY is required"); } try { const requestParams: any = { query: params.query, key: apiKey, }; if (params.location) { requestParams.location = params.location; } if (params.radius) { requestParams.radius = params.radius; } const response = await googleMapsClient.textSearch({ params: requestParams, }); const results = response.data.results; if (results.length === 0) { return { content: [ { type: "text" as const, text: "No places found for the given query.", }, ], }; } const places = results.slice(0, 5).map((place) => ({ name: place.name, formatted_address: place.formatted_address, latitude: place.geometry?.location.lat, longitude: place.geometry?.location.lng, place_id: place.place_id, rating: place.rating, types: place.types, })); return { content: [ { type: "text" as const, text: formatPlacesToMarkdown(places), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error searching places: ${ error instanceof Error ? error.message : String(error) }`, }, ], }; } } - src/maps.ts:114-121 (schema)Zod schema for input validation of the places-search tool: required 'query' string, optional 'location' string (lat,lng), and 'radius' number.
export const placesSearchSchema = z.object({ query: z.string().describe("The search query"), location: z .string() .optional() .describe("Bias results around this location (e.g., 'lat,lng')"), radius: z.number().optional().describe("Search radius in meters"), }); - src/index.ts:80-87 (registration)Tool registration in the MCP server, using the placesSearch handler and placesSearchSchema from maps.ts.
server.tool( "places-search", "Search for places using text query", placesSearchSchema.shape, async (params) => { return await placesSearch(params); } ); - src/maps.ts:16-38 (helper)Helper function used by placesSearch to format search results into a Markdown list with details like name, address, rating, location, and place ID.
function formatPlacesToMarkdown(places: any[]): string { if (!places.length) return "No places found."; let markdown = `# Places Search Results (${places.length})\n\n`; places.forEach((place, index) => { markdown += `## ${index + 1}. ${place.name}\n`; markdown += `Address: ${place.formatted_address} \n`; if (place.rating) { markdown += `Rating: ${place.rating}⭐ \n`; } if (place.latitude && place.longitude) { markdown += `Location: ${place.latitude}, ${place.longitude} \n`; markdown += `Maps: [View](https://maps.google.com/?q=${place.latitude},${place.longitude}) \n`; } if (place.place_id) { markdown += `Place ID: \`${place.place_id}\` \n`; } markdown += `\n`; }); return markdown; }