Skip to main content
Glama
stadiamaps

Stadia Maps Location API MCP Server

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
NameRequiredDescriptionDefault
queryYesThe 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.
countryFilterNo
langYesA BCP-47 language tag (may just be the language) to localize the results in (e.g. en, de, et).
focusPointNoGeographic coordinates to focus the search around. Provide this whenever possible.
layerNoThe 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

  • 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,
    );
  • 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.",
      );
  • 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(),
    });
  • 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}`,
          },
        ],
      };
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes what the tool returns (coordinates, bounding box, local context, and additional info like Wikipedia ID) and mentions that information is 'subject to availability,' which adds useful context about potential variability. However, it doesn't cover important behavioral aspects like rate limits, authentication needs, error conditions, or whether it's a read-only operation (though 'look up' implies non-destructive).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded: the first sentence states the core purpose and return values, and the second sentence adds supplementary information about additional data. Every sentence earns its place with no wasted words, making it efficient and easy to understand.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (5 parameters, nested objects, no output schema), the description is reasonably complete. It explains what the tool does and what information it returns, which is adequate for a geocoding function. However, without annotations or an output schema, it could benefit from more detail about the structure of returned data or error handling, though the high schema coverage helps compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 80%, which is high, so the baseline is 3 even though the description doesn't add parameter-specific information. The description mentions the types of queries (street address, POI, area) which aligns with the 'query' parameter, but doesn't provide additional semantic context beyond what's already documented in the detailed schema descriptions for each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('look up') and resources ('street address, POI, or area'), and distinguishes it from siblings by focusing on single-location geocoding (vs. bulk-geocode for multiple locations). It explicitly lists the types of information returned, making the function unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool (for looking up addresses, POIs, or areas to get geographic information), but doesn't explicitly mention when not to use it or name alternatives. It implies usage for single queries rather than bulk operations, which differentiates it from 'bulk-geocode', but lacks explicit exclusions or comparisons to other siblings like 'isochrone' or 'route-overview'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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