Skip to main content
Glama
blake365

Macrostrat MCP Server

by blake365

Map Tiles

map-tiles

Retrieve map tile URLs from Macrostrat's geological database to visualize geological features at specified coordinates and zoom levels.

Instructions

Get map tile URLs from the Macrostrat tiles server. Use lat-lng-to-tile tool first to get proper x,y coordinates. Defaults to 'carto' scale which automatically adapts detail level to zoom.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
scaleNoMap scale layer - 'carto' automatically selects appropriate detail level based on zoom. Other scales (tiny, small, medium, large) may have limited coverage.carto
zYesZoom level (0-18). Higher zoom = more detailed view of smaller area. Typical values: z=3 (continent), z=6 (country), z=10 (city), z=15 (neighborhood)
xYesTile X coordinate - use lat-lng-to-tile tool to calculate this from lat/lng
yYesTile Y coordinate - use lat-lng-to-tile tool to calculate this from lat/lng
formatNoTile format: 'png' for images, 'mvt' for vector tilespng
fetch_imageNoIf true, actually fetch the tile image data so Claude can analyze the geological features visually

Implementation Reference

  • The handler function for the 'map-tiles' tool. It takes parameters like scale, z (zoom), x, y coordinates, format, and fetch_image flag. Constructs the tile URL from Macrostrat server. If fetch_image is true and format png, fetches the image, converts to base64, and returns both text metadata and image content for analysis. Otherwise or on error, returns text with URL and info.
    async (request) => {
      const { scale, z, x, y, format, fetch_image } = request;
      const tileUrl = `https://tiles.macrostrat.org/${scale}/${z}/${x}/${y}.${format}`;
      
      if (fetch_image && format === "png") {
        try {
          const response = await fetch(tileUrl);
          if (response.ok) {
            const buffer = await response.arrayBuffer();
            const base64 = Buffer.from(buffer).toString('base64');
            
            // Return both text info and image content
            return {
              content: [
                { 
                  type: "text" as const, 
                  text: JSON.stringify({
                    url: tileUrl,
                    scale,
                    z,
                    x,
                    y,
                    format,
                    info: {
                      layers: ["units", "lines"],
                      description: scale === "carto" 
                        ? "Adaptive geological map that selects appropriate detail level based on zoom"
                        : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
                      license: "CC BY 4.0 International",
                      attribution: "Macrostrat and original data providers",
                      note: "Geological map tile image provided below for visual analysis"
                    }
                  }, null, 2)
                },
                {
                  type: "image" as const,
                  data: base64,
                  mimeType: "image/png"
                },
              ],
            };
          } else {
            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
          }
        } catch (error) {
          console.error("Error fetching tile image:", error);
          const data = {
            url: tileUrl,
            scale,
            z,
            x,
            y,
            format,
            error: `Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`,
            info: {
              layers: ["units", "lines"],
              description: scale === "carto" 
                ? "Adaptive geological map that selects appropriate detail level based on zoom"
                : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
              license: "CC BY 4.0 International",
              attribution: "Macrostrat and original data providers"
            }
          };
          
          return {
            content: [{
              type: "text" as const,
              text: JSON.stringify(data, null, 2)
            }]
          };
        }
      } else {
        const data = {
          url: tileUrl,
          scale,
          z,
          x,
          y,
          format,
          info: {
            layers: ["units", "lines"],
            description: scale === "carto" 
              ? "Adaptive geological map that selects appropriate detail level based on zoom"
              : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
            license: "CC BY 4.0 International",
            attribution: "Macrostrat and original data providers"
          }
        };
    
        return {
          content: [{
            type: "text" as const,
            text: JSON.stringify(data, null, 2)
          }]
        };
      }
    }
  • Input schema definition for the map-tiles tool using Zod, defining parameters: scale (enum with default 'carto'), z (zoom 0-18), x/y (tile coords), format (mvt/png default png), fetch_image (bool default false). Includes title and description.
    {
      title: "Map Tiles",
      description: "Get map tile URLs from the Macrostrat tiles server. Use lat-lng-to-tile tool first to get proper x,y coordinates. Defaults to 'carto' scale which automatically adapts detail level to zoom.",
      inputSchema: {
        scale: z.enum(["carto", "tiny", "small", "medium", "large"]).default("carto").describe("Map scale layer - 'carto' automatically selects appropriate detail level based on zoom. Other scales (tiny, small, medium, large) may have limited coverage."),
        z: z.number().int().min(0).max(18).describe("Zoom level (0-18). Higher zoom = more detailed view of smaller area. Typical values: z=3 (continent), z=6 (country), z=10 (city), z=15 (neighborhood)"),
        x: z.number().int().min(0).describe("Tile X coordinate - use lat-lng-to-tile tool to calculate this from lat/lng"),
        y: z.number().int().min(0).describe("Tile Y coordinate - use lat-lng-to-tile tool to calculate this from lat/lng"),
        format: z.enum(["mvt", "png"]).default("png").describe("Tile format: 'png' for images, 'mvt' for vector tiles"),
        fetch_image: z.boolean().default(false).describe("If true, actually fetch the tile image data so Claude can analyze the geological features visually"),
      }
    },
  • src/index.ts:1123-1234 (registration)
    Registration of the 'map-tiles' tool with the MCP server using server.registerTool, including name, schema, and inline anonymous handler function.
    server.registerTool(
      "map-tiles",
      {
        title: "Map Tiles",
        description: "Get map tile URLs from the Macrostrat tiles server. Use lat-lng-to-tile tool first to get proper x,y coordinates. Defaults to 'carto' scale which automatically adapts detail level to zoom.",
        inputSchema: {
          scale: z.enum(["carto", "tiny", "small", "medium", "large"]).default("carto").describe("Map scale layer - 'carto' automatically selects appropriate detail level based on zoom. Other scales (tiny, small, medium, large) may have limited coverage."),
          z: z.number().int().min(0).max(18).describe("Zoom level (0-18). Higher zoom = more detailed view of smaller area. Typical values: z=3 (continent), z=6 (country), z=10 (city), z=15 (neighborhood)"),
          x: z.number().int().min(0).describe("Tile X coordinate - use lat-lng-to-tile tool to calculate this from lat/lng"),
          y: z.number().int().min(0).describe("Tile Y coordinate - use lat-lng-to-tile tool to calculate this from lat/lng"),
          format: z.enum(["mvt", "png"]).default("png").describe("Tile format: 'png' for images, 'mvt' for vector tiles"),
          fetch_image: z.boolean().default(false).describe("If true, actually fetch the tile image data so Claude can analyze the geological features visually"),
        }
      },
      async (request) => {
        const { scale, z, x, y, format, fetch_image } = request;
        const tileUrl = `https://tiles.macrostrat.org/${scale}/${z}/${x}/${y}.${format}`;
        
        if (fetch_image && format === "png") {
          try {
            const response = await fetch(tileUrl);
            if (response.ok) {
              const buffer = await response.arrayBuffer();
              const base64 = Buffer.from(buffer).toString('base64');
              
              // Return both text info and image content
              return {
                content: [
                  { 
                    type: "text" as const, 
                    text: JSON.stringify({
                      url: tileUrl,
                      scale,
                      z,
                      x,
                      y,
                      format,
                      info: {
                        layers: ["units", "lines"],
                        description: scale === "carto" 
                          ? "Adaptive geological map that selects appropriate detail level based on zoom"
                          : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
                        license: "CC BY 4.0 International",
                        attribution: "Macrostrat and original data providers",
                        note: "Geological map tile image provided below for visual analysis"
                      }
                    }, null, 2)
                  },
                  {
                    type: "image" as const,
                    data: base64,
                    mimeType: "image/png"
                  },
                ],
              };
            } else {
              throw new Error(`HTTP ${response.status}: ${response.statusText}`);
            }
          } catch (error) {
            console.error("Error fetching tile image:", error);
            const data = {
              url: tileUrl,
              scale,
              z,
              x,
              y,
              format,
              error: `Failed to fetch image: ${error instanceof Error ? error.message : String(error)}`,
              info: {
                layers: ["units", "lines"],
                description: scale === "carto" 
                  ? "Adaptive geological map that selects appropriate detail level based on zoom"
                  : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
                license: "CC BY 4.0 International",
                attribution: "Macrostrat and original data providers"
              }
            };
            
            return {
              content: [{
                type: "text" as const,
                text: JSON.stringify(data, null, 2)
              }]
            };
          }
        } else {
          const data = {
            url: tileUrl,
            scale,
            z,
            x,
            y,
            format,
            info: {
              layers: ["units", "lines"],
              description: scale === "carto" 
                ? "Adaptive geological map that selects appropriate detail level based on zoom"
                : `Maps from the "${scale}" scale (may have limited geographic coverage)`,
              license: "CC BY 4.0 International",
              attribution: "Macrostrat and original data providers"
            }
          };
    
          return {
            content: [{
              type: "text" as const,
              text: JSON.stringify(data, null, 2)
            }]
          };
        }
      }
    );
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 adds some context beyond the schema: it mentions the server ('Macrostrat tiles server'), the default scale behavior ('carto' automatically adapts detail level to zoom), and implies a dependency on another tool. However, it lacks details on rate limits, authentication needs, error handling, or what the URLs point to (e.g., endpoints, response format).

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: two sentences with zero waste. The first sentence states the core purpose, and the second provides critical usage guidance and default behavior. Every sentence earns its place by adding essential information not obvious from the tool name or schema alone.

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 (6 parameters, no output schema, no annotations), the description is reasonably complete. It covers the purpose, prerequisite tool, and default behavior, which are crucial for correct usage. However, it lacks details on what the returned URLs look like, potential errors, or server-specific constraints, leaving some gaps for an agent to infer.

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 parameters thoroughly. The description adds minimal value beyond the schema: it reinforces the default scale ('carto') and its adaptive behavior, but does not provide additional syntax, format details, or usage examples for parameters like 'fetch_image' or 'format'. Baseline 3 is appropriate when the 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 specific action ('Get map tile URLs') and resource ('from the Macrostrat tiles server'), distinguishing it from sibling tools like 'lat-lng-to-tile' which calculates coordinates rather than fetching tiles. It explicitly names the server and the type of output (URLs), making the purpose unambiguous.

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

Usage Guidelines5/5

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

The description provides explicit guidance on when to use this tool: 'Use lat-lng-to-tile tool first to get proper x,y coordinates.' It names the alternative tool ('lat-lng-to-tile') and specifies the prerequisite step, clearly differentiating usage contexts between coordinate calculation and tile retrieval.

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/blake365/macrostrat-mcp'

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