geocode
Convert addresses, place names, or points of interest into geographic coordinates and contextual location data using the Stadia Maps Location API.
Instructions
Look up a street address, POI, or area. Returned geographic information includes coordinates, bounding box, local context (what country, city, etc. is it in).. Additional info may include Wikipedia ID, population, opening hours, website, and more, subject to availability.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The address or place name to search for. Use local formatting and order when possible. When searching for a POI name (e.g. 'Starbucks'), you will get better results with a focus point and filters. Avoid spelling out precise locations (e.g. 'Starbucks, Downtown Greenville'); this is acceptable for large areas though (e.g. 'Paris, France' is OK, as is 'Louvre, Paris'). Make multiple queries or use general knowledge when necessary to identify the correct non-textual filters. | |
| countryFilter | No | ||
| lang | Yes | A BCP-47 language tag (may just be the language) to localize the results in (e.g. en, de, et). | |
| focusPoint | No | Geographic coordinates to focus the search around. Provide this whenever possible. | |
| layer | No | The layer to search in. Coarse searches for areas such as neighborhoods, cities, states, and countries, AND a specific layer is not available. Address searches for street addresses. Country is what you expect. Localities are what we would colloquially refer to as a 'city', town, or village. Region is for first-level subdivisions within countries like states, provinces, or whatever they are called locally. POI searches for points of interest including restaurants, parks, shops, and museums. Defaults to all layers if not specified. |
Implementation Reference
- src/tools/geocoding.ts:69-91 (handler)The primary handler function for the 'geocode' tool. It takes unstructured query parameters, calls the Stadia Maps Geocoding API's searchV2 endpoint, processes the response using geocodingToolResult, and handles errors.export async function geocode({ query, countryFilter, lang, layer, }: UnstructuredGeocodeParams): Promise<CallToolResult> { return handleToolError( async () => { const res = await geocodeApi.searchV2({ text: query, boundaryCountry: countryFilter, lang, layers: layer ? [layer as LayerId] : undefined, }); return geocodingToolResult(res); }, { contextMessage: "Geocoding failed", enableLogging: true, }, ); }
- src/index.ts:50-58 (registration)Registers the 'geocode' tool with the MCP server, providing the tool name, description, Zod input schema (composed from geocodingUnstructuredQuery and geocodingCommonSchema), and references the handler function.server.tool( "geocode", `Look up a street address, POI, or area. ${commonGeocodingDescription}. Additional info may include Wikipedia ID, population, opening hours, website, and more, subject to availability.`, { query: geocodingUnstructuredQuery, ...geocodingCommonSchema.shape, }, geocode, );
- src/schemas.ts:58-62 (schema)Zod schema for the 'query' parameter of the geocode tool, defining it as a required string with detailed usage description.export const geocodingUnstructuredQuery = z .string() .describe( "The address or place name to search for. Use local formatting and order when possible. When searching for a POI name (e.g. 'Starbucks'), you will get better results with a focus point and filters. Avoid spelling out precise locations (e.g. 'Starbucks, Downtown Greenville'); this is acceptable for large areas though (e.g. 'Paris, France' is OK, as is 'Louvre, Paris'). Make multiple queries or use general knowledge when necessary to identify the correct non-textual filters.", );
- src/schemas.ts:64-74 (schema)Zod schema defining common optional parameters for geocoding tools: countryFilter, lang, focusPoint, and layer.export const geocodingCommonSchema = z.object({ countryFilter: countryFilterSchema, lang: languageSchema, focusPoint: focusPointSchema, layer: z .enum(["address", "poi", "coarse", "country", "region", "locality"]) .describe( "The layer to search in. Coarse searches for areas such as neighborhoods, cities, states, and countries, AND a specific layer is not available. Address searches for street addresses. Country is what you expect. Localities are what we would colloquially refer to as a 'city', town, or village. Region is for first-level subdivisions within countries like states, provinces, or whatever they are called locally. POI searches for points of interest including restaurants, parks, shops, and museums. Defaults to all layers if not specified.", ) .optional(), });
- src/tools/geocoding.ts:20-67 (helper)Helper function that formats the Geocoding API response into a human-readable text output for the MCP tool result, including name, layer, geometry, location, bbox, and additional info.function geocodingToolResult( envelope: GeocodeResponseEnvelopePropertiesV2, ): CallToolResult { if (!envelope.features || !envelope.features.length) { return { content: [ { type: "text", text: "No results found.", }, ], }; } const res = envelope.features .map((feature) => { let location: string | null | undefined; if (feature.properties.formattedAddressLine) { location = feature.properties.formattedAddressLine; } else { location = feature.properties.coarseLocation; } // Format bounding box if available (GeoJSON bbox is [west, south, east, north]) const bboxInfo = feature.bbox ? `[${feature.bbox[0]}, ${feature.bbox[1]}, ${feature.bbox[2]}, ${feature.bbox[3]}]` : "N/A (point geometry)"; return [ `Name: ${feature.properties?.name}`, `Layer: ${feature.properties?.layer}`, `GeoJSON Geometry: ${JSON.stringify(feature.geometry)}`, `Location: ${location || "unknown"}`, `Bounding Box (W, S, E, N): ${bboxInfo}`, `Additional information: ${JSON.stringify(feature.properties.addendum)}`, ].join("\n"); }) .join("\n---\n"); return { content: [ { type: "text", text: `Results:\n---\n${res}`, }, ], }; }