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
TableJSON 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; }