Skip to main content
Glama
stadiamaps

Stadia Maps Location API MCP Server

bulk-geocode

Geocode multiple addresses in a single request and retrieve results as a JSON list with coordinates, bounding box, and local context information. Best suited for address-based searches, not POIs.

Instructions

Perform multiple address geocoding operations in a single request. Returns results as a JSON list, showing only the first result for each. Using this to geocode POIs is strongly discouraged, as many places with the same name exist; only use this for addresses. Returned geographic information includes coordinates, bounding box, local context (what country, city, etc. is it in).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
itemsYesArray of geocoding items to process in bulk.

Implementation Reference

  • The primary handler function for the 'bulk-geocode' tool. It constructs bulk geocoding requests from the input items, calls the Stadia Maps bulk geocoding API, and formats the results using bulkGeocodingToolResult.
    export async function bulkGeocode({ items, }: BulkUnstructuredGeocodeParams): Promise<CallToolResult> { if (!items || items.length === 0) { return { content: [ { type: "text", text: "No geocoding items provided.", }, ], }; } // All items are valid by type definition (query is required) const bulkRequests = items.map((item) => { const request: BulkRequest = { endpoint: BulkRequestEndpointEnum.V1Search, }; // Unstructured query request.query = { text: item.query, focusPointLat: item.focusPoint?.lat, focusPointLon: item.focusPoint?.lon, boundaryCountry: item.countryFilter, lang: item.lang, }; return request; }); return handleToolError( async () => { const responses = await geocodeApi.searchBulk({ bulkRequest: bulkRequests, }); return bulkGeocodingToolResult(responses, []); }, { contextMessage: "Error performing bulk unstructured geocoding", enableLogging: true, }, ); }
  • src/index.ts:63-78 (registration)
    Registers the 'bulk-geocode' tool with the MCP server, defining its name, description, input schema (array of unstructured geocoding queries), and linking to the bulkGeocode handler.
    server.tool( "bulk-geocode", `Perform multiple address geocoding operations in a single request. Returns results as a JSON list, showing only the first result for each. Using this to geocode POIs is strongly discouraged, as many places with the same name exist; only use this for addresses. ${commonGeocodingDescription}`, { items: z .array( z.object({ query: geocodingUnstructuredQuery, ...geocodingCommonSchema.shape, }), ) .min(1) .describe("Array of geocoding items to process in bulk."), }, bulkGeocode, );
  • Helper function to process and format the results from bulk geocoding API responses into a structured JSON output for the tool response.
    function bulkGeocodingToolResult( responses: Array<BulkSearchResponse>, invalidItems: Array<{ item: BulkGeocodeItemType; error: string }> = [], ): CallToolResult { // Filter out any failed requests and extract the features const successfulResults = responses .filter( (response) => response.status === 200 && response.response?.features && response.response.features.length > 0, ) .flatMap((response) => { if (!response.response) return []; return response.response.features .map((feature) => { return { label: feature.properties?.label, geometry: feature.geometry, matchType: feature.properties?.matchType, addendum: feature.properties?.addendum, bbox: feature.bbox, }; // Slice to keep only the first element in the array; // we request a few more to enable dedupe, but only keep the first one. }) .slice(0, 1); }); // Get failed responses const failedResponses = responses .filter( (response) => response.status !== 200 || !response.response?.features?.length, ) .map((response) => ({ status: response.status, message: response.msg || "No results found", })); // Combine all results const result = { results: successfulResults, metadata: { totalRequests: responses.length + invalidItems.length, successfulRequests: successfulResults.length, failedRequests: failedResponses.length, invalidItems: invalidItems.length > 0 ? invalidItems.map((i) => ({ item: i.item, error: i.error, })) : undefined, }, }; return { content: [ { type: "text", text: JSON.stringify(result), }, ], }; }
  • Zod schema for common geocoding parameters (countryFilter, lang, focusPoint, layer), used in the input schema for each item in bulk-geocode.
    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(), });
  • Zod schema for the unstructured query string parameter, required for each geocoding item in bulk-geocode.
    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.", );

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stadiamaps/stadiamaps-mcp-server-ts'

If you have feedback or need assistance with the MCP directory API, please join our Discord server