From 992585ffef1e1bdf854718cb11924f3fc35faf8d Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 27 Oct 2025 16:36:26 -0400 Subject: [PATCH 1/2] [cursor] Adding bug fixes for known Cursor issues --- CLAUDE.md | 1 + README.md | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/index.ts | 8 ++++ 3 files changed, 116 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 05cd93e..10a87a5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,6 +71,7 @@ This file provides Claude and developers with essential context, commands, and s ## Known Issues & Warnings +- **Cursor + OpenAI models compatibility issue** - ALL OpenAI models (GPT-4, GPT-3.5, o1, o1-mini) fail with `[invalid_argument]` errors in Cursor when using `create_style_tool` and `update_style_tool` (works fine in VS Code, works fine with Claude in Cursor). Root cause: Cursor can't handle tools with complex input schemas when used with OpenAI models. **Workaround:** Set `CURSOR_OPENAI_MODE=true` to auto-disable the problematic tools. You'll still have 15/17 tools working. - Large GeoJSON files may cause slow performance in preview tools - Always check token scopes if a tool fails with authentication errors - Use `VERBOSE_ERRORS=true` for detailed error output diff --git a/README.md b/README.md index d80fa40..8227419 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,10 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 - [Creating New Tools](#creating-new-tools) - [Environment Variables](#environment-variables) - [VERBOSE_ERRORS](#verbose_errors) + - [CURSOR_OPENAI_MODE](#cursor_openai_mode) + - [Troubleshooting](#troubleshooting) + - [Cursor + OpenAI Models Issues](#cursor--openai-models-issues) + - [General Troubleshooting](#general-troubleshooting) - [Contributing](#contributing) ## Quick Start @@ -558,6 +562,109 @@ Set `VERBOSE_ERRORS=true` to get detailed error messages from the MCP server. Th By default, the server returns generic error messages. With verbose errors enabled, you'll receive the actual error details, which can help diagnose API connection issues, invalid parameters, or other problems. +#### CURSOR_OPENAI_MODE + +Set `CURSOR_OPENAI_MODE=true` when using **any OpenAI model (GPT-4, GPT-3.5, o1, o1-mini) in Cursor**. This is a simple workaround for Cursor's bug with OpenAI models and complex tool schemas. + +**What it does:** + +- Automatically disables `create_style_tool` and `update_style_tool` +- These tools have complex input schemas that break Cursor's OpenAI integration +- You'll still have 15 out of 17 tools working (all read/query/preview operations) + +**When to use:** + +- ✅ Using GPT-4, GPT-3.5, o1, or o1-mini in Cursor +- ❌ Not needed for Claude models in Cursor (all tools work) +- ❌ Not needed in VS Code (all tools work with all models) + +**Example:** + +```json +{ + "mcpServers": { + "mapbox-devkit": { + "env": { + "MAPBOX_ACCESS_TOKEN": "your-token", + "CURSOR_OPENAI_MODE": "true" + } + } + } +} +``` + +## Troubleshooting + +### Cursor + OpenAI Models Issues + +**Problem:** When using **any OpenAI model (GPT-4, GPT-3.5, o1, o1-mini)** in Cursor, the `create_style_tool` and `update_style_tool` cause failures with `[invalid_argument]` errors. + +**Example error:** + +``` +ConnectError: [invalid_argument] Error +The model returned an error. Try disabling MCP servers, or switch models. +``` + +**Cause:** This is a Cursor-specific bug with o1 model MCP integration. The same server works fine with o1 in VS Code and other MCP clients. + +**Root Cause:** Cursor's integration with OpenAI models fails when tools have complex input schemas with `.passthrough()` (like `create_style_tool` and `update_style_tool` which accept full Mapbox Style Specification objects). The error is: `[AiService] streamResponse ConnectError: [invalid_argument]` + +**Affected:** + +- ❌ Cursor + GPT-4 - Fails with these 2 tools +- ❌ Cursor + GPT-3.5 - Fails with these 2 tools +- ❌ Cursor + o1/o1-mini - Fails with these 2 tools +- ✅ Cursor + Claude - Works with all tools +- ✅ VS Code + any model - Works with all tools + +**Simple Fix - Use CURSOR_OPENAI_MODE:** +Add `CURSOR_OPENAI_MODE=true` to automatically disable the problematic tools: + +```json +{ + "mcpServers": { + "mapbox-devkit": { + "command": "node", + "args": ["/path/to/dist/esm/index.js"], + "env": { + "MAPBOX_ACCESS_TOKEN": "your-token", + "CURSOR_OPENAI_MODE": "true" + } + } + } +} +``` + +This automatically disables `create_style_tool` and `update_style_tool` which have complex input schemas that break Cursor's OpenAI integration. You'll still have **15 out of 17 tools** working, including all read/query operations. + +**Other Solutions:** + +1. **Use Claude in Cursor** - All 17 tools work perfectly with Claude models in Cursor +2. **Use VS Code** - All OpenAI models work with all 17 tools in VS Code (no workaround needed) +3. **Manually disable tools:** + ```json + { + "args": [ + "/path/to/dist/esm/index.js", + "--disable-tools", + "create_style_tool,update_style_tool" + ] + } + ``` + +**Status:** This is a Cursor bug with how it handles OpenAI models + MCP tools with complex input schemas. The same tools work fine in VS Code. + +### General Troubleshooting + +**Issue:** Tools fail with authentication errors + +**Solution:** Check that your `MAPBOX_ACCESS_TOKEN` has the required scopes for the tool you're using. See the token scopes section above. + +**Issue:** Large GeoJSON files cause slow performance + +**Solution:** The GeoJSON preview tool may be slow with very large files. Consider simplifying geometries or using smaller datasets for preview purposes. + ## Contributing We welcome contributions to the Mapbox Development MCP Server! Please review our standards and guidelines before contributing: diff --git a/src/index.ts b/src/index.ts index d38e577..94ef2b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,6 +16,14 @@ const config = parseToolConfigFromArgs(); // Get and filter tools based on configuration const allTools = getAllTools(); + +// Cursor + OpenAI models have issues with complex input schemas (create_style_tool, update_style_tool) +// This provides an easy workaround +const cursorOpenAiMode = process.env.CURSOR_OPENAI_MODE === 'true'; +if (cursorOpenAiMode && !config.disabledTools) { + config.disabledTools = ['create_style_tool', 'update_style_tool']; +} + const enabledTools = filterTools(allTools, config); // Create an MCP server From ba1813a7e9d0d1e58f8a11322a1d7db44d2bd5a8 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Mon, 27 Oct 2025 18:12:39 -0400 Subject: [PATCH 2/2] [cursor] Adding schema fixes for known GPT/Cursor issues --- CLAUDE.md | 1 - README.md | 96 ------------------- src/index.ts | 8 -- .../CreateStyleTool.input.schema.ts | 35 +++---- .../create-style-tool/CreateStyleTool.ts | 18 ++-- .../UpdateStyleTool.input.schema.ts | 28 ++---- .../create-style-tool/CreateStyleTool.test.ts | 20 ++-- .../update-style-tool/UpdateStyleTool.test.ts | 4 +- 8 files changed, 45 insertions(+), 165 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 10a87a5..05cd93e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -71,7 +71,6 @@ This file provides Claude and developers with essential context, commands, and s ## Known Issues & Warnings -- **Cursor + OpenAI models compatibility issue** - ALL OpenAI models (GPT-4, GPT-3.5, o1, o1-mini) fail with `[invalid_argument]` errors in Cursor when using `create_style_tool` and `update_style_tool` (works fine in VS Code, works fine with Claude in Cursor). Root cause: Cursor can't handle tools with complex input schemas when used with OpenAI models. **Workaround:** Set `CURSOR_OPENAI_MODE=true` to auto-disable the problematic tools. You'll still have 15/17 tools working. - Large GeoJSON files may cause slow performance in preview tools - Always check token scopes if a tool fails with authentication errors - Use `VERBOSE_ERRORS=true` for detailed error output diff --git a/README.md b/README.md index 8227419..5ac5456 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,7 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 - [Creating New Tools](#creating-new-tools) - [Environment Variables](#environment-variables) - [VERBOSE_ERRORS](#verbose_errors) - - [CURSOR_OPENAI_MODE](#cursor_openai_mode) - [Troubleshooting](#troubleshooting) - - [Cursor + OpenAI Models Issues](#cursor--openai-models-issues) - - [General Troubleshooting](#general-troubleshooting) - [Contributing](#contributing) ## Quick Start @@ -562,101 +559,8 @@ Set `VERBOSE_ERRORS=true` to get detailed error messages from the MCP server. Th By default, the server returns generic error messages. With verbose errors enabled, you'll receive the actual error details, which can help diagnose API connection issues, invalid parameters, or other problems. -#### CURSOR_OPENAI_MODE - -Set `CURSOR_OPENAI_MODE=true` when using **any OpenAI model (GPT-4, GPT-3.5, o1, o1-mini) in Cursor**. This is a simple workaround for Cursor's bug with OpenAI models and complex tool schemas. - -**What it does:** - -- Automatically disables `create_style_tool` and `update_style_tool` -- These tools have complex input schemas that break Cursor's OpenAI integration -- You'll still have 15 out of 17 tools working (all read/query/preview operations) - -**When to use:** - -- ✅ Using GPT-4, GPT-3.5, o1, or o1-mini in Cursor -- ❌ Not needed for Claude models in Cursor (all tools work) -- ❌ Not needed in VS Code (all tools work with all models) - -**Example:** - -```json -{ - "mcpServers": { - "mapbox-devkit": { - "env": { - "MAPBOX_ACCESS_TOKEN": "your-token", - "CURSOR_OPENAI_MODE": "true" - } - } - } -} -``` - ## Troubleshooting -### Cursor + OpenAI Models Issues - -**Problem:** When using **any OpenAI model (GPT-4, GPT-3.5, o1, o1-mini)** in Cursor, the `create_style_tool` and `update_style_tool` cause failures with `[invalid_argument]` errors. - -**Example error:** - -``` -ConnectError: [invalid_argument] Error -The model returned an error. Try disabling MCP servers, or switch models. -``` - -**Cause:** This is a Cursor-specific bug with o1 model MCP integration. The same server works fine with o1 in VS Code and other MCP clients. - -**Root Cause:** Cursor's integration with OpenAI models fails when tools have complex input schemas with `.passthrough()` (like `create_style_tool` and `update_style_tool` which accept full Mapbox Style Specification objects). The error is: `[AiService] streamResponse ConnectError: [invalid_argument]` - -**Affected:** - -- ❌ Cursor + GPT-4 - Fails with these 2 tools -- ❌ Cursor + GPT-3.5 - Fails with these 2 tools -- ❌ Cursor + o1/o1-mini - Fails with these 2 tools -- ✅ Cursor + Claude - Works with all tools -- ✅ VS Code + any model - Works with all tools - -**Simple Fix - Use CURSOR_OPENAI_MODE:** -Add `CURSOR_OPENAI_MODE=true` to automatically disable the problematic tools: - -```json -{ - "mcpServers": { - "mapbox-devkit": { - "command": "node", - "args": ["/path/to/dist/esm/index.js"], - "env": { - "MAPBOX_ACCESS_TOKEN": "your-token", - "CURSOR_OPENAI_MODE": "true" - } - } - } -} -``` - -This automatically disables `create_style_tool` and `update_style_tool` which have complex input schemas that break Cursor's OpenAI integration. You'll still have **15 out of 17 tools** working, including all read/query operations. - -**Other Solutions:** - -1. **Use Claude in Cursor** - All 17 tools work perfectly with Claude models in Cursor -2. **Use VS Code** - All OpenAI models work with all 17 tools in VS Code (no workaround needed) -3. **Manually disable tools:** - ```json - { - "args": [ - "/path/to/dist/esm/index.js", - "--disable-tools", - "create_style_tool,update_style_tool" - ] - } - ``` - -**Status:** This is a Cursor bug with how it handles OpenAI models + MCP tools with complex input schemas. The same tools work fine in VS Code. - -### General Troubleshooting - **Issue:** Tools fail with authentication errors **Solution:** Check that your `MAPBOX_ACCESS_TOKEN` has the required scopes for the tool you're using. See the token scopes section above. diff --git a/src/index.ts b/src/index.ts index 94ef2b6..d38e577 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,14 +16,6 @@ const config = parseToolConfigFromArgs(); // Get and filter tools based on configuration const allTools = getAllTools(); - -// Cursor + OpenAI models have issues with complex input schemas (create_style_tool, update_style_tool) -// This provides an easy workaround -const cursorOpenAiMode = process.env.CURSOR_OPENAI_MODE === 'true'; -if (cursorOpenAiMode && !config.disabledTools) { - config.disabledTools = ['create_style_tool', 'update_style_tool']; -} - const enabledTools = filterTools(allTools, config); // Create an MCP server diff --git a/src/tools/create-style-tool/CreateStyleTool.input.schema.ts b/src/tools/create-style-tool/CreateStyleTool.input.schema.ts index dd5c8b7..a20c5f2 100644 --- a/src/tools/create-style-tool/CreateStyleTool.input.schema.ts +++ b/src/tools/create-style-tool/CreateStyleTool.input.schema.ts @@ -3,30 +3,17 @@ import { z } from 'zod'; -// INPUT Schema - Simplified schema for creating styles -// Only defines the essential required fields. Additional Mapbox Style Specification -// properties (sources, layers, sprite, glyphs, etc.) are allowed via .passthrough() +// INPUT Schema - Accepts a complete Mapbox Style Specification as a generic object +// This avoids complex schemas with .passthrough() that break some MCP clients (Cursor + OpenAI) // Full spec: https://docs.mapbox.com/mapbox-gl-js/style-spec/ -export const MapboxStyleInputSchema = z - .object({ - name: z.string().describe('Human-readable name for the style (REQUIRED)'), - version: z - .literal(8) - .describe('Style specification version number. Must be 8'), - // Note: The Mapbox API requires at minimum 'version', 'name', 'sources', and 'layers'. - // We only validate 'name' and 'version' here. Other fields like sources, layers, sprite, - // glyphs, center, zoom, etc. are passed through without explicit validation to avoid - // overwhelming clients with the full 18+ field schema. - sources: z - .record(z.any()) - .optional() - .describe('Data source specifications'), - layers: z.array(z.any()).optional().describe('Layers in draw order') - }) - .passthrough() - .describe( - 'Mapbox style input. Accepts standard Mapbox Style Specification properties. Only key fields are validated; additional properties (center, zoom, bearing, pitch, sprite, glyphs, metadata, etc.) are accepted but not explicitly defined to keep schema manageable.' - ); +export const CreateStyleInputSchema = z.object({ + name: z.string().describe('Human-readable name for the style'), + style: z + .record(z.any()) + .describe( + 'Complete Mapbox Style Specification object. Must include: version (8), sources, layers. Optional: sprite, glyphs, center, zoom, bearing, pitch, metadata, etc. See https://docs.mapbox.com/mapbox-gl-js/style-spec/' + ) +}); // Type exports -export type MapboxStyleInput = z.infer; +export type CreateStyleInput = z.infer; diff --git a/src/tools/create-style-tool/CreateStyleTool.ts b/src/tools/create-style-tool/CreateStyleTool.ts index edf0f90..7e6ecf7 100644 --- a/src/tools/create-style-tool/CreateStyleTool.ts +++ b/src/tools/create-style-tool/CreateStyleTool.ts @@ -7,8 +7,8 @@ import { getUserNameFromToken } from '../../utils/jwtUtils.js'; import { filterExpandedMapboxStyles } from '../../utils/styleUtils.js'; import { MapboxApiBasedTool } from '../MapboxApiBasedTool.js'; import { - MapboxStyleInputSchema, - MapboxStyleInput + CreateStyleInputSchema, + CreateStyleInput } from './CreateStyleTool.input.schema.js'; import { MapboxStyleOutput, @@ -16,7 +16,7 @@ import { } from './CreateStyleTool.output.schema.js'; export class CreateStyleTool extends MapboxApiBasedTool< - typeof MapboxStyleInputSchema, + typeof CreateStyleInputSchema, typeof MapboxStyleOutputSchema > { name = 'create_style_tool'; @@ -31,25 +31,31 @@ export class CreateStyleTool extends MapboxApiBasedTool< constructor(params: { httpRequest: HttpRequest }) { super({ - inputSchema: MapboxStyleInputSchema, + inputSchema: CreateStyleInputSchema, outputSchema: MapboxStyleOutputSchema, httpRequest: params.httpRequest }); } protected async execute( - input: MapboxStyleInput, + input: CreateStyleInput, accessToken?: string ): Promise { const username = getUserNameFromToken(accessToken); const url = `${MapboxApiBasedTool.mapboxApiEndpoint}styles/v1/${username}?access_token=${accessToken}`; + // Merge name into style object for API request + const payload = { + ...input.style, + name: input.name + }; + const response = await this.httpRequest(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(input) + body: JSON.stringify(payload) }); if (!response.ok) { diff --git a/src/tools/update-style-tool/UpdateStyleTool.input.schema.ts b/src/tools/update-style-tool/UpdateStyleTool.input.schema.ts index c16c385..ef1dcbf 100644 --- a/src/tools/update-style-tool/UpdateStyleTool.input.schema.ts +++ b/src/tools/update-style-tool/UpdateStyleTool.input.schema.ts @@ -3,29 +3,17 @@ import { z } from 'zod'; -// Simplified Mapbox Style Input Schema for updates -// Only defines essential fields. Additional properties are accepted via .passthrough() -export const MapboxStyleInputSchema = z - .object({ - name: z.string().optional().describe('Human-readable name for the style'), - version: z.literal(8).optional().describe('Style specification version'), - sources: z - .record(z.any()) - .optional() - .describe('Data source specifications'), - layers: z.array(z.any()).optional().describe('Layers in draw order') - }) - .passthrough() - .describe( - 'Mapbox style properties to update. Accepts standard Mapbox Style Specification properties.' - ); - +// INPUT Schema - Accepts a complete Mapbox Style Specification as a generic object +// This avoids complex schemas with .passthrough() that break some MCP clients (Cursor + OpenAI) export const UpdateStyleInputSchema = z.object({ styleId: z.string().describe('Style ID to update'), name: z.string().optional().describe('New name for the style'), - style: MapboxStyleInputSchema.optional().describe( - 'Updated Mapbox style specification object' - ) + style: z + .record(z.any()) + .optional() + .describe( + 'Complete Mapbox Style Specification object to update. Must include: version (8), sources, layers. Optional: sprite, glyphs, center, zoom, bearing, pitch, metadata, etc. See https://docs.mapbox.com/mapbox-gl-js/style-spec/' + ) }); export type UpdateStyleInput = z.infer; diff --git a/test/tools/create-style-tool/CreateStyleTool.test.ts b/test/tools/create-style-tool/CreateStyleTool.test.ts index 79df03d..341e3d1 100644 --- a/test/tools/create-style-tool/CreateStyleTool.test.ts +++ b/test/tools/create-style-tool/CreateStyleTool.test.ts @@ -29,10 +29,10 @@ describe('CreateStyleTool', () => { }); it('should have correct input schema', async () => { - const { MapboxStyleInputSchema } = await import( + const { CreateStyleInputSchema } = await import( '../../../src/tools/create-style-tool/CreateStyleTool.input.schema.js' ); - expect(MapboxStyleInputSchema).toBeDefined(); + expect(CreateStyleInputSchema).toBeDefined(); }); }); @@ -50,9 +50,11 @@ describe('CreateStyleTool', () => { await new CreateStyleTool({ httpRequest }).run({ name: 'Test Style', - version: 8, - sources: {}, - layers: [] + style: { + version: 8, + sources: {}, + layers: [] + } }); assertHeadersSent(mockHttpRequest); }); @@ -66,9 +68,11 @@ describe('CreateStyleTool', () => { const result = await new CreateStyleTool({ httpRequest }).run({ name: 'Test Style', - version: 8, - sources: {}, - layers: [] + style: { + version: 8, + sources: {}, + layers: [] + } }); expect(result.isError).toBe(true); diff --git a/test/tools/update-style-tool/UpdateStyleTool.test.ts b/test/tools/update-style-tool/UpdateStyleTool.test.ts index 987815e..1f59c20 100644 --- a/test/tools/update-style-tool/UpdateStyleTool.test.ts +++ b/test/tools/update-style-tool/UpdateStyleTool.test.ts @@ -29,10 +29,10 @@ describe('UpdateStyleTool', () => { }); it('should have correct input schema', async () => { - const { MapboxStyleInputSchema } = await import( + const { UpdateStyleInputSchema } = await import( '../../../src/tools/update-style-tool/UpdateStyleTool.input.schema.js' ); - expect(MapboxStyleInputSchema).toBeDefined(); + expect(UpdateStyleInputSchema).toBeDefined(); }); });