Skip to content

Latest commit

 

History

History
447 lines (341 loc) · 12.1 KB

importing-tools.md

File metadata and controls

447 lines (341 loc) · 12.1 KB

Importing Tools, Resources, and Prompts

This guide shows how to import and use Mapbox MCP Server components directly in your own applications, without running the full MCP server.

Overview

The Mapbox MCP Server exposes several subpath exports for direct integration:

  • @mapbox/mcp-server/tools - Geospatial tools (routing, search, geocoding, etc.)
  • @mapbox/mcp-server/resources - Static resources (category lists, etc.)
  • @mapbox/mcp-server/prompts - Pre-built prompts for common workflows
  • @mapbox/mcp-server/utils - HTTP pipeline utilities and server setup helpers

All exports support both ESM and CommonJS via dual builds powered by tshy.

Installation

npm install @mapbox/mcp-server

Usage Patterns

Simple: Pre-configured Instances

The easiest way to use tools is with pre-configured instances. These come with the HTTP pipeline already set up:

import {
  directions,
  searchAndGeocode,
  isochrone
} from '@mapbox/mcp-server/tools';

// Tools are ready to use immediately
const result = await directions.execute({
  coordinates: [
    [-122.4194, 37.7749], // San Francisco
    [-118.2437, 34.0522] // Los Angeles
  ],
  profile: 'driving-traffic'
});

Advanced: Custom Tool Instances

For more control, import tool classes and instantiate with your own configuration:

import { DirectionsTool, IsochroneTool } from '@mapbox/mcp-server/tools';
import { httpRequest } from '@mapbox/mcp-server/utils';

// Create tool instances with the default pipeline
const directions = new DirectionsTool({ httpRequest });
const isochrone = new IsochroneTool({ httpRequest });

Expert: Custom HTTP Pipeline

For full customization, create your own HTTP pipeline with custom policies:

import { DirectionsTool, SearchAndGeocodeTool } from '@mapbox/mcp-server/tools';
import {
  HttpPipeline,
  UserAgentPolicy,
  RetryPolicy,
  TracingPolicy
} from '@mapbox/mcp-server/utils';

// Create a custom pipeline
const pipeline = new HttpPipeline();

// Add custom policies
pipeline.usePolicy(new UserAgentPolicy('MyApp/2.0.0'));
pipeline.usePolicy(
  new RetryPolicy(
    5, // maxRetries
    300, // baseDelayMs
    3000 // maxDelayMs
  )
);
pipeline.usePolicy(new TracingPolicy());

// Add your own custom policy
pipeline.usePolicy({
  id: 'custom-auth',
  async handle(input, init, next) {
    // Add custom headers, logging, etc.
    const headers = new Headers(init.headers);
    headers.set('X-Custom-Header', 'value');

    return next(input, { ...init, headers });
  }
});

// Use the custom pipeline
const httpRequest = pipeline.execute.bind(pipeline);
const directions = new DirectionsTool({ httpRequest });
const search = new SearchAndGeocodeTool({ httpRequest });

Available Tools

Pre-configured Instances

Import ready-to-use tool instances:

import {
  // Geometry tools (no HTTP required)
  area,
  bearing,
  boundingBox,
  buffer,
  centroid,
  distance,
  midpoint,
  pointsWithinPolygon,
  simplify,

  // API tools (HTTP pre-configured)
  categorySearch,
  directions,
  feedback,
  isochrone,
  mapMatching,
  matrix,
  optimization,
  report,
  reverseGeocode,
  searchAndGeocode,
  staticMapImage,

  // Utility tools
  version
} from '@mapbox/mcp-server/tools';

Tool Classes

Import classes for custom instantiation:

import {
  // Geometry tools
  AreaTool,
  BearingTool,
  BoundingBoxTool,
  BufferTool,
  CentroidTool,
  DistanceTool,
  MidpointTool,
  PointsWithinPolygonTool,
  SimplifyTool,

  // API tools
  CategorySearchTool,
  DirectionsTool,
  IsochroneTool,
  MapMatchingTool,
  MatrixTool,
  OptimizationTool,
  ReverseGeocodeTool,
  SearchAndGeocodeTool,
  StaticMapImageTool,

  // Utility tools
  VersionTool
} from '@mapbox/mcp-server/tools';

