Skip to main content
Glama
stadiamaps

Stadia Maps Location API MCP Server

static-map

Generate PNG map images with customizable markers and route lines for visualizing locations and paths using Stadia Maps styles.

Instructions

Generate a PNG map image of an area, optionally including markers and a line (e.g. to draw a route or a boundary)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
styleNoThe Stadia Maps style slug to use.outdoors
encodedPolylineNoThe encoded polyline representing the route (precision 6). Optional, but either markers or a polyline must be specified.
strokeColorNoOptional color for the polyline (hex code or CSS color name; e.g. FFFFFF or blue).
strokeWidthNoOptional width for the route line in pixels.
markersNoMarkers to add to the map. Optional, but either markers or a polyline must be specified.

Implementation Reference

  • Main handler function for 'static-map' tool. Constructs payload for Stadia Maps Static API, including optional encoded polyline (route line) and markers, then calls helper to fetch and return base64 PNG image.
    export async function staticMap({
      style = DEFAULT_STYLE,
      encodedPolyline,
      strokeColor,
      strokeWidth,
      markers,
    }: StaticMapParams): Promise<CallToolResult> {
      const payload: any = {
        // Fixed at 600x400; customize as needed
        size: "600x400@2x",
        lines: [],
      };
    
      // Add line if provided
      if (encodedPolyline) {
        // Create the line object
        const line: any = {
          shape: encodedPolyline,
        };
    
        // Add optional line properties if provided
        if (strokeColor) line.stroke_color = strokeColor;
        if (strokeWidth) line.stroke_width = strokeWidth;
    
        payload.lines.push(line);
      }
    
      // Add markers if provided
      if (markers && markers.length > 0) {
        payload.markers = markers.map((marker) => {
          const markerObj: any = {
            lat: marker.lat,
            lon: marker.lon,
          };
    
          if (marker.label) markerObj.label = marker.label;
          if (marker.color) markerObj.color = marker.color;
          if (marker.markerUrl) markerObj.style = `custom:${marker.markerUrl}`;
    
          return markerObj;
        });
      }
    
      return generateStaticMapAsCallToolResult(payload, style);
    }
  • src/index.ts:104-140 (registration)
    MCP server tool registration for 'static-map', defining input schema using Zod and linking to staticMap handler.
      "static-map",
      "Generate a PNG map image of an area, optionally including markers and a line (e.g. to draw a route or a boundary)",
      {
        style: mapStyleSchema,
        encodedPolyline: z
          .string()
          .describe(
            "The encoded polyline representing the route (precision 6). Optional, but either markers or a polyline must be specified.",
          )
          .optional(),
        strokeColor: z
          .string()
          .describe(
            "Optional color for the polyline (hex code or CSS color name; e.g. FFFFFF or blue).",
          )
          .optional(),
        strokeWidth: z
          .number()
          .describe("Optional width for the route line in pixels.")
          .optional(),
        markers: z
          .array(
            z.object({
              lat: latitudeSchema,
              lon: longitudeSchema,
              label: markerLabelSchema,
              color: markerColorSchema,
              markerStyle: markerStyleSchema,
            }),
          )
          .describe(
            "Markers to add to the map. Optional, but either markers or a polyline must be specified.",
          )
          .optional(),
      },
      staticMap,
    );
  • Helper function to POST payload to Stadia Maps Static API, fetch PNG image, convert to base64, and return as MCP CallToolResult.
    async function generateStaticMapAsCallToolResult(
      payload: any,
      style: string,
    ): Promise<CallToolResult> {
      return handleToolError(
        async () => {
          const url = `${STATIC_MAPS_BASE_URL}/${style}?api_key=${API_KEY}`;
    
          const response = await fetch(url, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
            },
            body: JSON.stringify(payload),
          });
    
          if (!response.ok) {
            throw new Error(
              `HTTP code: ${response.status}.\nPayload: ${JSON.stringify(payload)}`,
            );
          }
    
          // Get the image as a buffer
          const imageBuffer = await response.arrayBuffer();
    
          // Convert to base64
          const base64Image = Buffer.from(imageBuffer).toString("base64");
    
          return {
            content: [
              {
                type: "image",
                data: base64Image,
                mimeType: "image/png",
              },
            ],
          };
        },
        {
          contextMessage: "Failed to generate static map",
          enableLogging: true,
        },
      );
    }
  • Zod schema for map style parameter used in static-map tool.
    export const mapStyleSchema = z
      // See https://docs.stadiamaps.com/themes/ for more styles!
      .enum(["outdoors", "alidade_smooth", "alidade_smooth_dark"])
      .describe("The Stadia Maps style slug to use.")
      .default(DEFAULT_STYLE);
  • Zod schemas for marker properties (label, color, style) used in static-map markers array.
    export const markerLabelSchema = z
      .string()
      .describe(
        "Optional label for the marker. This must be either a single character or supported emoji (most emoji work).",
      )
      .optional();
    
    export const markerColorSchema = z
      .string()
      .describe(
        "Optional color for the marker (hex code or CSS color name; no quoting and no # prefix).",
      )
      .optional();
    
    export const markerStyleSchema = z
      .string()
      .describe("Optional custom marker style or URL to a custom marker image.")
      .optional();
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. It states the tool generates a PNG image but doesn't mention output format details, size limitations, rate limits, authentication needs, or error conditions. The description is minimal and lacks crucial behavioral context for a tool that produces visual output.

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 a single, efficient sentence that front-loads the core purpose ('Generate a PNG map image') and includes essential optional features. Every word earns its place with zero waste or redundancy.

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

Completeness2/5

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

For a tool with 5 parameters, no annotations, and no output schema, the description is insufficient. It doesn't explain what the PNG output contains, how large images can be, coordinate system details, or error handling. The description leaves too many behavioral aspects undefined given the tool's complexity.

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 100%, so the schema already documents all 5 parameters thoroughly. The description adds marginal value by mentioning 'markers and a line' which corresponds to the 'markers' and 'encodedPolyline' parameters, but doesn't provide additional semantic context beyond what's in the schema. Baseline 3 is appropriate when schema does the heavy lifting.

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: 'Generate a PNG map image of an area' with specific optional features ('including markers and a line'). It distinguishes from siblings like 'geocode' (address conversion) and 'route-overview' (likely textual routing) by focusing on visual map generation.

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

Usage Guidelines3/5

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

The description implies usage through examples ('e.g. to draw a route or a boundary'), but doesn't explicitly state when to use this versus alternatives like 'route-overview' or 'isochrone'. It mentions that either markers or a polyline must be specified, which provides some contextual guidance but lacks explicit sibling differentiation.

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