Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"dxt_version": "0.1",
"display_name": "Mapbox MCP Server",
"name": "@mapbox/mcp-server",
"version": "0.8.0",
"version": "0.8.1",
"description": "Mapbox MCP server.",
"author": {
"name": "Mapbox, Inc."
Expand Down
5,142 changes: 2,422 additions & 2,720 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@mapbox/mcp-server",
"version": "0.8.0",
"version": "0.8.1",
"description": "Mapbox MCP server.",
"mcpName": "io.github.mapbox/mcp-server",
"main": "./dist/commonjs/index.js",
Expand Down Expand Up @@ -76,7 +76,7 @@
],
"dependencies": {
"@mcp-ui/server": "^5.13.1",
"@modelcontextprotocol/sdk": "^1.21.1",
"@modelcontextprotocol/sdk": "^1.25.1",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@modelcontextprotocol/sdk 1.25.1 / package.json

Total vulnerabilities: 1

Critical: 0 High: 1 Medium: 0 Low: 0
Vulnerability IDSeverityCVSSFixed inStatus
CVE-2026-0621 HIGH HIGH - - Open

"@opentelemetry/api": "^1.9.0",
"@opentelemetry/auto-instrumentations-node": "^0.56.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.56.0",
Expand Down
54 changes: 0 additions & 54 deletions patches/@modelcontextprotocol+sdk+1.21.1.patch

This file was deleted.

122 changes: 122 additions & 0 deletions patches/@modelcontextprotocol+sdk+1.25.1.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
diff --git a/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js b/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js
index e10bb3d..2e99bee 100644
--- a/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js
+++ b/node_modules/@modelcontextprotocol/sdk/dist/cjs/server/mcp.js
@@ -197,15 +197,20 @@ class McpServer {
return;
}
if (!result.structuredContent) {
- throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Output validation error: Tool ${toolName} has an output schema but no structured content was provided`);
+ // Log warning but don't throw - allow tools to omit structured content
+ console.warn(`[MCP SDK Patch] Output validation warning: Tool ${toolName} has an output schema but no structured content was provided`);
}
- // if the tool has an output schema, validate structured content
- const outputObj = (0, zod_compat_js_1.normalizeObjectSchema)(tool.outputSchema);
- const parseResult = await (0, zod_compat_js_1.safeParseAsync)(outputObj, result.structuredContent);
- if (!parseResult.success) {
- const error = 'error' in parseResult ? parseResult.error : 'Unknown error';
- const errorMessage = (0, zod_compat_js_1.getParseErrorMessage)(error);
- throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage}`);
+ else {
+ // if the tool has an output schema, validate structured content
+ const outputObj = (0, zod_compat_js_1.normalizeObjectSchema)(tool.outputSchema);
+ const parseResult = await (0, zod_compat_js_1.safeParseAsync)(outputObj, result.structuredContent);
+ if (!parseResult.success) {
+ const error = 'error' in parseResult ? parseResult.error : 'Unknown error';
+ const errorMessage = (0, zod_compat_js_1.getParseErrorMessage)(error);
+ // Log warning but don't throw - allow schema mismatches
+ console.warn(`[MCP SDK Patch] Output validation warning: Invalid structured content for tool ${toolName}: ${errorMessage}`);
+ // Keep the structuredContent despite validation failure
+ }
}
}
/**
diff --git a/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js b/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
index 23639ce..75f18b5 100644
--- a/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
+++ b/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js
@@ -85,6 +85,9 @@ export class McpServer {
execution: tool.execution,
_meta: tool._meta
};
+ if (tool.icons) {
+ toolDefinition.icons = tool.icons;
+ }
if (tool.outputSchema) {
const obj = normalizeObjectSchema(tool.outputSchema);
if (obj) {
@@ -194,15 +197,20 @@ export class McpServer {
return;
}
if (!result.structuredContent) {
- throw new McpError(ErrorCode.InvalidParams, `Output validation error: Tool ${toolName} has an output schema but no structured content was provided`);
+ // Log warning but don't throw - allow tools to omit structured content
+ console.warn(`[MCP SDK Patch] Output validation warning: Tool ${toolName} has an output schema but no structured content was provided`);
}
- // if the tool has an output schema, validate structured content
- const outputObj = normalizeObjectSchema(tool.outputSchema);
- const parseResult = await safeParseAsync(outputObj, result.structuredContent);
- if (!parseResult.success) {
- const error = 'error' in parseResult ? parseResult.error : 'Unknown error';
- const errorMessage = getParseErrorMessage(error);
- throw new McpError(ErrorCode.InvalidParams, `Output validation error: Invalid structured content for tool ${toolName}: ${errorMessage}`);
+ else {
+ // if the tool has an output schema, validate structured content
+ const outputObj = normalizeObjectSchema(tool.outputSchema);
+ const parseResult = await safeParseAsync(outputObj, result.structuredContent);
+ if (!parseResult.success) {
+ const error = 'error' in parseResult ? parseResult.error : 'Unknown error';
+ const errorMessage = getParseErrorMessage(error);
+ // Log warning but don't throw - allow schema mismatches
+ console.warn(`[MCP SDK Patch] Output validation warning: Invalid structured content for tool ${toolName}: ${errorMessage}`);
+ // Keep the structuredContent despite validation failure
+ }
}
}
/**
@@ -602,7 +610,7 @@ export class McpServer {
}
return registeredPrompt;
}
- _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, execution, _meta, handler) {
+ _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, execution, _meta, icons, handler) {
// Validate tool name according to SEP specification
validateAndWarnToolName(name);
const registeredTool = {
@@ -613,6 +621,7 @@ export class McpServer {
annotations,
execution,
_meta,
+ icons,
handler: handler,
enabled: true,
disable: () => registeredTool.update({ enabled: false }),
@@ -641,6 +650,8 @@ export class McpServer {
registeredTool.annotations = updates.annotations;
if (typeof updates._meta !== 'undefined')
registeredTool._meta = updates._meta;
+ if (typeof updates.icons !== 'undefined')
+ registeredTool.icons = updates.icons;
if (typeof updates.enabled !== 'undefined')
registeredTool.enabled = updates.enabled;
this.sendToolListChanged();
@@ -690,7 +701,7 @@ export class McpServer {
}
}
const callback = rest[0];
- return this._createRegisteredTool(name, undefined, description, inputSchema, outputSchema, annotations, { taskSupport: 'forbidden' }, undefined, callback);
+ return this._createRegisteredTool(name, undefined, description, inputSchema, outputSchema, annotations, { taskSupport: 'forbidden' }, undefined, undefined, callback);
}
/**
* Registers a tool with a config object and callback.
@@ -699,8 +710,8 @@ export class McpServer {
if (this._registeredTools[name]) {
throw new Error(`Tool ${name} is already registered`);
}
- const { title, description, inputSchema, outputSchema, annotations, _meta } = config;
- return this._createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, { taskSupport: 'forbidden' }, _meta, cb);
+ const { title, description, inputSchema, outputSchema, annotations, _meta, icons } = config;
+ return this._createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, { taskSupport: 'forbidden' }, _meta, icons, cb);
}
prompt(name, ...rest) {
if (this._registeredPrompts[name]) {
69 changes: 48 additions & 21 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,17 @@ import {
ListPromptsRequestSchema,
GetPromptRequestSchema
} from '@modelcontextprotocol/sdk/types.js';
import {
InMemoryTaskStore,
InMemoryTaskMessageQueue
} from '@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js';
import { parseToolConfigFromArgs, filterTools } from './config/toolConfig.js';
import { getAllTools } from './tools/toolRegistry.js';
import { getAllResources } from './resources/resourceRegistry.js';
import { getAllPrompts, getPromptByName } from './prompts/promptRegistry.js';
import { getVersionInfo } from './utils/versionUtils.js';
import { registerOptimizationTask } from './tools/optimization-tool/OptimizationTask.js';
import { httpRequest } from './utils/httpPipeline.js';
import {
initializeTracing,
shutdownTracing,
Expand Down Expand Up @@ -62,6 +68,9 @@ const enabledTools = filterTools(allTools, config);
// Get all resources
const allResources = getAllResources();

// Create task store for async operations
const taskStore = new InMemoryTaskStore();

// Create an MCP server
const server = new McpServer(
{
Expand All @@ -72,16 +81,26 @@ const server = new McpServer(
capabilities: {
tools: {},
resources: {},
prompts: {}
}
prompts: {},
tasks: { requests: { tools: { call: {} } } }
},
taskStore,
taskMessageQueue: new InMemoryTaskMessageQueue()
}
);

// Register enabled tools to the server
enabledTools.forEach((tool) => {
// Skip OptimizationTool as it's registered as a task instead
if (tool.name === 'optimization_tool') {
return;
}
tool.installTo(server);
});

// Register task-based tools
registerOptimizationTask(server, httpRequest);

// Register all resources to the server
allResources.forEach((resource) => {
resource.installTo(server);
Expand All @@ -95,28 +114,36 @@ server.server.setRequestHandler(ListPromptsRequestSchema, async () => {
};
});

server.server.setRequestHandler(GetPromptRequestSchema, async (request) => {
const { name, arguments: args } = request.params;

const prompt = getPromptByName(name);
if (!prompt) {
throw new Error(`Prompt not found: ${name}`);
}
// Type assertion to avoid "Type instantiation is excessively deep" error
// This is a known issue in MCP SDK 1.25.1: https://github.com/modelcontextprotocol/typescript-sdk/issues/985
// TODO: Remove this workaround when SDK fixes their type definitions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(server.server as any).setRequestHandler(
GetPromptRequestSchema,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async (request: any) => {
const { name, arguments: args } = request.params;

const prompt = getPromptByName(name);
if (!prompt) {
throw new Error(`Prompt not found: ${name}`);
}

// Convert args to object for easier access
const argsObj: Record<string, string> = {};
if (args && typeof args === 'object') {
Object.assign(argsObj, args);
}
// Convert args to object for easier access
const argsObj: Record<string, string> = {};
if (args && typeof args === 'object') {
Object.assign(argsObj, args);
}

// Get the prompt messages with filled-in arguments
const messages = prompt.getMessages(argsObj);
// Get the prompt messages with filled-in arguments
const messages = prompt.getMessages(argsObj);

return {
description: prompt.description,
messages
};
});
return {
description: prompt.description,
messages
};
}
);

async function main() {
// Initialize OpenTelemetry tracing if not in test mode
Expand Down
13 changes: 11 additions & 2 deletions src/tools/BaseTool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,17 @@ export abstract class BaseTool<
(this.outputSchema as unknown as z.ZodObject<any>).shape;
}

return server.registerTool(this.name, config, (args, extra) =>
this.run(args, extra)
// Type assertion to avoid "Type instantiation is excessively deep" error
// This is a known issue in MCP SDK 1.25.1: https://github.com/modelcontextprotocol/typescript-sdk/issues/985
// TODO: Remove this workaround when SDK fixes their type definitions
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const serverAny = server as any;

return serverAny.registerTool(
this.name,
config,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(args: any, extra: any) => this.run(args, extra)
);
}

Expand Down
Loading