Skip to content

Conversation

@mattpodwysocki
Copy link
Contributor

@mattpodwysocki mattpodwysocki commented Oct 21, 2025

Description

This PR adds MCP Resources and a reference tool to expose static Mapbox documentation and schemas, making it easier for AI assistants to build correct styles, tokens, and filters by providing essential reference information about Streets v8 fields, token scopes, and layer type mappings.

Motivation

When building Mapbox styles or creating tokens, AI assistants need to know:

  • What fields are available for filtering (e.g., class: 'park' for landuse layer)
  • What token scopes are needed for different operations
  • Which layer types are compatible with which source layers
  • What properties are available for each layer type

Previously, this information wasn't easily accessible, leading to trial-and-error or incorrect configurations. This PR provides comprehensive reference documentation directly through the MCP server.

Changes

1. MCP Resources Implementation

Added four new MCP resources exposing static reference data:

MapboxStreetsV8FieldsResource (resource://mapbox-streets-v8-fields)

  • Exposes complete field definitions for all Streets v8 source layers
  • Includes enumerated values for each field (e.g., landuse.class: ['park', 'cemetery', 'hospital', ...])
  • JSON format for easy parsing
  • Essential for building accurate style filters

MapboxTokenScopesResource (resource://mapbox-token-scopes)

  • Comprehensive Markdown documentation of all Mapbox token scopes
  • Explains public vs. secret token scopes
  • Includes common scope combinations and best practices
  • Helps AI recommend appropriate scopes when creating tokens

MapboxLayerTypeMappingResource (resource://mapbox-layer-type-mapping)

  • Maps Streets v8 source layers to compatible GL JS layer types
  • Organized by geometry type (polygon, line, point)
  • Includes common usage patterns and examples
  • Prevents incompatible layer type/source layer combinations

MapboxStyleLayersResource (existing, now documented)

  • Already existed but now properly documented
  • Provides GL JS style specification reference

2. GetReferenceTool - Claude Desktop Workaround

Added get_reference_tool to work around Claude Desktop's current limitation:

  • Problem: Claude Desktop can list resources but doesn't automatically fetch their content
  • Solution: Tool that internally calls resource readCallback() and returns content
  • Benefit: Makes reference data accessible to Claude Desktop users today
  • Future: Can be deprecated when Claude Desktop supports automatic resource fetching

3. Infrastructure Updates

BaseResource Class

  • Updated to use standard ReadResourceResult type from MCP SDK (like CallToolResult for tools)
  • Changed readCallback from protected to public for tool access
  • Added proper TypeScript types with RequestHandlerExtra parameter
  • Used _extra naming convention for intentionally unused parameters

ESLint Configuration

  • Added @typescript-eslint/no-unused-vars rule with argsIgnorePattern: '^_'
  • Allows the _extra parameter convention without lint errors
  • Consistent with TypeScript/JavaScript best practices

Resource Registry

  • Registered all 4 resources in resourceRegistry.ts
  • Resources are automatically exposed by the MCP server

4. Testing

Added comprehensive test coverage:

  • MapboxStreetsV8FieldsResource.test.ts - 5 tests
  • MapboxTokenScopesResource.test.ts - 8 tests
  • MapboxLayerTypeMappingResource.test.ts - 11 tests
  • Total: 26 new tests, all passing
  • Updated existing test fixtures for readCallback signature

5. Documentation

Updated README.md with:

  • New "Reference Tools" section documenting get_reference_tool
  • New "Resources" section explaining all 4 MCP resources
  • Clear explanation of Claude Desktop limitation and workaround
  • Example prompts for users
  • Updated Table of Contents

Technical Details

Resource vs. Tool Design Decision

Resources (static reference data):

  • ✅ Streets v8 field definitions
  • ✅ Token scope documentation
  • ✅ Layer type mappings
  • ✅ Style specification reference

Tools (dynamic, user-specific data):

  • list_styles_tool - fetches user's styles
  • list_tokens_tool - fetches user's tokens
  • ✅ Other action-based tools

This separation aligns with MCP best practices: resources for static knowledge, tools for dynamic data and actions.

Claude Desktop Limitation

From research and GitHub issues:

  • Claude Desktop calls resources/list successfully
  • Claude Desktop displays resources in settings UI
  • Claude Desktop does NOT automatically call resources/read
  • Workaround: get_reference_tool provides same data via tool interface

Type Safety Improvements

  • Used official ReadResourceResult type from @modelcontextprotocol/sdk/types.js
  • Consistent with tool pattern using CallToolResult
  • Ensures compatibility with MCP protocol evolution

Example Usage

With Claude Desktop (using tool)

User: "What fields are available for the landuse layer?"

Assistant: Uses get_reference_tool with resource://mapbox-streets-v8-fields and finds:

{
  "landuse": {
    "class": {
      "values": ["park", "cemetery", "hospital", "school", "industrial", ...]
    }
  }
}

User: "What scopes do I need for a public token that displays maps?"

Assistant: Uses get_reference_tool with resource://mapbox-token-scopes and recommends:

["styles:tiles", "fonts:read"]

With Future MCP Clients (using resources directly)

Clients that support automatic resource fetching can access the data directly without the tool workaround.


Testing

Cursor can read resources:
Screenshot 2025-10-21 at 16 56 16

Claude Code can read resources:
Screenshot 2025-10-21 at 17 54 35

Claude Desktop can read resources via tool usage:
Screenshot 2025-10-21 at 17 46 55

Cursor can read the Mapbox Streets V8 fields:
Screenshot 2025-10-27 at 10 11 45

Claude Desktop can read the Mapbox Streets V8 fields:
Screenshot 2025-10-27 at 10 10 03

Claude Code can read the Mapbox Streets V8 fields:
Screenshot 2025-10-27 at 10 08 09


Checklist

  • Code has been tested locally
  • Unit tests have been added or updated
  • Documentation has been updated if needed

Additional Notes

@mattpodwysocki mattpodwysocki requested a review from a team as a code owner October 21, 2025 21:54
@jussi-sa
Copy link
Contributor

for the token scopes, in devkit we no longer support secret scopes, so it's not worth mentioning about the secret scopes in resource://mapbox-token-scopes. we removed secret token support from the devkit because we don't want to expose .sk tokens to the LLM. you can see in create_token_tool schema - only public scopes are available. so it's not worth mentioning secret scopes in this resource I would say.

on Claude Code, the response from get_reference_tool using resource://mapbox-streets-v8-fields - the response is too large. it exceeds 25k tokens and therefore this error is shown:

image

on cursor, I can't send any messages if this branch of devkit is configured:

Screenshot 2025-10-24 at 17 04 14

zmofei
zmofei previously approved these changes Oct 24, 2025
@mattpodwysocki
Copy link
Contributor Author

for the token scopes, in devkit we no longer support secret scopes, so it's not worth mentioning about the secret scopes in resource://mapbox-token-scopes. we removed secret token support from the devkit because we don't want to expose .sk tokens to the LLM. you can see in create_token_tool schema - only public scopes are available. so it's not worth mentioning secret scopes in this resource I would say.

on Claude Code, the response from get_reference_tool using resource://mapbox-streets-v8-fields - the response is too large. it exceeds 25k tokens and therefore this error is shown:

image on cursor, I can't send any messages if this branch of devkit is configured: Screenshot 2025-10-24 at 17 04 14

@jussi-sa updated to trim the response of the spec and also added notes for only public keys are enumerated.

@mattpodwysocki mattpodwysocki requested a review from zmofei October 24, 2025 19:12
@zmofei
Copy link
Member

zmofei commented Oct 27, 2025

@mattpodwysocki Based on @jussi-sa 's comment, could you also provide some screenshots that prove the changes works on both Claude and cursor?

@mattpodwysocki mattpodwysocki merged commit b7baf99 into main Oct 27, 2025
1 check passed
@mattpodwysocki mattpodwysocki deleted the devkit_resources branch October 27, 2025 14:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants