diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d785c4..f5759d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Unreleased +### Removed + +- **`get_latest_mapbox_docs_tool` and `get_reference_tool` removed** — documentation fetching has moved to [mcp-docs-server](https://github.com/mapbox/mcp-docs-server). Use mcp-docs-server alongside this server for Mapbox documentation access. Static reference data (style layers, Streets v8 fields, token scopes, layer type mapping) remains available as MCP Resources. +- Removed `CLIENT_NEEDS_RESOURCE_FALLBACK` environment variable and resource fallback tool pattern + ### Dependencies - **Upgrade `zod` from `^3.25.42` to `^4.3.6`** — migrated all `z.record()` calls to require explicit key schema (`z.string()`), updated test assertions for changed error message format diff --git a/README.md b/README.md index d15f02c..bd3a70a 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A Model Context Protocol (MCP) server that provides AI assistants with direct access to Mapbox developer APIs. This server enables AI models to interact with Mapbox services, helping developers build Mapbox applications more efficiently. +> **Looking for Mapbox documentation access?** Use [mcp-docs-server](https://github.com/mapbox/mcp-docs-server) alongside this server — it provides AI assistants with access to Mapbox documentation, guides, and API references from docs.mapbox.com. + https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 ## Table of Contents @@ -15,7 +17,6 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 - [Hosted MCP Endpoint](#hosted-mcp-endpoint) - [Getting Your Mapbox Access Token](#getting-your-mapbox-access-token) - [Tools](#tools) - - [Documentation Tools](#documentation-tools) - [Reference Tools](#reference-tools) - [Style Management Tools](#style-management-tools) - [Token Management Tools](#token-management-tools) @@ -116,27 +117,9 @@ The `MAPBOX_ACCESS_TOKEN` environment variable is required. **Each tool requires ## Tools -### Documentation Tools - -**get_latest_mapbox_docs_tool** - Access the latest official Mapbox documentation directly from the source. This tool fetches comprehensive, up-to-date information about all Mapbox APIs, SDKs, and developer resources from docs.mapbox.com/llms.txt. - -**Example prompts:** - -- "What are the latest Mapbox APIs available for developers?" -- "Show me all current Mapbox services and SDKs" -- "I need up-to-date Mapbox documentation for my project" -- "What mapping solutions does Mapbox offer for my tech stack?" -- "Give me an overview of Mapbox's navigation and routing capabilities" -- "Compare Mapbox web SDKs versus mobile SDKs" -- "What's new in the Mapbox ecosystem?" - -📖 **[See more examples and interactive demo →](./docs/mapbox-docs-tool-demo.md)** - ### Reference Tools -**get_reference_tool** - Access static Mapbox reference documentation and schemas. This tool provides essential reference information that helps AI assistants understand Mapbox concepts and build correct styles and tokens. - -> **Note:** This tool exists as a workaround for Claude Desktop's current limitation with MCP resources. Claude Desktop can see resources (via `resources/list`) but doesn't automatically call `resources/read` to fetch their content. This tool provides the same reference data through the tool interface, which Claude Desktop does support. Other MCP clients that fully support the resources protocol can access this data directly as MCP Resources (see [Resources](#resources) section below). +Reference data is exposed as MCP Resources (see [Resources](#resources) section). MCP clients that support the resources protocol can access them directly. **Available References:** @@ -1053,7 +1036,7 @@ See the [mapbox-style-quality skill](skills/mapbox-style-quality/SKILL.md) for d ## Resources -This server exposes static reference documentation as MCP Resources. While these are primarily accessed through the `get_reference_tool`, MCP clients that fully support the resources protocol can access them directly. +This server exposes static reference documentation as MCP Resources. MCP clients that support the resources protocol can access them directly. **Available Resources:** @@ -1080,11 +1063,6 @@ This server exposes static reference documentation as MCP Resources. While these - Includes common usage patterns and examples - Helps avoid incompatible layer type/source layer combinations -**Accessing Resources:** - -- **Claude Desktop & Most MCP Clients**: Use the `get_reference_tool` to access these references -- **Future MCP Clients**: May support direct resource access via the MCP resources protocol - **Note:** Resources provide static reference data that doesn't change frequently, while tools provide dynamic, user-specific data (like listing your styles or tokens) and perform actions (like creating styles or tokens). ## Observability & Tracing @@ -1311,29 +1289,6 @@ node dist/esm/index.js --disable-mcp-ui **Note:** You typically don't need to disable this. All clients receive a usable text URL regardless; interactive previews are a progressive enhancement on top. -#### CLIENT_NEEDS_RESOURCE_FALLBACK - -**Resource Fallback Tools (Opt-In for Non-Compliant Clients)** - -Resources are a core MCP feature supported by most clients (Claude Desktop, VS Code, MCP Inspector, etc.). However, some clients (like smolagents) don't support resources at all. For these clients, the server can provide "resource fallback tools" that deliver the same content as resources but via tool calls. - -**Fallback Tools:** - -- `get_reference_tool` - Access to style layers, Streets v8 fields, token scopes, layer type mapping -- `get_latest_mapbox_docs_tool` - Access to Mapbox documentation - -**By default, these tools are NOT included** (assumes your client supports resources). If your client doesn't support resources, enable the fallback tools: - -```bash -export CLIENT_NEEDS_RESOURCE_FALLBACK=true -``` - -**When to set this:** - -- ✅ Set to `true` if using smolagents or other clients without resource support -- ❌ Leave unset (default) if using Claude Desktop, VS Code, MCP Inspector, or any resource-capable client -- ❌ Leave unset if unsure (most clients support resources) - ## Troubleshooting **Issue:** Tools fail with authentication errors diff --git a/docs/mapbox-docs-tool-demo.md b/docs/mapbox-docs-tool-demo.md deleted file mode 100644 index 2543ee2..0000000 --- a/docs/mapbox-docs-tool-demo.md +++ /dev/null @@ -1,223 +0,0 @@ -# Mapbox Documentation Tool Demo - -This demo showcases the `get_latest_mapbox_docs_tool` and provides example prompts that will trigger the AI assistant to use this tool instead of web search. - -> **⚠️ Important Note**: Different MCP clients (Claude Desktop, Claude Code, etc.) and different LLM models may exhibit varying behavior when selecting tools. The examples below are demonstrations of intended behavior and may not work identically across all environments. Tool selection depends on the specific AI model's training, the MCP client implementation, and system prompts used. - -## 🎯 Tool Overview - -The `get_latest_mapbox_docs_tool` automatically fetches the latest official Mapbox documentation from `docs.mapbox.com/llms.txt`. This ensures AI assistants always have access to current, authoritative information about Mapbox APIs and services. - -## 📝 Demo Prompts - -Try these prompts with your AI assistant to see the tool in action: - -### 1. Basic Documentation Queries - -``` -What are the latest Mapbox APIs available for developers? I want to make sure I'm using the most current information. -``` - -``` -I need the most up-to-date official Mapbox documentation. Can you provide a complete overview? -``` - -``` -Please show me all current Mapbox services and APIs using the latest documentation. -``` - -### 2. Development Planning (More Direct Approach) - -``` -Can you get the latest official Mapbox documentation and help me understand what developer tools are available? -``` - -``` -I need current information from Mapbox documentation about their complete developer platform. -``` - -``` -Please use the most recent Mapbox documentation to show me all mapping solutions they offer. -``` - -### 3. Learning & Research - -``` -Using the latest Mapbox documentation, give me a comprehensive overview of their current product ecosystem. -``` - -``` -I need up-to-date official information about Mapbox's navigation and routing capabilities. -``` - -``` -Please check the current Mapbox documentation and explain the differences between their web and mobile SDKs. -``` - -``` -I'm new to Mapbox. Can you get the latest official documentation and give me an overview of their resources? -``` - -### 4. Architecture Decisions - -``` -Can you check the latest Mapbox documentation and tell me what APIs are available for real estate applications with maps and search? -``` - -``` -I need current Mapbox documentation about mapping, geocoding, and routing options. What's available? -``` - -``` -Using the latest official Mapbox documentation, compare their web versus mobile solutions. -``` - -``` -Please get the most recent Mapbox documentation and show me services relevant for logistics platforms. -``` - -### 5. Latest Information Requests - -``` -What's new in the Mapbox ecosystem? Please use the latest official documentation to show me all current offerings. -``` - -``` -Can you get the most recent Mapbox documentation and tell me about any recent additions to their APIs? -``` - -``` -I need the current state of Mapbox developer tools - please check their latest documentation. -``` - -``` -I last used Mapbox 2 years ago. Can you get the latest documentation and show me what has changed? -``` - -## 🎪 Interactive Demo Session - -### More Effective Examples (Based on Real Testing): - -**Try these prompts that are more likely to trigger the documentation tool:** - -**Example 1:** - -``` -What are the latest Mapbox APIs available for developers? I want to make sure I'm using the most current information. -``` - -**Example 2:** - -``` -I need the most up-to-date Mapbox documentation for my project. Can you show me all current services available? -``` - -**Example 3:** - -``` -Please use the latest official Mapbox documentation to tell me about their navigation capabilities. -``` - -### Less Effective Examples: - -❌ **"I'm planning a food delivery app with real-time tracking and route optimization. What current Mapbox services would be relevant?"** - -- _Problem_: Too project-specific, may trigger general knowledge response - -❌ **"What Mapbox APIs should I use for my app?"** - -- _Problem_: Too general, may trigger web search - -❌ **"How do I implement Mapbox in React?"** - -- _Problem_: Implementation-focused, may trigger general coding help - -### Why Some Examples Work Better: - -✅ **Direct documentation requests**: "latest Mapbox documentation", "current APIs available" -✅ **Emphasis on currency**: "most current information", "up-to-date" -✅ **Official source requests**: "official Mapbox documentation", "latest official information" - -> **📝 Real-World Note**: Based on testing, prompts that explicitly request documentation or emphasize getting the latest official information have higher success rates for triggering the documentation tool. - -## 🔍 What Makes These Prompts Effective - -These prompts work because they: - -- ✅ **Emphasize currency**: Use words like "latest", "current", "up-to-date" -- ✅ **Request completeness**: Ask for "all", "comprehensive", "complete overview" -- ✅ **Imply official sources**: Request "current offerings", "official documentation" -- ✅ **Suggest comparison needs**: Multiple options require comprehensive data -- ✅ **Focus on accuracy**: "make sure I'm using correct information" - -## 🚀 Benefits Demonstration - -### Before (using web search): - -- May get outdated information -- Fragmented results from multiple sources -- Potential inaccuracies from third-party sites -- Missing new APIs or changes - -### After (using get_latest_mapbox_docs_tool): - -- ✅ Always current official information -- ✅ Complete ecosystem overview -- ✅ Authoritative source (directly from Mapbox) -- ✅ Includes latest APIs and features - -## 🎛 Advanced Usage - -### Complex Project Planning - -``` -Can you get the latest Mapbox documentation and help me architect a geospatial solution with mapping, search, routing, and analytics? I need to know what services are currently available. -``` - -### Competitive Analysis - -``` -I'm evaluating Mapbox versus other platforms. Please use the most current official Mapbox documentation to show me all their capabilities for my analysis. -``` - -### Migration Planning - -``` -We're migrating from another platform. Can you check the latest Mapbox documentation and show me all services that could replace our current functionality? -``` - -## 💡 Pro Tips - -1. **Use temporal keywords**: "latest", "current", "up-to-date", "recent" -2. **Request comprehensiveness**: "all", "complete", "entire", "full" -3. **Emphasize accuracy**: "official", "authoritative", "correct" -4. **Avoid specific tool names**: Let the AI choose the right tool naturally -5. **Context matters**: Mention your project needs to get relevant filtering - -### 🔧 **Troubleshooting Tool Selection** - -If the AI is not using the documentation tool: - -- **Be more explicit**: "I need official Mapbox documentation" or "Please use the latest source" -- **Emphasize currency**: "Make sure you have the most current information" -- **Request authority**: "I want authoritative information directly from Mapbox" -- **Try rephrasing**: Different models respond to different prompt styles -- **Check your MCP setup**: Ensure the tool is properly registered and available - -### 🌐 **Environment Considerations** - -**Claude Desktop vs Claude Code**: Different interfaces may have varying tool selection behaviors. - -**Model Versions**: Newer models may be better at tool selection than older ones. - -**System Prompts**: Some MCP clients may have system prompts that influence tool selection preferences. - ---- - -## 📋 **Disclaimer** - -_This demo file provides **examples and suggestions** for using the Mapbox Documentation Tool. The prompts are crafted to **ideally** trigger correct tool selection, but actual behavior **will vary** across different MCP clients, AI models, and system configurations._ - -_**Results may vary**: Tool selection depends on many factors including model training, client implementation, and system prompts. These examples show **intended behavior** rather than guaranteed outcomes._ - -_Use these examples as **starting points** and adjust your prompts based on your specific environment and the AI assistant's responses._ diff --git a/docs/tracing-verification.md b/docs/tracing-verification.md index f8ce56b..30b97ba 100644 --- a/docs/tracing-verification.md +++ b/docs/tracing-verification.md @@ -44,7 +44,7 @@ This will: In the MCP inspector: -1. Execute any tool (e.g., `list_styles_tool` or `get_latest_mapbox_docs_tool`) +1. Execute any tool (e.g., `list_styles_tool` or `validate_style_tool`) 2. Try multiple tools to generate various traces: - Style operations (create, update, retrieve, delete) - Token management diff --git a/docs/tracing.md b/docs/tracing.md index a5d292e..bdc8280 100644 --- a/docs/tracing.md +++ b/docs/tracing.md @@ -300,7 +300,6 @@ All developer tools are automatically traced: - **Style Management**: `list_styles_tool`, `create_style_tool`, `update_style_tool`, `retrieve_style_tool`, `delete_style_tool` - **Style Building**: `style_builder_tool`, `preview_style_tool`, `style_comparison_tool` - **Token Management**: `list_tokens_tool`, `create_token_tool` -- **Documentation**: `get_latest_mapbox_docs_tool`, `get_reference_tool` - **Local Processing**: `geojson_preview_tool`, `coordinate_conversion_tool`, `bounding_box_tool` - **Tilesets**: `tilequery_tool` diff --git a/package-lock.json b/package-lock.json index bc9c6df..2220340 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11841,7 +11841,9 @@ } }, "node_modules/prettier": { - "version": "3.6.2", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", + "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", "dev": true, "license": "MIT", "bin": { diff --git a/src/index.ts b/src/index.ts index 0f44562..6e824de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -17,11 +17,7 @@ import { } from '@modelcontextprotocol/ext-apps/server'; import { z } from 'zod'; import { parseToolConfigFromArgs, filterTools } from './config/toolConfig.js'; -import { - getCoreTools, - getElicitationTools, - getResourceFallbackTools -} from './tools/toolRegistry.js'; +import { getCoreTools, getElicitationTools } from './tools/toolRegistry.js'; import { getAllResources } from './resources/resourceRegistry.js'; import { getAllPrompts } from './prompts/promptRegistry.js'; import { getVersionInfo } from './utils/versionUtils.js'; @@ -65,11 +61,9 @@ const config = parseToolConfigFromArgs(); // Split into categories for capability-aware registration const coreTools = getCoreTools(); const elicitationTools = getElicitationTools(); -const resourceFallbackTools = getResourceFallbackTools(); const enabledCoreTools = filterTools(coreTools, config); const enabledElicitationTools = filterTools(elicitationTools, config); -const enabledResourceFallbackTools = filterTools(resourceFallbackTools, config); // Create an MCP server const server = new McpServer( @@ -279,34 +273,6 @@ async function main() { }); } - // Register resource fallback tools for clients that don't support resources - // Note: Resources are a core MCP feature supported by most clients. - // However, some clients (like smolagents) don't support resources at all. - // These fallback tools provide the same content as resources but via tool calls instead. - // - // Configuration via CLIENT_NEEDS_RESOURCE_FALLBACK environment variable: - // - unset (default) = Skip fallback tools (assume client supports resources) - // - "true" = Provide fallback tools (client does NOT support resources) - const clientNeedsResourceFallback = - process.env.CLIENT_NEEDS_RESOURCE_FALLBACK?.toLowerCase() === 'true'; - - if (clientNeedsResourceFallback && enabledResourceFallbackTools.length > 0) { - server.server.sendLoggingMessage({ - level: 'info', - data: `CLIENT_NEEDS_RESOURCE_FALLBACK=true. Registering ${enabledResourceFallbackTools.length} resource fallback tools` - }); - - enabledResourceFallbackTools.forEach((tool) => { - tool.installTo(server); - }); - toolsAdded = true; - } else if (enabledResourceFallbackTools.length > 0) { - server.server.sendLoggingMessage({ - level: 'debug', - data: `CLIENT_NEEDS_RESOURCE_FALLBACK not set or false. Skipping ${enabledResourceFallbackTools.length} resource fallback tools (client supports resources)` - }); - } - // Notify client about tool list changes if any tools were added if (toolsAdded) { try { diff --git a/src/prompts/DebugMapboxIntegrationPrompt.ts b/src/prompts/DebugMapboxIntegrationPrompt.ts index fe7d22f..00f1d89 100644 --- a/src/prompts/DebugMapboxIntegrationPrompt.ts +++ b/src/prompts/DebugMapboxIntegrationPrompt.ts @@ -186,7 +186,7 @@ Analyze the error and provide specific solutions: 1. **Source not defined**: Ensure source is added before layers that reference it 2. **Invalid layer type**: Check layer type matches source geometry 3. **Missing required property**: Verify all required layer properties are set -4. **Use get_reference_tool**: Get 'style-spec-reference' for layer requirements +4. **Check style spec**: Read \`resource://mapbox-style-layers\` for layer requirements `; } @@ -228,10 +228,9 @@ Run these diagnostic checks: - Compare the working preview with the broken implementation 3. **Check documentation** - - Use get_reference_tool with: - * 'style-spec-reference' for style JSON issues - * 'token-scopes-reference' for token scope questions - * 'streets-v8-fields-reference' for data layer questions + - Read \`resource://mapbox-style-layers\` for style JSON issues + - Read \`resource://mapbox-token-scopes\` for token scope questions + - Read \`resource://mapbox-streets-v8-fields\` for data layer questions ## Phase 5: Solution Summary diff --git a/src/prompts/DesignDataDrivenStylePrompt.ts b/src/prompts/DesignDataDrivenStylePrompt.ts index 85ebfda..b09df1c 100644 --- a/src/prompts/DesignDataDrivenStylePrompt.ts +++ b/src/prompts/DesignDataDrivenStylePrompt.ts @@ -259,7 +259,7 @@ Before finalizing the style, you need to know: - These tools will show you the data structure and property values **If using Mapbox tilesets:** -- Use get_reference_tool with 'streets-v8-fields-reference' to see available fields +- Read \`resource://mapbox-streets-v8-fields\` to see available fields - Review typical value ranges in the documentation ## Step 4: Create the Style @@ -425,7 +425,7 @@ After creating your data-driven style, automatically run validation: ## Step 9: Documentation For more information on expressions: -- Use get_reference_tool with 'style-spec-reference' +- Read \`resource://mapbox-style-layers\` for style spec reference - Search for "expressions" in the Mapbox documentation - Review expression examples for your use case diff --git a/src/resources/index.ts b/src/resources/index.ts index a0e0c56..bc8a1fc 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -13,27 +13,16 @@ * ```typescript * import { mapboxStyleLayers } from '@mapbox/mcp-devkit-server/resources'; * - * // Use directly - httpRequest already configured + * // Use directly - already configured * const result = await mapboxStyleLayers.read(); * ``` - * - * @example Advanced usage with custom pipeline - * ```typescript - * import { MapboxDocumentationResource } from '@mapbox/mcp-devkit-server/resources'; - * import { httpRequest } from '@mapbox/mcp-devkit-server/utils'; - * - * const customResource = new MapboxDocumentationResource({ httpRequest }); - * ``` */ -import { httpRequest } from '../utils/httpPipeline.js'; - // Export all resource classes export { MapboxStyleLayersResource } from './mapbox-style-layers-resource/MapboxStyleLayersResource.js'; export { MapboxStreetsV8FieldsResource } from './mapbox-streets-v8-fields-resource/MapboxStreetsV8FieldsResource.js'; export { MapboxTokenScopesResource } from './mapbox-token-scopes-resource/MapboxTokenScopesResource.js'; export { MapboxLayerTypeMappingResource } from './mapbox-layer-type-mapping-resource/MapboxLayerTypeMappingResource.js'; -export { MapboxDocumentationResource } from './mapbox-documentation-resource/MapboxDocumentationResource.js'; export { PreviewStyleUIResource } from './ui-apps/PreviewStyleUIResource.js'; export { StyleComparisonUIResource } from './ui-apps/StyleComparisonUIResource.js'; export { GeojsonPreviewUIResource } from './ui-apps/GeojsonPreviewUIResource.js'; @@ -43,12 +32,12 @@ import { MapboxStyleLayersResource } from './mapbox-style-layers-resource/Mapbox import { MapboxStreetsV8FieldsResource } from './mapbox-streets-v8-fields-resource/MapboxStreetsV8FieldsResource.js'; import { MapboxTokenScopesResource } from './mapbox-token-scopes-resource/MapboxTokenScopesResource.js'; import { MapboxLayerTypeMappingResource } from './mapbox-layer-type-mapping-resource/MapboxLayerTypeMappingResource.js'; -import { MapboxDocumentationResource } from './mapbox-documentation-resource/MapboxDocumentationResource.js'; import { PreviewStyleUIResource } from './ui-apps/PreviewStyleUIResource.js'; import { StyleComparisonUIResource } from './ui-apps/StyleComparisonUIResource.js'; import { GeojsonPreviewUIResource } from './ui-apps/GeojsonPreviewUIResource.js'; // Export pre-configured resource instances with short, clean names + /** Mapbox style layers reference */ export const mapboxStyleLayers = new MapboxStyleLayersResource(); @@ -61,11 +50,6 @@ export const mapboxTokenScopes = new MapboxTokenScopesResource(); /** Mapbox layer type mapping reference */ export const mapboxLayerTypeMapping = new MapboxLayerTypeMappingResource(); -/** Mapbox documentation */ -export const mapboxDocumentation = new MapboxDocumentationResource({ - httpRequest -}); - /** Preview style UI resource */ export const previewStyleUI = new PreviewStyleUIResource(); diff --git a/src/resources/mapbox-documentation-resource/MapboxDocumentationResource.ts b/src/resources/mapbox-documentation-resource/MapboxDocumentationResource.ts deleted file mode 100644 index 9fea819..0000000 --- a/src/resources/mapbox-documentation-resource/MapboxDocumentationResource.ts +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import type { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js'; -import type { - ReadResourceResult, - ServerNotification, - ServerRequest -} from '@modelcontextprotocol/sdk/types.js'; -import type { HttpRequest } from '../../utils/types.js'; -import { BaseResource } from '../BaseResource.js'; - -/** - * Resource providing the latest official Mapbox documentation - * fetched from docs.mapbox.com/llms.txt - */ -export class MapboxDocumentationResource extends BaseResource { - readonly name = 'Mapbox Documentation'; - readonly uri = 'resource://mapbox-documentation'; - readonly description = - 'Latest official Mapbox documentation, APIs, SDKs, and developer resources. Always up-to-date comprehensive coverage of all current Mapbox services.'; - readonly mimeType = 'text/markdown'; - - private httpRequest: HttpRequest; - - constructor(params: { httpRequest: HttpRequest }) { - super(); - this.httpRequest = params.httpRequest; - } - - public async readCallback( - uri: URL, - _extra: RequestHandlerExtra - ): Promise { - try { - const response = await this.httpRequest( - 'https://docs.mapbox.com/llms.txt', - { - headers: { - Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8' - } - } - ); - - if (!response.ok) { - throw new Error( - `Failed to fetch Mapbox documentation: ${response.statusText}` - ); - } - - const content = await response.text(); - - return { - contents: [ - { - uri: uri.href, - mimeType: this.mimeType, - text: content - } - ] - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : 'Unknown error occurred'; - throw new Error(`Failed to fetch Mapbox documentation: ${errorMessage}`); - } - } -} diff --git a/src/resources/resourceRegistry.ts b/src/resources/resourceRegistry.ts index 4786a97..a9758bc 100644 --- a/src/resources/resourceRegistry.ts +++ b/src/resources/resourceRegistry.ts @@ -5,11 +5,9 @@ import { MapboxStyleLayersResource } from './mapbox-style-layers-resource/Mapbox import { MapboxStreetsV8FieldsResource } from './mapbox-streets-v8-fields-resource/MapboxStreetsV8FieldsResource.js'; import { MapboxTokenScopesResource } from './mapbox-token-scopes-resource/MapboxTokenScopesResource.js'; import { MapboxLayerTypeMappingResource } from './mapbox-layer-type-mapping-resource/MapboxLayerTypeMappingResource.js'; -import { MapboxDocumentationResource } from './mapbox-documentation-resource/MapboxDocumentationResource.js'; import { PreviewStyleUIResource } from './ui-apps/PreviewStyleUIResource.js'; import { StyleComparisonUIResource } from './ui-apps/StyleComparisonUIResource.js'; import { GeojsonPreviewUIResource } from './ui-apps/GeojsonPreviewUIResource.js'; -import { httpRequest } from '../utils/httpPipeline.js'; // Central registry of all resources export const ALL_RESOURCES = [ @@ -17,7 +15,6 @@ export const ALL_RESOURCES = [ new MapboxStreetsV8FieldsResource(), new MapboxTokenScopesResource(), new MapboxLayerTypeMappingResource(), - new MapboxDocumentationResource({ httpRequest }), // MCP Apps UI resources (ui:// scheme) new PreviewStyleUIResource(), new StyleComparisonUIResource(), diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.input.schema.ts b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.input.schema.ts deleted file mode 100644 index 7701ebd..0000000 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.input.schema.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { z } from 'zod'; - -export const GetMapboxDocSourceSchema = z.object({}); - -export type GetMapboxDocSourceInput = z.infer; diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts deleted file mode 100644 index 18715bf..0000000 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import type { HttpRequest } from '../../utils/types.js'; -import { BaseTool } from '../BaseTool.js'; -import { - GetMapboxDocSourceSchema, - GetMapboxDocSourceInput -} from './GetMapboxDocSourceTool.input.schema.js'; - -export class GetMapboxDocSourceTool extends BaseTool< - typeof GetMapboxDocSourceSchema -> { - name = 'get_latest_mapbox_docs_tool'; - description = - 'Get the latest official Mapbox documentation, APIs, SDKs, and developer resources directly from Mapbox. Always up-to-date, comprehensive coverage of all current Mapbox services including mapping, navigation, search, geocoding, and mobile SDKs. Use this for accurate, official Mapbox information instead of web search. For clients that support resources, use resource://mapbox-documentation for proper text/markdown MIME type support.'; - readonly annotations = { - readOnlyHint: true, - destructiveHint: false, - idempotentHint: true, - openWorldHint: true, - title: 'Get Mapbox Documentation Tool' - }; - - private httpRequest: HttpRequest; - - constructor(params: { httpRequest: HttpRequest }) { - super({ - inputSchema: GetMapboxDocSourceSchema - }); - this.httpRequest = params.httpRequest; - } - - protected async execute( - _input: GetMapboxDocSourceInput - ): Promise { - try { - const response = await this.httpRequest( - 'https://docs.mapbox.com/llms.txt', - { - headers: { - Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8' - } - } - ); - - if (!response.ok) { - return { - content: [ - { - type: 'text', - text: `Failed to fetch Mapbox documentation: ${response.statusText}` - } - ], - isError: true - }; - } - - const content = await response.text(); - - return { - content: [ - { - type: 'text', - text: content - } - ], - isError: false - }; - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : 'Unknown error occurred'; - return { - content: [ - { - type: 'text', - text: `Failed to fetch Mapbox documentation: ${errorMessage}` - } - ], - isError: true - }; - } - } -} diff --git a/src/tools/get-reference-tool/GetReferenceTool.input.schema.ts b/src/tools/get-reference-tool/GetReferenceTool.input.schema.ts deleted file mode 100644 index 29237c1..0000000 --- a/src/tools/get-reference-tool/GetReferenceTool.input.schema.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { z } from 'zod'; - -export const GetReferenceSchema = z.object({ - reference: z - .enum([ - 'resource://mapbox-style-layers', - 'resource://mapbox-streets-v8-fields', - 'resource://mapbox-token-scopes', - 'resource://mapbox-layer-type-mapping' - ]) - .describe( - 'The reference documentation to retrieve. Available references: ' + - 'resource://mapbox-style-layers (Mapbox GL JS style specification for layer types and properties), ' + - 'resource://mapbox-streets-v8-fields (Complete field definitions for all Streets v8 source layers), ' + - 'resource://mapbox-token-scopes (Token scope reference and permissions guide), ' + - 'resource://mapbox-layer-type-mapping (Mapping of source layers to compatible layer types)' - ) -}); - -export type GetReferenceInput = z.infer; diff --git a/src/tools/get-reference-tool/GetReferenceTool.ts b/src/tools/get-reference-tool/GetReferenceTool.ts deleted file mode 100644 index e695107..0000000 --- a/src/tools/get-reference-tool/GetReferenceTool.ts +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { CallToolResult } from '@modelcontextprotocol/sdk/types.js'; -import { BaseTool } from '../BaseTool.js'; -import { - GetReferenceSchema, - GetReferenceInput -} from './GetReferenceTool.input.schema.js'; -import { getAllResources } from '../../resources/resourceRegistry.js'; - -/** - * Tool to access Mapbox reference documentation and schemas - * This tool provides access to static reference data that helps understand - * Mapbox concepts, field definitions, token scopes, and layer type mappings. - */ -export class GetReferenceTool extends BaseTool { - readonly name = 'get_reference_tool'; - readonly description = - 'Get Mapbox reference documentation including Streets v8 field definitions, token scopes, layer type mappings, and style specifications. Use this tool to understand what fields, scopes, or layer types are available before creating styles or tokens.'; - readonly annotations = { - readOnlyHint: true, - destructiveHint: false, - idempotentHint: true, - openWorldHint: false, - title: 'Get Mapbox Reference Documentation' - }; - - constructor() { - super({ inputSchema: GetReferenceSchema }); - } - - protected async execute(input: GetReferenceInput): Promise { - const resources = getAllResources(); - const resource = resources.find((r) => r.uri === input.reference); - - if (!resource) { - return { - content: [ - { - type: 'text', - text: `Reference not found: ${input.reference}\n\nAvailable references:\n${resources.map((r) => `- ${r.uri}: ${r.description}`).join('\n')}` - } - ], - isError: true - }; - } - - try { - // Call the resource's readCallback to get the content - const uri = new URL(resource.uri); - // Pass empty object for extra parameter (not used by resources) - const result = await resource.readCallback(uri, {} as any); - - // Return the first content item (resources can return multiple but we typically have one) - if (result.contents.length === 0) { - return { - content: [ - { - type: 'text', - text: `No content available for reference: ${input.reference}` - } - ], - isError: true - }; - } - - const content = result.contents[0]; - // Type guard: check if content has 'text' property (vs 'blob' for binary resources) - if (!('text' in content)) { - return { - content: [ - { - type: 'text', - text: `Reference ${input.reference} returned binary content, expected text` - } - ], - isError: true - }; - } - - return { - content: [ - { - type: 'text', - text: content.text - } - ], - isError: false - }; - } catch (error) { - return { - content: [ - { - type: 'text', - text: `Error reading reference: ${error instanceof Error ? error.message : String(error)}` - } - ], - isError: true - }; - } - } -} diff --git a/src/tools/index.ts b/src/tools/index.ts index 4e9c4a6..ca134f3 100644 --- a/src/tools/index.ts +++ b/src/tools/index.ts @@ -40,8 +40,6 @@ export { DeleteStyleTool } from './delete-style-tool/DeleteStyleTool.js'; export { GetFeedbackTool } from './get-feedback-tool/GetFeedbackTool.js'; export { ListFeedbackTool } from './list-feedback-tool/ListFeedbackTool.js'; export { GeojsonPreviewTool } from './geojson-preview-tool/GeojsonPreviewTool.js'; -export { GetMapboxDocSourceTool } from './get-mapbox-doc-source-tool/GetMapboxDocSourceTool.js'; -export { GetReferenceTool } from './get-reference-tool/GetReferenceTool.js'; export { ListStylesTool } from './list-styles-tool/ListStylesTool.js'; export { ListTokensTool } from './list-tokens-tool/ListTokensTool.js'; export { OptimizeStyleTool } from './optimize-style-tool/OptimizeStyleTool.js'; @@ -67,8 +65,6 @@ import { DeleteStyleTool } from './delete-style-tool/DeleteStyleTool.js'; import { GetFeedbackTool } from './get-feedback-tool/GetFeedbackTool.js'; import { ListFeedbackTool } from './list-feedback-tool/ListFeedbackTool.js'; import { GeojsonPreviewTool } from './geojson-preview-tool/GeojsonPreviewTool.js'; -import { GetMapboxDocSourceTool } from './get-mapbox-doc-source-tool/GetMapboxDocSourceTool.js'; -import { GetReferenceTool } from './get-reference-tool/GetReferenceTool.js'; import { ListStylesTool } from './list-styles-tool/ListStylesTool.js'; import { ListTokensTool } from './list-tokens-tool/ListTokensTool.js'; import { OptimizeStyleTool } from './optimize-style-tool/OptimizeStyleTool.js'; @@ -118,12 +114,6 @@ export const listFeedback = new ListFeedbackTool({ httpRequest }); /** Preview GeoJSON on a map */ export const geojsonPreview = new GeojsonPreviewTool(); -/** Get Mapbox documentation source */ -export const getMapboxDocSource = new GetMapboxDocSourceTool({ httpRequest }); - -/** Get reference documentation */ -export const getReference = new GetReferenceTool(); - /** List Mapbox styles */ export const listStyles = new ListStylesTool({ httpRequest }); @@ -165,7 +155,6 @@ export { getAllTools, getCoreTools, getElicitationTools, - getResourceFallbackTools, getToolByName, type ToolInstance } from './toolRegistry.js'; diff --git a/src/tools/toolRegistry.ts b/src/tools/toolRegistry.ts index 481ea7e..5e9237d 100644 --- a/src/tools/toolRegistry.ts +++ b/src/tools/toolRegistry.ts @@ -12,8 +12,6 @@ import { DeleteStyleTool } from './delete-style-tool/DeleteStyleTool.js'; import { GetFeedbackTool } from './get-feedback-tool/GetFeedbackTool.js'; import { ListFeedbackTool } from './list-feedback-tool/ListFeedbackTool.js'; import { GeojsonPreviewTool } from './geojson-preview-tool/GeojsonPreviewTool.js'; -import { GetMapboxDocSourceTool } from './get-mapbox-doc-source-tool/GetMapboxDocSourceTool.js'; -import { GetReferenceTool } from './get-reference-tool/GetReferenceTool.js'; import { ListStylesTool } from './list-styles-tool/ListStylesTool.js'; import { ListTokensTool } from './list-tokens-tool/ListTokensTool.js'; import { OptimizeStyleTool } from './optimize-style-tool/OptimizeStyleTool.js'; @@ -68,41 +66,16 @@ export const CORE_TOOLS = [ */ export const ELICITATION_TOOLS = [] as const; -/** - * Tools that serve as bridges for clients without resource support - * These tools are only registered if CLIENT_NEEDS_RESOURCE_FALLBACK env var is set to "true" - * - * Context: Most MCP clients support resources (Claude Desktop, VS Code, Inspector, etc.). - * However, some clients (like smolagents) don't support resources at all. - * These tools provide the same content as resources but via tool calls instead. - * - * Configuration: - * - Leave unset (default) = Skip these tools (assumes client supports resources) - * - Set CLIENT_NEEDS_RESOURCE_FALLBACK=true = Include these tools (for smolagents, etc.) - * - * Tools: - * - GetReferenceTool: Provides access to reference resources (style layers, Streets v8 fields, token scopes, layer type mapping) - * - GetMapboxDocSourceTool: Provides access to Mapbox documentation (resource://mapbox-documentation) - */ -export const RESOURCE_FALLBACK_TOOLS = [ - new GetReferenceTool(), - new GetMapboxDocSourceTool({ httpRequest }) -] as const; - /** * All tools combined (for backward compatibility and testing) */ -export const ALL_TOOLS = [ - ...CORE_TOOLS, - ...ELICITATION_TOOLS, - ...RESOURCE_FALLBACK_TOOLS -] as const; +export const ALL_TOOLS = [...CORE_TOOLS, ...ELICITATION_TOOLS] as const; export type ToolInstance = (typeof ALL_TOOLS)[number]; /** * Get all tools (for backward compatibility) - * @deprecated Use getCoreTools(), getElicitationTools(), etc. instead for capability-aware registration + * @deprecated Use getCoreTools(), getElicitationTools() instead for capability-aware registration */ export function getAllTools(): readonly ToolInstance[] { return ALL_TOOLS; @@ -122,13 +95,6 @@ export function getElicitationTools(): readonly ToolInstance[] { return ELICITATION_TOOLS; } -/** - * Get tools that serve as fallbacks when client doesn't support resources - */ -export function getResourceFallbackTools(): readonly ToolInstance[] { - return RESOURCE_FALLBACK_TOOLS; -} - export function getToolByName(name: string): ToolInstance | undefined { return ALL_TOOLS.find((tool) => tool.name === name); } diff --git a/test/resources/mapbox-documentation-resource/MapboxDocumentationResource.test.ts b/test/resources/mapbox-documentation-resource/MapboxDocumentationResource.test.ts deleted file mode 100644 index 73574f2..0000000 --- a/test/resources/mapbox-documentation-resource/MapboxDocumentationResource.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { describe, expect, it } from 'vitest'; -import { MapboxDocumentationResource } from '../../../src/resources/mapbox-documentation-resource/MapboxDocumentationResource.js'; -import { setupHttpRequest } from '../../utils/httpPipelineUtils.js'; - -describe('MapboxDocumentationResource', () => { - it('should have correct metadata', () => { - const { httpRequest } = setupHttpRequest(); - const resource = new MapboxDocumentationResource({ httpRequest }); - - expect(resource.name).toBe('Mapbox Documentation'); - expect(resource.uri).toBe('resource://mapbox-documentation'); - expect(resource.mimeType).toBe('text/markdown'); - expect(resource.description).toContain( - 'Latest official Mapbox documentation' - ); - }); - - it('should successfully fetch documentation content with proper MIME type', async () => { - const mockContent = `# Mapbox Documentation - -This is the Mapbox developer documentation for LLMs. - -## Web SDKs -- Mapbox GL JS for interactive maps -- Mobile SDKs for iOS and Android - -## APIs -- Geocoding API for address search -- Directions API for routing`; - - const { httpRequest, mockHttpRequest } = setupHttpRequest({ - ok: true, - status: 200, - text: () => Promise.resolve(mockContent) - }); - - const resource = new MapboxDocumentationResource({ httpRequest }); - const uri = new URL('resource://mapbox-documentation'); - const result = await resource.readCallback(uri, {} as any); - - expect(mockHttpRequest).toHaveBeenCalledWith( - 'https://docs.mapbox.com/llms.txt', - { - headers: { - Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8', - 'User-Agent': 'TestServer/1.0.0 (default, no-tag, abcdef)' - } - } - ); - - expect(result.contents).toHaveLength(1); - expect(result.contents[0]).toMatchObject({ - uri: 'resource://mapbox-documentation', - mimeType: 'text/markdown', - text: mockContent - }); - }); - - it('should handle HTTP errors', async () => { - const { httpRequest } = setupHttpRequest({ - ok: false, - status: 404, - statusText: 'Not Found' - }); - - const resource = new MapboxDocumentationResource({ httpRequest }); - const uri = new URL('resource://mapbox-documentation'); - - await expect(resource.readCallback(uri, {} as any)).rejects.toThrow( - 'Failed to fetch Mapbox documentation: Not Found' - ); - }); - - it('should handle network errors', async () => { - const { httpRequest } = setupHttpRequest({ - text: () => Promise.reject(new Error('Network error')) - }); - - const resource = new MapboxDocumentationResource({ httpRequest }); - const uri = new URL('resource://mapbox-documentation'); - - await expect(resource.readCallback(uri, {} as any)).rejects.toThrow( - 'Failed to fetch Mapbox documentation: Network error' - ); - }); - - it('should handle unknown errors', async () => { - const { httpRequest } = setupHttpRequest({ - text: () => Promise.reject('String error') - }); - - const resource = new MapboxDocumentationResource({ httpRequest }); - const uri = new URL('resource://mapbox-documentation'); - - await expect(resource.readCallback(uri, {} as any)).rejects.toThrow( - 'Failed to fetch Mapbox documentation: Unknown error occurred' - ); - }); -}); diff --git a/test/tools/__snapshots__/tool-naming-convention.test.ts.snap b/test/tools/__snapshots__/tool-naming-convention.test.ts.snap index 8b22510..e8e0c2e 100644 --- a/test/tools/__snapshots__/tool-naming-convention.test.ts.snap +++ b/test/tools/__snapshots__/tool-naming-convention.test.ts.snap @@ -52,16 +52,6 @@ exports[`Tool Naming Convention > should maintain consistent tool list (snapshot "description": "Get a single user feedback item from the Mapbox Feedback API by its unique ID. Use this tool to retrieve detailed information about a specific user-reported issue, suggestion, or feedback about map data, routing, or POI details. Requires user-feedback:read scope on the access token.", "toolName": "get_feedback_tool", }, - { - "className": "GetMapboxDocSourceTool", - "description": "Get the latest official Mapbox documentation, APIs, SDKs, and developer resources directly from Mapbox. Always up-to-date, comprehensive coverage of all current Mapbox services including mapping, navigation, search, geocoding, and mobile SDKs. Use this for accurate, official Mapbox information instead of web search. For clients that support resources, use resource://mapbox-documentation for proper text/markdown MIME type support.", - "toolName": "get_latest_mapbox_docs_tool", - }, - { - "className": "GetReferenceTool", - "description": "Get Mapbox reference documentation including Streets v8 field definitions, token scopes, layer type mappings, and style specifications. Use this tool to understand what fields, scopes, or layer types are available before creating styles or tokens.", - "toolName": "get_reference_tool", - }, { "className": "ListFeedbackTool", "description": "List user feedback items from the Mapbox Feedback API with filtering, sorting, and pagination. Use this tool to access user-reported issues, suggestions, and feedback about map data, routing, and POI details. Supports comprehensive filtering by status, category, date ranges, trace IDs, and search text. Requires user-feedback:read scope on the access token.", diff --git a/test/tools/bounding-box-tool/BoundingBoxTool.test.ts b/test/tools/bounding-box-tool/BoundingBoxTool.test.ts index 747e4f1..70db92b 100644 --- a/test/tools/bounding-box-tool/BoundingBoxTool.test.ts +++ b/test/tools/bounding-box-tool/BoundingBoxTool.test.ts @@ -272,9 +272,8 @@ describe('BoundingBoxTool', () => { }); it('should have correct input schema', async () => { - const { BoundingBoxSchema } = await import( - '../../../src/tools/bounding-box-tool/BoundingBoxTool.input.schema.js' - ); + const { BoundingBoxSchema } = + await import('../../../src/tools/bounding-box-tool/BoundingBoxTool.input.schema.js'); expect(BoundingBoxSchema).toBeDefined(); expect(BoundingBoxSchema.shape.geojson).toBeDefined(); }); diff --git a/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts b/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts index 1245d74..1ac4e98 100644 --- a/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts +++ b/test/tools/bounding-box-tool/CountryBoundingBoxTool.test.ts @@ -150,9 +150,8 @@ describe('CountryBoundingBoxTool', () => { }); it('should have correct input schema', async () => { - const { CountryBoundingBoxSchema } = await import( - '../../../src/tools/bounding-box-tool/CountryBoundingBoxTool.input.schema.js' - ); + const { CountryBoundingBoxSchema } = + await import('../../../src/tools/bounding-box-tool/CountryBoundingBoxTool.input.schema.js'); expect(CountryBoundingBoxSchema).toBeDefined(); }); }); diff --git a/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts b/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts index a45c60d..083fe92 100644 --- a/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts +++ b/test/tools/coordinate-conversion-tool/CoordinateConversionTool.test.ts @@ -20,9 +20,8 @@ describe('CoordinateConversionTool', () => { }); it('should have correct input schema', async () => { - const { CoordinateConversionSchema } = await import( - '../../../src/tools/coordinate-conversion-tool/CoordinateConversionTool.input.schema.js' - ); + const { CoordinateConversionSchema } = + await import('../../../src/tools/coordinate-conversion-tool/CoordinateConversionTool.input.schema.js'); expect(CoordinateConversionSchema).toBeDefined(); }); }); diff --git a/test/tools/create-style-tool/CreateStyleTool.test.ts b/test/tools/create-style-tool/CreateStyleTool.test.ts index 341e3d1..1304440 100644 --- a/test/tools/create-style-tool/CreateStyleTool.test.ts +++ b/test/tools/create-style-tool/CreateStyleTool.test.ts @@ -29,9 +29,8 @@ describe('CreateStyleTool', () => { }); it('should have correct input schema', async () => { - const { CreateStyleInputSchema } = await import( - '../../../src/tools/create-style-tool/CreateStyleTool.input.schema.js' - ); + const { CreateStyleInputSchema } = + await import('../../../src/tools/create-style-tool/CreateStyleTool.input.schema.js'); expect(CreateStyleInputSchema).toBeDefined(); }); }); diff --git a/test/tools/create-token-tool/CreateTokenTool.test.ts b/test/tools/create-token-tool/CreateTokenTool.test.ts index 1542202..5526967 100644 --- a/test/tools/create-token-tool/CreateTokenTool.test.ts +++ b/test/tools/create-token-tool/CreateTokenTool.test.ts @@ -44,9 +44,8 @@ describe('CreateTokenTool', () => { }); it('should have correct input schema', async () => { - const { CreateTokenSchema } = await import( - '../../../src/tools/create-token-tool/CreateTokenTool.input.schema.js' - ); + const { CreateTokenSchema } = + await import('../../../src/tools/create-token-tool/CreateTokenTool.input.schema.js'); expect(CreateTokenSchema).toBeDefined(); }); }); diff --git a/test/tools/delete-style-tool/DeleteStyleTool.test.ts b/test/tools/delete-style-tool/DeleteStyleTool.test.ts index 6a21b08..7c576a5 100644 --- a/test/tools/delete-style-tool/DeleteStyleTool.test.ts +++ b/test/tools/delete-style-tool/DeleteStyleTool.test.ts @@ -29,9 +29,8 @@ describe('DeleteStyleTool', () => { }); it('should have correct input schema', async () => { - const { DeleteStyleSchema } = await import( - '../../../src/tools/delete-style-tool/DeleteStyleTool.input.schema.js' - ); + const { DeleteStyleSchema } = + await import('../../../src/tools/delete-style-tool/DeleteStyleTool.input.schema.js'); expect(DeleteStyleSchema).toBeDefined(); }); }); diff --git a/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts b/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts index ff863a3..a022d2b 100644 --- a/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts +++ b/test/tools/geojson-preview-tool/GeojsonPreviewTool.test.ts @@ -19,9 +19,8 @@ describe('GeojsonPreviewTool', () => { }); it('should have correct input schema', async () => { - const { GeojsonPreviewSchema } = await import( - '../../../src/tools/geojson-preview-tool/GeojsonPreviewTool.input.schema.js' - ); + const { GeojsonPreviewSchema } = + await import('../../../src/tools/geojson-preview-tool/GeojsonPreviewTool.input.schema.js'); expect(GeojsonPreviewSchema).toBeDefined(); }); }); diff --git a/test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts b/test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts deleted file mode 100644 index b305358..0000000 --- a/test/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.test.ts +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) Mapbox, Inc. -// Licensed under the MIT License. - -import { describe, expect, it } from 'vitest'; -import { GetMapboxDocSourceTool } from '../../../src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.js'; -import { setupHttpRequest } from '../../utils/httpPipelineUtils.js'; - -describe('GetMapboxDocSourceTool', () => { - it('should have correct name and description', () => { - const { httpRequest } = setupHttpRequest(); - const tool = new GetMapboxDocSourceTool({ httpRequest }); - - expect(tool.name).toBe('get_latest_mapbox_docs_tool'); - expect(tool.description).toContain( - 'Get the latest official Mapbox documentation' - ); - expect(tool.description).toContain('Always up-to-date'); - expect(tool.description).toContain('instead of web search'); - }); - - it('should successfully fetch documentation content', async () => { - const mockContent = `# Mapbox Documentation - -This is the Mapbox developer documentation for LLMs. - -## Web SDKs -- Mapbox GL JS for interactive maps -- Mobile SDKs for iOS and Android - -## APIs -- Geocoding API for address search -- Directions API for routing`; - const { httpRequest, mockHttpRequest } = setupHttpRequest({ - ok: true, - status: 200, - text: () => Promise.resolve(mockContent) - }); - - const tool = new GetMapboxDocSourceTool({ httpRequest }); - const result = await tool.run({}); - - expect(mockHttpRequest).toHaveBeenCalledWith( - 'https://docs.mapbox.com/llms.txt', - { - headers: { - Accept: 'text/markdown, text/plain;q=0.9, */*;q=0.8', - 'User-Agent': 'TestServer/1.0.0 (default, no-tag, abcdef)' - } - } - ); - expect(result.content).toHaveLength(1); - expect(result.content[0].type).toBe('text'); - - if (result.content[0].type === 'text') { - expect(result.content[0].text).toBe(mockContent); - } - expect(result.isError).toBe(false); - }); - - it('should handle HTTP errors', async () => { - const { httpRequest } = setupHttpRequest({ - ok: false, - status: 404, - statusText: 'Not Found' - }); - - const tool = new GetMapboxDocSourceTool({ httpRequest }); - - const result = await tool.run({}); - - expect(result.isError).toBe(true); - expect(result.content[0].type).toBe('text'); - - if (result.content[0].type === 'text') { - expect(result.content[0].text).toContain( - 'Failed to fetch Mapbox documentation' - ); - expect(result.content[0].text).toContain('Not Found'); - } - }); - - it('should handle network errors', async () => { - const { httpRequest } = setupHttpRequest({ - text: () => Promise.reject(new Error('Network error')) - }); - - const tool = new GetMapboxDocSourceTool({ httpRequest }); - const result = await tool.run({}); - - expect(result.isError).toBe(true); - expect(result.content[0].type).toBe('text'); - - if (result.content[0].type === 'text') { - expect(result.content[0].text).toContain( - 'Failed to fetch Mapbox documentation' - ); - expect(result.content[0].text).toContain('Network error'); - } - }); - - it('should handle unknown errors', async () => { - const { httpRequest } = setupHttpRequest({ - text: () => Promise.reject(new Error('Unknown error occurred')) - }); - - const tool = new GetMapboxDocSourceTool({ httpRequest }); - const result = await tool.run({}); - - expect(result.isError).toBe(true); - expect(result.content[0].type).toBe('text'); - - if (result.content[0].type === 'text') { - expect(result.content[0].text).toContain( - 'Failed to fetch Mapbox documentation' - ); - expect(result.content[0].text).toContain('Unknown error occurred'); - } - }); - - it('should work with empty input object', async () => { - const mockContent = 'Test documentation content'; - - const { httpRequest } = setupHttpRequest({ - ok: true, - status: 200, - text: () => Promise.resolve(mockContent) - }); - - const tool = new GetMapboxDocSourceTool({ httpRequest }); - - const result = await tool.run({}); - - expect(result.isError).toBe(false); - expect(result.content).toHaveLength(1); - expect(result.content[0].type).toBe('text'); - }); -}); diff --git a/test/tools/list-styles-tool/ListStylesTool.test.ts b/test/tools/list-styles-tool/ListStylesTool.test.ts index 915ffc7..de9e37c 100644 --- a/test/tools/list-styles-tool/ListStylesTool.test.ts +++ b/test/tools/list-styles-tool/ListStylesTool.test.ts @@ -30,9 +30,8 @@ describe('ListStylesTool', () => { }); it('should have correct input schema', async () => { - const { ListStylesSchema } = await import( - '../../../src/tools/list-styles-tool/ListStylesTool.input.schema.js' - ); + const { ListStylesSchema } = + await import('../../../src/tools/list-styles-tool/ListStylesTool.input.schema.js'); expect(ListStylesSchema).toBeDefined(); }); }); diff --git a/test/tools/list-tokens-tool/ListTokensTool.test.ts b/test/tools/list-tokens-tool/ListTokensTool.test.ts index 1af785c..380af90 100644 --- a/test/tools/list-tokens-tool/ListTokensTool.test.ts +++ b/test/tools/list-tokens-tool/ListTokensTool.test.ts @@ -43,9 +43,8 @@ describe('ListTokensTool', () => { }); it('should have correct input schema', async () => { - const { ListTokensSchema } = await import( - '../../../src/tools/list-tokens-tool/ListTokensTool.input.schema.js' - ); + const { ListTokensSchema } = + await import('../../../src/tools/list-tokens-tool/ListTokensTool.input.schema.js'); expect(ListTokensSchema).toBeDefined(); }); }); diff --git a/test/tools/preview-style-tool/PreviewStyleTool.test.ts b/test/tools/preview-style-tool/PreviewStyleTool.test.ts index 20e29ed..7a4eecf 100644 --- a/test/tools/preview-style-tool/PreviewStyleTool.test.ts +++ b/test/tools/preview-style-tool/PreviewStyleTool.test.ts @@ -21,9 +21,8 @@ describe('PreviewStyleTool', () => { }); it('should have correct input schema', async () => { - const { PreviewStyleSchema } = await import( - '../../../src/tools/preview-style-tool/PreviewStyleTool.input.schema.js' - ); + const { PreviewStyleSchema } = + await import('../../../src/tools/preview-style-tool/PreviewStyleTool.input.schema.js'); expect(PreviewStyleSchema).toBeDefined(); }); }); diff --git a/test/tools/retrieve-style-tool/RetrieveStyleTool.test.ts b/test/tools/retrieve-style-tool/RetrieveStyleTool.test.ts index 4d0858b..540965d 100644 --- a/test/tools/retrieve-style-tool/RetrieveStyleTool.test.ts +++ b/test/tools/retrieve-style-tool/RetrieveStyleTool.test.ts @@ -29,9 +29,8 @@ describe('RetrieveStyleTool', () => { }); it('should have correct input schema', async () => { - const { RetrieveStyleSchema } = await import( - '../../../src/tools/retrieve-style-tool/RetrieveStyleTool.input.schema.js' - ); + const { RetrieveStyleSchema } = + await import('../../../src/tools/retrieve-style-tool/RetrieveStyleTool.input.schema.js'); expect(RetrieveStyleSchema).toBeDefined(); }); }); diff --git a/test/tools/toolRegistry.test.ts b/test/tools/toolRegistry.test.ts index 0acc821..1a7aa41 100644 --- a/test/tools/toolRegistry.test.ts +++ b/test/tools/toolRegistry.test.ts @@ -5,7 +5,6 @@ import { describe, it, expect } from 'vitest'; import { getCoreTools, getElicitationTools, - getResourceFallbackTools, getAllTools } from '../../src/tools/toolRegistry.js'; @@ -21,7 +20,6 @@ describe('Tool Registry', () => { const coreTools = getCoreTools(); const toolNames = coreTools.map((tool) => tool.name); - // Verify some expected core tools expect(toolNames).toContain('list_styles_tool'); expect(toolNames).toContain('create_style_tool'); expect(toolNames).toContain('style_builder_tool'); @@ -32,20 +30,9 @@ describe('Tool Registry', () => { const coreTools = getCoreTools(); const toolNames = coreTools.map((tool) => tool.name); - // These tools are currently in CORE_TOOLS - // They will move to ELICITATION_TOOLS when elicitation support is added expect(toolNames).toContain('preview_style_tool'); expect(toolNames).toContain('style_comparison_tool'); }); - - it('should not include resource fallback tools', () => { - const coreTools = getCoreTools(); - const toolNames = coreTools.map((tool) => tool.name); - - // Resource fallback tools should not be in core - expect(toolNames).not.toContain('get_reference_tool'); - expect(toolNames).not.toContain('get_latest_mapbox_docs_tool'); - }); }); describe('getElicitationTools', () => { @@ -58,33 +45,6 @@ describe('Tool Registry', () => { const elicitationTools = getElicitationTools(); expect(elicitationTools.length).toBe(0); }); - - it('should be ready for future elicitation-dependent tools', () => { - // This test documents that the infrastructure is in place - // When elicitation support is added, tools can be moved here - const elicitationTools = getElicitationTools(); - expect(Array.isArray(elicitationTools)).toBe(true); - }); - }); - - describe('getResourceFallbackTools', () => { - it('should return an array of resource fallback tools', () => { - const resourceFallbackTools = getResourceFallbackTools(); - expect(Array.isArray(resourceFallbackTools)).toBe(true); - expect(resourceFallbackTools.length).toBe(2); - }); - - it('should include get_reference_tool', () => { - const resourceFallbackTools = getResourceFallbackTools(); - const toolNames = resourceFallbackTools.map((tool) => tool.name); - expect(toolNames).toContain('get_reference_tool'); - }); - - it('should include get_latest_mapbox_docs_tool', () => { - const resourceFallbackTools = getResourceFallbackTools(); - const toolNames = resourceFallbackTools.map((tool) => tool.name); - expect(toolNames).toContain('get_latest_mapbox_docs_tool'); - }); }); describe('getAllTools', () => { @@ -92,13 +52,8 @@ describe('Tool Registry', () => { const allTools = getAllTools(); const coreTools = getCoreTools(); const elicitationTools = getElicitationTools(); - const resourceFallbackTools = getResourceFallbackTools(); - expect(allTools.length).toBe( - coreTools.length + - elicitationTools.length + - resourceFallbackTools.length - ); + expect(allTools.length).toBe(coreTools.length + elicitationTools.length); }); it('should have no duplicate tools', () => { @@ -109,17 +64,12 @@ describe('Tool Registry', () => { expect(toolNames.length).toBe(uniqueToolNames.size); }); - it('should include tools from all categories', () => { + it('should include expected tools', () => { const allTools = getAllTools(); const toolNames = allTools.map((tool) => tool.name); - // Core tools expect(toolNames).toContain('list_styles_tool'); expect(toolNames).toContain('preview_style_tool'); - // Resource fallback tools - expect(toolNames).toContain('get_reference_tool'); - expect(toolNames).toContain('get_latest_mapbox_docs_tool'); - // Note: No elicitation tools yet (empty array) }); }); @@ -135,31 +85,5 @@ describe('Tool Registry', () => { ); expect(overlap).toEqual([]); }); - - it('should have no overlap between core and resource fallback tools', () => { - const coreToolNames = getCoreTools().map((tool) => tool.name); - const resourceFallbackToolNames = getResourceFallbackTools().map( - (tool) => tool.name - ); - - const overlap = coreToolNames.filter((name) => - resourceFallbackToolNames.includes(name) - ); - expect(overlap).toEqual([]); - }); - - it('should have no overlap between elicitation and resource fallback tools', () => { - const elicitationToolNames = getElicitationTools().map( - (tool) => tool.name - ); - const resourceFallbackToolNames = getResourceFallbackTools().map( - (tool) => tool.name - ); - - const overlap = elicitationToolNames.filter((name) => - resourceFallbackToolNames.includes(name) - ); - expect(overlap).toEqual([]); - }); }); }); diff --git a/test/tools/update-style-tool/UpdateStyleTool.test.ts b/test/tools/update-style-tool/UpdateStyleTool.test.ts index 1f59c20..f196c29 100644 --- a/test/tools/update-style-tool/UpdateStyleTool.test.ts +++ b/test/tools/update-style-tool/UpdateStyleTool.test.ts @@ -29,9 +29,8 @@ describe('UpdateStyleTool', () => { }); it('should have correct input schema', async () => { - const { UpdateStyleInputSchema } = await import( - '../../../src/tools/update-style-tool/UpdateStyleTool.input.schema.js' - ); + const { UpdateStyleInputSchema } = + await import('../../../src/tools/update-style-tool/UpdateStyleTool.input.schema.js'); expect(UpdateStyleInputSchema).toBeDefined(); }); });