Registry Functions

For batch access to tools:

import {
  getCoreTools,
  getElicitationTools,
  getResourceFallbackTools,
  getToolByName
} from '@mapbox/mcp-server/tools';

// Get all core tools
const coreTools = getCoreTools();

// Find a specific tool by name
const directionsTool = getToolByName('directions_tool');

Resources

Resources provide static reference data:

import { categoryList } from '@mapbox/mcp-server/resources';

// Read the category list resource
const categories = await categoryList.read();

Custom instantiation:

import { CategoryListResource } from '@mapbox/mcp-server/resources';
import { httpRequest } from '@mapbox/mcp-server/utils';

const resource = new CategoryListResource({ httpRequest });

Prompts

Prompts provide pre-built workflows:

import {
  getDirections,
  findPlacesNearby,
  searchAlongRoute,
  showReachableAreas
} from '@mapbox/mcp-server/prompts';

// Use a prompt
const result = await getDirections.execute({
  origin: 'San Francisco, CA',
  destination: 'Los Angeles, CA'
});

Custom instantiation:

import { GetDirectionsPrompt } from '@mapbox/mcp-server/prompts';

const prompt = new GetDirectionsPrompt();

HTTP Pipeline Utilities

Default Pipeline

Use the pre-configured default pipeline:

import { httpRequest } from '@mapbox/mcp-server/utils';

// Pre-configured with User-Agent, Retry, and Tracing policies
const response = await httpRequest('https://api.mapbox.com/...');

Custom Pipeline

Build your own pipeline:

import {
  HttpPipeline,
  UserAgentPolicy,
  RetryPolicy,
  TracingPolicy,
  type HttpPolicy
} from '@mapbox/mcp-server/utils';

const pipeline = new HttpPipeline();
pipeline.usePolicy(new UserAgentPolicy('MyApp/1.0.0'));
pipeline.usePolicy(new RetryPolicy(3, 200, 2000));
pipeline.usePolicy(new TracingPolicy());

// Create custom policy
const customPolicy: HttpPolicy = {
  id: 'my-policy',
  async handle(input, init, next) {
    console.log('Making request to:', input);
    return next(input, init);
  }
};
pipeline.usePolicy(customPolicy);

// Use the pipeline
const httpRequest = pipeline.execute.bind(pipeline);

Managing Policies

import { HttpPipeline, systemHttpPipeline } from '@mapbox/mcp-server/utils';

// Access the system pipeline
const policies = systemHttpPipeline.listPolicies();

// Find a policy by ID
const retryPolicy = systemHttpPipeline.findPolicyById('system-retry-policy');

// Remove a policy
systemHttpPipeline.removePolicy('system-retry-policy');

// Add it back
systemHttpPipeline.usePolicy(retryPolicy!);

CommonJS Support

All subpath exports work in CommonJS too:

// CommonJS
const { directions, searchAndGeocode } = require('@mapbox/mcp-server/tools');
const { httpRequest } = require('@mapbox/mcp-server/utils');

// ESM
import { directions, searchAndGeocode } from '@mapbox/mcp-server/tools';
import { httpRequest } from '@mapbox/mcp-server/utils';

Type Definitions

Full TypeScript support is included:

import type {
  ToolInstance,
  HttpRequest,
  TracedRequestInit,
  HttpPolicy
} from '@mapbox/mcp-server/tools';
import type { ResourceInstance } from '@mapbox/mcp-server/resources';
import type { PromptInstance } from '@mapbox/mcp-server/prompts';

Example: Building a Custom MCP Server

Here's how you might use these exports to build your own MCP server with a subset of tools. Each tool and resource registers itself with installTo(server):

import { McpServer } from '@modelcontextprotocol/server';
import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';

import { getAllTools } from '@mapbox/mcp-server/tools';
import { getAllResources } from '@mapbox/mcp-server/resources';
import { buildServerInstructions } from '@mapbox/mcp-server/utils';

// Pick only the tools you need. render_map_tool is only available through
// the registry, and it needs the map UI resource from getAllResources().
const wanted = new Set([
  'directions_tool',
  'search_and_geocode_tool',
  'isochrone_tool',
  'render_map_tool'
]);
const tools = getAllTools().filter((tool) => wanted.has(tool.name));

const server = new McpServer(
  { name: 'my-custom-mcp-server', version: '1.0.0' },
  {
    capabilities: { tools: {}, resources: {} },
    // Tells the model to show maps with render_map_tool and to pass
    // mapboxRender refs through unchanged. Hosts that load tools lazily only
    // see tool names up front, so tool descriptions alone can't do this.
    instructions: buildServerInstructions(tools.map((tool) => tool.name))
  }
);

tools.forEach((tool) => tool.installTo(server));
getAllResources().forEach((resource) => resource.installTo(server));

// Start server
const transport = new StdioServerTransport();
await server.connect(transport);

Server setup helpers

  • buildServerInstructions(toolNames): returns the server instructions text for the given enabled tool names, or undefined when render_map_tool isn't among them.
  • toJsonSchema2020(schema): converts a single draft-07 JSON Schema to JSON Schema 2020-12.
  • publishJsonSchema2020(server): deprecated no-op. MCP SDK v1 published tool schemas as draft-07 and this converted them; SDK v2 publishes 2020-12 itself, so the call can be removed.

The tools and resources are built against MCP TypeScript SDK v2 (@modelcontextprotocol/server), so installTo needs a v2 McpServer. A v1 McpServer from @modelcontextprotocol/sdk won't work.

Directions routes by reference

Long directions_tool routes are too big to hand to a model: above 50 KB the tool returns a summary without the geometry. If your app draws routes itself, pass the model the short ref from structuredContent.mapboxRender.ref (a few hundred bytes, in every result) and fetch the full route when you need it:

import { directionsRequestFromRef } from '@mapbox/mcp-server/utils';

const request = directionsRequestFromRef(ref, { accessToken });
if (request) {
  const response = await fetch(request.url);
  const { routes } = await response.json();
  const route = routes[request.selectedRouteIndex ?? 0]; // GeoJSON geometry
}

The ref holds only the original call's inputs, so it resolves in any process with no server-side state. The route is fetched again, so with live traffic it can differ slightly from the original call. resolveSelfFetchRef decodes any of these refs (directions, isochrone, search and others) to the tool and parameters behind it. To build the request yourself, buildDirectionsRequestUrl is the URL builder directions_tool and directionsRequestFromRef both use, so your request matches the tool's. directionsRequestFromRef always asks for geometries=geojson and overview=full, whatever the original call used, so you get every vertex of the route.

Example: Using in a Web Application

Use tools directly in a web app without MCP:

import { searchAndGeocode, directions } from '@mapbox/mcp-server/tools';

async function findRoute(origin: string, destination: string) {
  // Geocode the origin
  const originResult = await searchAndGeocode.execute({
    query: origin,
    limit: 1
  });

  // Geocode the destination
  const destResult = await searchAndGeocode.execute({
    query: destination,
    limit: 1
  });

  // Get directions
  const route = await directions.execute({
    coordinates: [
      originResult.features[0].geometry.coordinates,
      destResult.features[0].geometry.coordinates
    ],
    profile: 'driving'
  });

  return route;
}

// Use it
const route = await findRoute('San Francisco', 'Los Angeles');
console.log('Duration:', route.routes[0].duration, 'seconds');

Best Practices

  1. Use pre-configured instances for simple use cases
  2. Import only what you need to keep bundle size small
  3. Reuse tool instances rather than creating new ones repeatedly
  4. Use the default httpRequest unless you need custom behavior
  5. Create custom pipelines only when you need different retry logic, user agents, or custom policies
  6. Bind pipeline.execute when passing to tools: pipeline.execute.bind(pipeline)

See Also