From 0e3fe76cf655bac6946757be68c0e5b2e79aa0eb Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 5 Nov 2025 10:00:44 -0500 Subject: [PATCH 1/5] [otel] Update DevKit Server docs with OTEL information --- .env.example | 5 + CLAUDE.md | 1 + README.md | 20 +- docs/claude-code-integration.md | 9 +- docs/claude-desktop-integration.md | 9 +- docs/cursor-integration.md | 150 +++++++++++ docs/vscode-integration.md | 239 ++++++++++++++++++ package.json | 4 +- src/index.ts | 12 +- .../GetMapboxDocSourceTool.ts | 1 - src/utils/tracing.ts | 34 ++- 11 files changed, 463 insertions(+), 21 deletions(-) create mode 100644 docs/cursor-integration.md create mode 100644 docs/vscode-integration.md diff --git a/.env.example b/.env.example index 88daead..dd1d330 100644 --- a/.env.example +++ b/.env.example @@ -39,6 +39,11 @@ OTEL_RESOURCE_ATTRIBUTES=service.name=mapbox-mcp-devkit-server,service.version=0 # ⚠️ Do NOT enable with stdio transport - it breaks JSON-RPC communication # OTEL_EXPORTER_CONSOLE_ENABLED=true +# Optional: OTEL diagnostic log level (default: NONE to avoid stdio pollution) +# Set to DEBUG, INFO, WARN, or ERROR for troubleshooting OTEL issues +# ⚠️ Only use for debugging - logs will corrupt stdio transport +# OTEL_LOG_LEVEL=ERROR + # Optional: OTLP authentication headers (for production backends) # OTEL_EXPORTER_OTLP_HEADERS={"Authorization": "Bearer your-token"} diff --git a/CLAUDE.md b/CLAUDE.md index da032fc..b44d8fc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,7 @@ This server includes OpenTelemetry (OTEL) instrumentation for distributed tracin - `OTEL_TRACING_ENABLED` — Set to `false` to explicitly disable tracing even if endpoint is configured - `OTEL_SERVICE_NAME` — Override service name (default: `mapbox-mcp-devkit-server`) - `OTEL_EXPORTER_OTLP_HEADERS` — JSON string of additional headers for OTLP exporter +- `OTEL_LOG_LEVEL` — OTEL diagnostic log level: `NONE` (default), `ERROR`, `WARN`, `INFO`, `DEBUG`, `VERBOSE`. Set to `NONE` to prevent OTEL logs from polluting stdio transport. ### What Gets Traced diff --git a/README.md b/README.md index 6b2d824..eff34d2 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,12 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 - [Coordinate Conversion tool](#coordinate-conversion-tool) - [Bounding Box tool](#bounding-box-tool) - [Resources](#resources) - - [Observability & Tracing](#observability--tracing) + - [Observability \& Tracing](#observability--tracing) + - [Features](#features) + - [Quick Start with Jaeger](#quick-start-with-jaeger) + - [Supported Backends](#supported-backends) + - [Documentation](#documentation) + - [Environment Variables](#environment-variables) - [Development](#development) - [Testing](#testing) - [Tool Snapshot Tests](#tool-snapshot-tests) @@ -35,7 +40,7 @@ https://github.com/user-attachments/assets/8b1b8ef2-9fba-4951-bc9a-beaed4f6aff6 - [Using Node.js](#using-nodejs) - [Using Docker](#using-docker) - [Creating New Tools](#creating-new-tools) - - [Environment Variables](#environment-variables) + - [Environment Variables](#environment-variables-1) - [VERBOSE_ERRORS](#verbose_errors) - [Troubleshooting](#troubleshooting) - [Contributing](#contributing) @@ -48,6 +53,8 @@ Get started by integrating with your preferred AI development environment: - [Claude Code Integration](./docs/claude-code-integration.md) - Command-line development with Claude - [Claude Desktop Integration](./docs/claude-desktop-integration.md) - Desktop application integration +- [Cursor Integration](./docs/cursor-integration.md) - Cursor IDE integration +- [VS Code Integration](./docs/vscode-integration.md) - Visual Studio Code with GitHub Copilot ### DXT Package Distribution @@ -592,11 +599,8 @@ npm test -- --updateSnapshot #### Using Node.js ```sh -# Build -npm run build - -# Inspect -npx @modelcontextprotocol/inspector node dist/esm/index.js +# Run the built image +npm run inspect:build ``` #### Using Docker @@ -606,7 +610,7 @@ npx @modelcontextprotocol/inspector node dist/esm/index.js docker build -t mapbox-mcp-devkit . # Run and inspect the server -npx @modelcontextprotocol/inspector docker run -i --rm --env MAPBOX_ACCESS_TOKEN="YOUR_TOKEN" mapbox-mcp-devkit +npx @modelcontextprotocol/inspector docker run -i --rm --env MAPBOX_ACCESS_TOKEN="YOUR_TOKEN" --env MCP_LOGGING_DISABLE="true" mapbox-mcp-devkit ``` ### Creating New Tools diff --git a/docs/claude-code-integration.md b/docs/claude-code-integration.md index a3d48fb..c12d5da 100644 --- a/docs/claude-code-integration.md +++ b/docs/claude-code-integration.md @@ -60,7 +60,8 @@ Add to your Claude Code MCP configuration: "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here" + "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true" } } } @@ -80,6 +81,8 @@ Add to your Claude Code MCP configuration: "--rm", "-e", "MAPBOX_ACCESS_TOKEN=your_token_here", + "-e", + "MCP_LOGGING_DISABLE": "true", "mapbox-mcp-devkit" ] } @@ -98,7 +101,8 @@ If you want to use a local version (need to clone and build from this repo): "command": "/path/to/your/node", "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here" + "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true" } } } @@ -196,6 +200,7 @@ Enable verbose error reporting by adding the environment variable: "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true", "VERBOSE_ERRORS": "true" } } diff --git a/docs/claude-desktop-integration.md b/docs/claude-desktop-integration.md index 7987263..905cfe8 100644 --- a/docs/claude-desktop-integration.md +++ b/docs/claude-desktop-integration.md @@ -71,7 +71,8 @@ For users who prefer manual configuration or need custom setups, you can configu "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here" + "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true" } } } @@ -91,6 +92,8 @@ For users who prefer manual configuration or need custom setups, you can configu "--rm", "-e", "MAPBOX_ACCESS_TOKEN=your_token_here", + "-e", + "MCP_LOGGING_DISABLE": "true", "mapbox-mcp-devkit" ] } @@ -109,7 +112,8 @@ If you want to use a local version (need to clone and build from this repo): "command": "/path/to/your/node", "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here" + "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true" } } } @@ -180,6 +184,7 @@ Enable verbose error reporting by adding the environment variable: "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here", + "MCP_LOGGING_DISABLE": "true" "VERBOSE_ERRORS": "true" } } diff --git a/docs/cursor-integration.md b/docs/cursor-integration.md new file mode 100644 index 0000000..6117df8 --- /dev/null +++ b/docs/cursor-integration.md @@ -0,0 +1,150 @@ +# Cursor Integration + +This guide explains how to configure Cursor IDE for use with the Mapbox MCP DevKit Server. + +## Requirements + +- [Cursor](https://www.cursor.com/) installed +- Mapbox MCP DevKit Server [built locally](../README.md#development-setup) + +```sh +# from repository root: +# using node +npm run build + +# note your absolute path to node, you will need it for MCP config +# For Mac/Linux +which node +# For Windows +where node + +# or alternatively, using docker +docker build -t mapbox-mcp-devkit . +``` + +## Setup Instructions + +### Configure Cursor to use Mapbox MCP DevKit Server + +1. Go to Cursor Settings/ MCP Tools and click on "Add Custom MCP". +2. Add either of the following MCP config: + - **NPM version** (recommended for simplicity) + + ```json + { + "mcpServers": { + "MapboxDevKit": { + "type": "stdio", + "command": "", + "args": ["-y", "@mapbox/mcp-devkit-server"], + "env": { + "MAPBOX_ACCESS_TOKEN": "", + "MCP_LOGGING_DISABLE": "true" + } + } + } + } + ``` + + - **Docker version** (recommended for isolation) + + ```json + { + "mcpServers": { + "MapboxDevKit": { + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "--env", + "MAPBOX_ACCESS_TOKEN=", + "--env", + "MCP_LOGGING_DISABLE=true", + "mapbox-mcp-devkit" + ] + } + } + } + ``` + + - **Node version** (for local development) + ```json + { + "mcpServers": { + "MapboxDevKit": { + "type": "stdio", + "command": "", + "args": ["/YOUR_PATH_TO_GIT_REPOSITORY/dist/esm/index.js"], + "env": { + "MAPBOX_ACCESS_TOKEN": "", + "MCP_LOGGING_DISABLE": "true" + } + } + } + } + ``` + +3. Click "Save" to apply the configuration. + +## Important Notes + +### Stdio Transport Logging + +The MCP DevKit Server uses stdio (standard input/output) for communication with Cursor. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. + +Both variable names are supported for backwards compatibility: + +- `MCP_LOGGING_DISABLE` (recommended) +- `MCP_DISABLE_LOGGING` (legacy) + +### Token Scopes + +Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. + +### Configuration Options + +Additional environment variables you can set: + +- `OTEL_EXPORTER_OTLP_ENDPOINT` - Enable OpenTelemetry tracing (see [tracing docs](./tracing.md)) +- `OTEL_SERVICE_NAME` - Override service name for tracing +- `MAPBOX_API_ENDPOINT` - Override Mapbox API endpoint (advanced) + +## Troubleshooting + +### Server Not Appearing + +If the Mapbox DevKit Server doesn't appear in Cursor's MCP tools: + +1. Check that your `MAPBOX_ACCESS_TOKEN` is valid +2. Verify the path to `node` or `npx` is correct +3. For Docker: ensure the image is built with `docker images | grep mapbox-mcp-devkit` +4. Check Cursor's logs for any error messages + +### Connection Errors + +If you see JSON-RPC or parsing errors: + +1. Ensure `MCP_LOGGING_DISABLE` is set to `"true"` in your configuration +2. If using Node version, verify the path to `dist/esm/index.js` is correct +3. Run `npm run build` to ensure the latest build is available + +### Tool Execution Failures + +If tools fail to execute: + +1. Verify your Mapbox token has the required scopes (see [README](../README.md)) +2. Check if you're hitting rate limits (429 errors) +3. Enable verbose errors by adding `"VERBOSE_ERRORS": "true"` to the env config + +## Example Usage + +Once configured, you can use natural language to interact with Mapbox tools: + +- "List all my Mapbox styles" +- "Show me the bounding box for San Francisco" +- "Convert these coordinates to lat/lng: -122.4194, 37.7749" +- "Create a new Mapbox style called 'my-custom-map'" + +See the [README](../README.md#example-prompts) for more example prompts. diff --git a/docs/vscode-integration.md b/docs/vscode-integration.md new file mode 100644 index 0000000..6bbfdf1 --- /dev/null +++ b/docs/vscode-integration.md @@ -0,0 +1,239 @@ +# VS Code Integration + +This guide explains how to configure Visual Studio Code for use with the Mapbox MCP DevKit Server. + +## Requirements + +- [Visual Studio Code](https://code.visualstudio.com/) installed +- GitHub Copilot extension installed and configured +- Mapbox MCP DevKit Server built locally + +```sh +# from repository root: +# using node +npm install +npm run build + +# note your absolute path to node, you will need it for MCP config +# For Mac/Linux +which node +# For Windows +where node + +# or alternatively, using docker +docker build -t mapbox-mcp-devkit . +``` + +## Setup Instructions + +### Configure VS Code to use Mapbox MCP DevKit Server + +1. Open your VS Code `settings.json` file: + - **Mac/Linux**: `Cmd+Shift+P` → "Preferences: Open User Settings (JSON)" + - **Windows**: `Ctrl+Shift+P` → "Preferences: Open User Settings (JSON)" + +2. At the top level of the JSON file, add the MCP configuration: + - **NPM version** (recommended for simplicity) + + ```json + "mcp": { + "servers": { + "MapboxDevKit": { + "type": "stdio", + "command": "", + "args": ["-y", "@mapbox/mcp-devkit-server"], + "env": { + "MAPBOX_ACCESS_TOKEN": "", + "MCP_LOGGING_DISABLE": "true" + } + } + } + } + ``` + + - **Docker version** (recommended for isolation) + + ```json + "mcp": { + "servers": { + "MapboxDevKit": { + "type": "stdio", + "command": "docker", + "args": [ + "run", + "-i", + "--rm", + "--env", + "MAPBOX_ACCESS_TOKEN=", + "--env", + "MCP_LOGGING_DISABLE=true", + "mapbox-mcp-devkit" + ] + } + } + } + ``` + + - **Node version** (for local development) + ```json + "mcp": { + "servers": { + "MapboxDevKit": { + "type": "stdio", + "command": "", + "args": [ + "/YOUR_PATH_TO_GIT_REPOSITORY/dist/esm/index.js" + ], + "env": { + "MAPBOX_ACCESS_TOKEN": "", + "MCP_LOGGING_DISABLE": "true" + } + } + } + } + ``` + +3. Save the `settings.json` file. + +4. Restart VS Code to apply the changes. + +### Verify Installation + +After restarting VS Code, you should see "Mapbox DevKit" appear in the GitHub Copilot tools menu or MCP servers list. + +## Important Notes + +### Stdio Transport Logging + +The MCP DevKit Server uses stdio (standard input/output) for communication with VS Code. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. + +Both variable names are supported for backwards compatibility: + +- `MCP_LOGGING_DISABLE` (recommended) +- `MCP_DISABLE_LOGGING` (legacy) + +### Token Scopes + +Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. + +### Configuration Options + +Additional environment variables you can set: + +- `OTEL_EXPORTER_OTLP_ENDPOINT` - Enable OpenTelemetry tracing (see [tracing docs](./tracing.md)) +- `OTEL_SERVICE_NAME` - Override service name for tracing +- `MAPBOX_API_ENDPOINT` - Override Mapbox API endpoint (advanced) + +## Complete Example Configuration + +Here's a complete `settings.json` example with the NPM version: + +```json +{ + "editor.fontSize": 14, + "editor.tabSize": 2, + "mcp": { + "servers": { + "MapboxDevKit": { + "type": "stdio", + "command": "/usr/local/bin/npx", + "args": ["-y", "@mapbox/mcp-devkit-server"], + "env": { + "MAPBOX_ACCESS_TOKEN": "pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbGV4YW1wbGUifQ.example", + "MCP_LOGGING_DISABLE": "true" + } + } + } + } +} +``` + +## Troubleshooting + +### Server Not Appearing + +If the Mapbox DevKit Server doesn't appear in VS Code's MCP servers: + +1. **Check GitHub Copilot**: Ensure GitHub Copilot is installed and active +2. **Verify token**: Check that your `MAPBOX_ACCESS_TOKEN` is valid +3. **Verify paths**: Ensure the path to `node` or `npx` is correct (use absolute paths) +4. **Docker image**: If using Docker, verify the image exists: `docker images | grep mapbox-mcp-devkit` +5. **Check Output**: Open "Output" panel → Select "MCP" from dropdown to see logs + +### Connection Errors / JSON-RPC Parsing Errors + +If you see JSON-RPC or parsing errors in the Output panel: + +1. **Logging disabled**: Ensure `MCP_LOGGING_DISABLE` is set to `"true"` in your configuration +2. **Build fresh**: Run `npm run build` to ensure you have the latest build +3. **Path verification**: For Node version, verify the path to `dist/esm/index.js` is correct and absolute + +### Tool Execution Failures + +If tools fail to execute: + +1. **Token scopes**: Verify your Mapbox token has the required scopes (see [README](../README.md)) +2. **Rate limits**: Check if you're hitting API rate limits (429 errors) +3. **Verbose errors**: Add `"VERBOSE_ERRORS": "true"` to the env config for detailed error messages +4. **Network**: Ensure you can reach `api.mapbox.com` from your network + +### Finding Your NPX Path + +```sh +# Mac/Linux +which npx +# Output example: /usr/local/bin/npx + +# Windows (Command Prompt) +where npx +# Output example: C:\Program Files\nodejs\npx.cmd + +# Windows (PowerShell) +Get-Command npx +# Look for "Source" field in output +``` + +### Finding Your Node Path + +```sh +# Mac/Linux +which node +# Output example: /usr/local/bin/node + +# Windows (Command Prompt) +where node +# Output example: C:\Program Files\nodejs\node.exe + +# Windows (PowerShell) +Get-Command node +# Look for "Source" field in output +``` + +## Example Usage + +Once configured, you can use natural language in GitHub Copilot Chat to interact with Mapbox tools: + +``` +@MapboxDevKit list all my Mapbox styles +``` + +``` +@MapboxDevKit show me the bounding box for Tokyo, Japan +``` + +``` +@MapboxDevKit convert these coordinates to lat/lng: -122.4194, 37.7749 +``` + +``` +@MapboxDevKit create a new Mapbox style called 'dark-mode-map' +``` + +See the [README](../README.md#example-prompts) for more example prompts and available tools. + +## Additional Resources + +- [VS Code MCP Documentation](https://code.visualstudio.com/docs/copilot/mcp) +- [GitHub Copilot Documentation](https://docs.github.com/en/copilot) +- [Mapbox Token Scopes](https://docs.mapbox.com/api/overview/#access-tokens-and-token-scopes) +- [OpenTelemetry Tracing Guide](./tracing.md) diff --git a/package.json b/package.json index e2bc20d..ba31119 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "format": "prettier --check \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", "format:fix": "prettier --write \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", "generate-version": "node scripts/build-helpers.cjs generate-version", - "inspect:build": "npm run build && npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" node dist/esm/index.js", - "inspect:dev": "npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" npx -y tsx src/index.ts", + "inspect:build": "npm run build && npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" -e MCP_LOGGING_DISABLE=true node dist/esm/index.js", + "inspect:dev": "npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" -e MCP_LOGGING_DISABLE=true npx -y tsx src/index.ts", "lint": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\"", "lint:fix": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\" --fix", "prepare": "husky && node .husky/setup-hooks.js", diff --git a/src/index.ts b/src/index.ts index 45f8cde..70d1c5a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,15 +41,15 @@ if (existsSync(envPath)) { envLoadedCount++; } - // Log success if logging is enabled - if (!process.env.MCP_DISABLE_LOGGING) { + // Log success if logging is enabled (check both env var names for compatibility) + if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { console.error( `✓ Loaded ${envLoadedCount} environment variables from ${envPath}` ); } } catch (error) { envLoadError = error instanceof Error ? error : new Error(String(error)); - if (!process.env.MCP_DISABLE_LOGGING) { + if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { console.error( `⚠️ Warning loading .env: ${error instanceof Error ? error.message : String(error)}` ); @@ -92,9 +92,10 @@ resources.forEach((resource) => { }); // MCP-compatible logging functions -// Completely suppress logging when MCP_DISABLE_LOGGING is set (for MCP inspector compatibility) +// Completely suppress logging when MCP_DISABLE_LOGGING or MCP_LOGGING_DISABLE is set (for MCP inspector compatibility) +// Supports both variable names for backwards compatibility function logIfEnabled(level: 'log' | 'warn' | 'error', ...args: unknown[]) { - if (!process.env.MCP_DISABLE_LOGGING) { + if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { console[level](...args); } } @@ -160,6 +161,7 @@ async function main() { OTEL_EXPORTER_CONSOLE_ENABLED: process.env.OTEL_EXPORTER_CONSOLE_ENABLED, OTEL_TRACING_ENABLED: process.env.OTEL_TRACING_ENABLED, MCP_DISABLE_LOGGING: process.env.MCP_DISABLE_LOGGING, + MCP_LOGGING_DISABLE: process.env.MCP_LOGGING_DISABLE, NODE_ENV: process.env.NODE_ENV }); diff --git a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts index ad7cb00..8b758a6 100644 --- a/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts +++ b/src/tools/get-mapbox-doc-source-tool/GetMapboxDocSourceTool.ts @@ -33,7 +33,6 @@ export class GetMapboxDocSourceTool extends BaseTool< } protected async execute( - // eslint-disable-next-line @typescript-eslint/no-unused-vars _input: GetMapboxDocSourceInput ): Promise { try { diff --git a/src/utils/tracing.ts b/src/utils/tracing.ts index 8e64624..38a491b 100644 --- a/src/utils/tracing.ts +++ b/src/utils/tracing.ts @@ -9,11 +9,43 @@ import { ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions'; import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http'; -import { trace, SpanStatusCode, SpanKind, type Span } from '@opentelemetry/api'; +import { + trace, + SpanStatusCode, + SpanKind, + type Span, + diag, + DiagLogLevel +} from '@opentelemetry/api'; import { getVersionInfo } from './versionUtils.js'; import { ATTR_SERVICE_INSTANCE_ID } from '@opentelemetry/semantic-conventions/incubating'; import { type HttpRequest } from './types.js'; +// Suppress OpenTelemetry diagnostic logging IMMEDIATELY to avoid polluting stdio +// This must happen at module load time, before any OTEL operations +// Use OTEL_LOG_LEVEL env var to override if needed for debugging +const configureOtelDiagnostics = () => { + const logLevel = process.env.OTEL_LOG_LEVEL + ? DiagLogLevel[ + process.env.OTEL_LOG_LEVEL.toUpperCase() as keyof typeof DiagLogLevel + ] + : DiagLogLevel.NONE; + + diag.setLogger( + { + verbose: () => {}, + debug: () => {}, + info: () => {}, + warn: () => {}, + error: () => {} + }, + logLevel + ); +}; + +// Configure diagnostics at module load time +configureOtelDiagnostics(); + // Global SDK instance let sdk: NodeSDK | null = null; let isTracingEnabled = false; From f1286caf0d835e5e754907a9eccc7d2c9a6b0304 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 5 Nov 2025 10:23:09 -0500 Subject: [PATCH 2/5] [otel] Update DevKit Server docs with OTEL information --- .env.example | 2 +- docs/cursor-integration.md | 5 ----- docs/vscode-integration.md | 5 ----- src/index.ts | 12 +++++------- 4 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.env.example b/.env.example index dd1d330..130b40b 100644 --- a/.env.example +++ b/.env.example @@ -15,7 +15,7 @@ MAPBOX_ACCESS_TOKEN=your-mapbox-token-here # Disable console logging (recommended when using stdio transport) # Uncomment to enable: -# MCP_DISABLE_LOGGING=true +# MCP_LOGGING_DISABLE=true # ============================================================================= # OpenTelemetry Tracing (Optional) diff --git a/docs/cursor-integration.md b/docs/cursor-integration.md index 6117df8..aaf734f 100644 --- a/docs/cursor-integration.md +++ b/docs/cursor-integration.md @@ -94,11 +94,6 @@ docker build -t mapbox-mcp-devkit . The MCP DevKit Server uses stdio (standard input/output) for communication with Cursor. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. -Both variable names are supported for backwards compatibility: - -- `MCP_LOGGING_DISABLE` (recommended) -- `MCP_DISABLE_LOGGING` (legacy) - ### Token Scopes Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. diff --git a/docs/vscode-integration.md b/docs/vscode-integration.md index 6bbfdf1..c72188d 100644 --- a/docs/vscode-integration.md +++ b/docs/vscode-integration.md @@ -107,11 +107,6 @@ After restarting VS Code, you should see "Mapbox DevKit" appear in the GitHub Co The MCP DevKit Server uses stdio (standard input/output) for communication with VS Code. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. -Both variable names are supported for backwards compatibility: - -- `MCP_LOGGING_DISABLE` (recommended) -- `MCP_DISABLE_LOGGING` (legacy) - ### Token Scopes Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. diff --git a/src/index.ts b/src/index.ts index 70d1c5a..46e52b7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,15 +41,15 @@ if (existsSync(envPath)) { envLoadedCount++; } - // Log success if logging is enabled (check both env var names for compatibility) - if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { + // Log success if logging is enabled + if (!process.env.MCP_LOGGING_DISABLE) { console.error( `✓ Loaded ${envLoadedCount} environment variables from ${envPath}` ); } } catch (error) { envLoadError = error instanceof Error ? error : new Error(String(error)); - if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { + if (!process.env.MCP_LOGGING_DISABLE) { console.error( `⚠️ Warning loading .env: ${error instanceof Error ? error.message : String(error)}` ); @@ -92,10 +92,9 @@ resources.forEach((resource) => { }); // MCP-compatible logging functions -// Completely suppress logging when MCP_DISABLE_LOGGING or MCP_LOGGING_DISABLE is set (for MCP inspector compatibility) -// Supports both variable names for backwards compatibility +// Completely suppress logging when MCP_LOGGING_DISABLE is set (for MCP inspector compatibility) function logIfEnabled(level: 'log' | 'warn' | 'error', ...args: unknown[]) { - if (!process.env.MCP_DISABLE_LOGGING && !process.env.MCP_LOGGING_DISABLE) { + if (!process.env.MCP_LOGGING_DISABLE) { console[level](...args); } } @@ -160,7 +159,6 @@ async function main() { OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_EXPORTER_CONSOLE_ENABLED: process.env.OTEL_EXPORTER_CONSOLE_ENABLED, OTEL_TRACING_ENABLED: process.env.OTEL_TRACING_ENABLED, - MCP_DISABLE_LOGGING: process.env.MCP_DISABLE_LOGGING, MCP_LOGGING_DISABLE: process.env.MCP_LOGGING_DISABLE, NODE_ENV: process.env.NODE_ENV }); From 072bdd6c3bb1dc67b646d1e6b7d1a1ba644e41e0 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 5 Nov 2025 10:27:06 -0500 Subject: [PATCH 3/5] [otel] Update DevKit Server docs with OTEL information --- docs/cursor-integration.md | 42 +++++++++++++++++++------ docs/vscode-integration.md | 64 ++++++++++++++++---------------------- 2 files changed, 59 insertions(+), 47 deletions(-) diff --git a/docs/cursor-integration.md b/docs/cursor-integration.md index aaf734f..be28d1e 100644 --- a/docs/cursor-integration.md +++ b/docs/cursor-integration.md @@ -12,12 +12,6 @@ This guide explains how to configure Cursor IDE for use with the Mapbox MCP DevK # using node npm run build -# note your absolute path to node, you will need it for MCP config -# For Mac/Linux -which node -# For Windows -where node - # or alternatively, using docker docker build -t mapbox-mcp-devkit . ``` @@ -35,7 +29,7 @@ docker build -t mapbox-mcp-devkit . "mcpServers": { "MapboxDevKit": { "type": "stdio", - "command": "", + "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "", @@ -75,8 +69,8 @@ docker build -t mapbox-mcp-devkit . "mcpServers": { "MapboxDevKit": { "type": "stdio", - "command": "", - "args": ["/YOUR_PATH_TO_GIT_REPOSITORY/dist/esm/index.js"], + "command": "node", + "args": ["/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "", "MCP_LOGGING_DISABLE": "true" @@ -113,10 +107,38 @@ Additional environment variables you can set: If the Mapbox DevKit Server doesn't appear in Cursor's MCP tools: 1. Check that your `MAPBOX_ACCESS_TOKEN` is valid -2. Verify the path to `node` or `npx` is correct +2. Verify `node` and `npx` are in your PATH (run `which node` or `which npx`) 3. For Docker: ensure the image is built with `docker images | grep mapbox-mcp-devkit` 4. Check Cursor's logs for any error messages +### Command Not Found + +If you get "command not found" errors for `node` or `npx`: + +1. Find the absolute path: + + ```bash + # Mac/Linux + which node + which npx + + # Windows + where node + where npx + ``` + +2. Use the absolute path in your config: + ```json + { + "mcpServers": { + "MapboxDevKit": { + "command": "/usr/local/bin/npx", // Use your actual path + ... + } + } + } + ``` + ### Connection Errors If you see JSON-RPC or parsing errors: diff --git a/docs/vscode-integration.md b/docs/vscode-integration.md index c72188d..a3b5cc5 100644 --- a/docs/vscode-integration.md +++ b/docs/vscode-integration.md @@ -14,12 +14,6 @@ This guide explains how to configure Visual Studio Code for use with the Mapbox npm install npm run build -# note your absolute path to node, you will need it for MCP config -# For Mac/Linux -which node -# For Windows -where node - # or alternatively, using docker docker build -t mapbox-mcp-devkit . ``` @@ -40,7 +34,7 @@ docker build -t mapbox-mcp-devkit . "servers": { "MapboxDevKit": { "type": "stdio", - "command": "", + "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "", @@ -80,9 +74,9 @@ docker build -t mapbox-mcp-devkit . "servers": { "MapboxDevKit": { "type": "stdio", - "command": "", + "command": "node", "args": [ - "/YOUR_PATH_TO_GIT_REPOSITORY/dist/esm/index.js" + "/dist/esm/index.js" ], "env": { "MAPBOX_ACCESS_TOKEN": "", @@ -131,7 +125,7 @@ Here's a complete `settings.json` example with the NPM version: "servers": { "MapboxDevKit": { "type": "stdio", - "command": "/usr/local/bin/npx", + "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbGV4YW1wbGUifQ.example", @@ -151,7 +145,7 @@ If the Mapbox DevKit Server doesn't appear in VS Code's MCP servers: 1. **Check GitHub Copilot**: Ensure GitHub Copilot is installed and active 2. **Verify token**: Check that your `MAPBOX_ACCESS_TOKEN` is valid -3. **Verify paths**: Ensure the path to `node` or `npx` is correct (use absolute paths) +3. **Verify PATH**: Ensure `node` and `npx` are in your PATH (run `which node` or `which npx`) 4. **Docker image**: If using Docker, verify the image exists: `docker images | grep mapbox-mcp-devkit` 5. **Check Output**: Open "Output" panel → Select "MCP" from dropdown to see logs @@ -172,37 +166,33 @@ If tools fail to execute: 3. **Verbose errors**: Add `"VERBOSE_ERRORS": "true"` to the env config for detailed error messages 4. **Network**: Ensure you can reach `api.mapbox.com` from your network -### Finding Your NPX Path +### Command Not Found -```sh -# Mac/Linux -which npx -# Output example: /usr/local/bin/npx +If you get "command not found" errors for `node` or `npx`: -# Windows (Command Prompt) -where npx -# Output example: C:\Program Files\nodejs\npx.cmd +1. Find the absolute path: -# Windows (PowerShell) -Get-Command npx -# Look for "Source" field in output -``` + ```bash + # Mac/Linux + which node + which npx -### Finding Your Node Path - -```sh -# Mac/Linux -which node -# Output example: /usr/local/bin/node + # Windows + where node + where npx + ``` -# Windows (Command Prompt) -where node -# Output example: C:\Program Files\nodejs\node.exe - -# Windows (PowerShell) -Get-Command node -# Look for "Source" field in output -``` +2. Use the absolute path in your config: + ```json + "mcp": { + "servers": { + "MapboxDevKit": { + "command": "/usr/local/bin/npx", // Use your actual path + ... + } + } + } + ``` ## Example Usage From 2c0a76304b4101a5fbe8e9ac36eecfa816821bdf Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 5 Nov 2025 11:12:41 -0500 Subject: [PATCH 4/5] [otel] Update Server docs with OTEL information --- .env.example | 20 ++---- CLAUDE.md | 3 +- README.md | 2 +- docs/claude-code-integration.md | 9 +-- docs/claude-desktop-integration.md | 9 +-- docs/cursor-integration.md | 17 ++--- docs/tracing-verification.md | 32 ++------- docs/tracing.md | 44 +++++------- docs/vscode-integration.md | 21 ++---- package.json | 4 +- src/index.ts | 103 +++++++++++++++++------------ src/utils/tracing.ts | 41 ++++-------- 12 files changed, 119 insertions(+), 186 deletions(-) diff --git a/.env.example b/.env.example index 130b40b..4828950 100644 --- a/.env.example +++ b/.env.example @@ -9,14 +9,6 @@ # Get your token at: https://account.mapbox.com/access-tokens MAPBOX_ACCESS_TOKEN=your-mapbox-token-here -# ============================================================================= -# Optional MCP Configuration -# ============================================================================= - -# Disable console logging (recommended when using stdio transport) -# Uncomment to enable: -# MCP_LOGGING_DISABLE=true - # ============================================================================= # OpenTelemetry Tracing (Optional) # ============================================================================= @@ -35,13 +27,11 @@ OTEL_SERVICE_NAME=mapbox-mcp-devkit-server # Resource attributes (customize as needed) OTEL_RESOURCE_ATTRIBUTES=service.name=mapbox-mcp-devkit-server,service.version=0.4.5 -# Optional: Console tracing for development (SSE transport only) -# ⚠️ Do NOT enable with stdio transport - it breaks JSON-RPC communication -# OTEL_EXPORTER_CONSOLE_ENABLED=true - -# Optional: OTEL diagnostic log level (default: NONE to avoid stdio pollution) -# Set to DEBUG, INFO, WARN, or ERROR for troubleshooting OTEL issues -# ⚠️ Only use for debugging - logs will corrupt stdio transport +# Optional: OTEL diagnostic log level (default: NONE) +# This server uses stdio transport exclusively. OTEL diagnostic logs are disabled +# by default to prevent corrupting JSON-RPC communication. +# Set to DEBUG, INFO, WARN, or ERROR only for troubleshooting OTEL configuration issues. +# Valid values: NONE (default), ERROR, WARN, INFO, DEBUG, VERBOSE # OTEL_LOG_LEVEL=ERROR # Optional: OTLP authentication headers (for production backends) diff --git a/CLAUDE.md b/CLAUDE.md index b44d8fc..ec691ae 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,11 +56,10 @@ This server includes OpenTelemetry (OTEL) instrumentation for distributed tracin ### Environment Variables - `OTEL_EXPORTER_OTLP_ENDPOINT` — OTLP endpoint URL (e.g., `http://localhost:4318`). If not set, tracing is disabled. -- `OTEL_EXPORTER_CONSOLE_ENABLED` — Set to `true` to log traces to console (avoid with stdio transport) - `OTEL_TRACING_ENABLED` — Set to `false` to explicitly disable tracing even if endpoint is configured - `OTEL_SERVICE_NAME` — Override service name (default: `mapbox-mcp-devkit-server`) - `OTEL_EXPORTER_OTLP_HEADERS` — JSON string of additional headers for OTLP exporter -- `OTEL_LOG_LEVEL` — OTEL diagnostic log level: `NONE` (default), `ERROR`, `WARN`, `INFO`, `DEBUG`, `VERBOSE`. Set to `NONE` to prevent OTEL logs from polluting stdio transport. +- `OTEL_LOG_LEVEL` — OTEL diagnostic log level: `NONE` (default), `ERROR`, `WARN`, `INFO`, `DEBUG`, `VERBOSE`. Defaults to `NONE` to prevent diagnostic logs from corrupting stdio transport. ### What Gets Traced diff --git a/README.md b/README.md index eff34d2..4db8fd3 100644 --- a/README.md +++ b/README.md @@ -610,7 +610,7 @@ npm run inspect:build docker build -t mapbox-mcp-devkit . # Run and inspect the server -npx @modelcontextprotocol/inspector docker run -i --rm --env MAPBOX_ACCESS_TOKEN="YOUR_TOKEN" --env MCP_LOGGING_DISABLE="true" mapbox-mcp-devkit +npx @modelcontextprotocol/inspector docker run -i --rm --env MAPBOX_ACCESS_TOKEN="YOUR_TOKEN" mapbox-mcp-devkit ``` ### Creating New Tools diff --git a/docs/claude-code-integration.md b/docs/claude-code-integration.md index c12d5da..a3d48fb 100644 --- a/docs/claude-code-integration.md +++ b/docs/claude-code-integration.md @@ -60,8 +60,7 @@ Add to your Claude Code MCP configuration: "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "your_token_here" } } } @@ -81,8 +80,6 @@ Add to your Claude Code MCP configuration: "--rm", "-e", "MAPBOX_ACCESS_TOKEN=your_token_here", - "-e", - "MCP_LOGGING_DISABLE": "true", "mapbox-mcp-devkit" ] } @@ -101,8 +98,7 @@ If you want to use a local version (need to clone and build from this repo): "command": "/path/to/your/node", "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "your_token_here" } } } @@ -200,7 +196,6 @@ Enable verbose error reporting by adding the environment variable: "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true", "VERBOSE_ERRORS": "true" } } diff --git a/docs/claude-desktop-integration.md b/docs/claude-desktop-integration.md index 905cfe8..7987263 100644 --- a/docs/claude-desktop-integration.md +++ b/docs/claude-desktop-integration.md @@ -71,8 +71,7 @@ For users who prefer manual configuration or need custom setups, you can configu "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "your_token_here" } } } @@ -92,8 +91,6 @@ For users who prefer manual configuration or need custom setups, you can configu "--rm", "-e", "MAPBOX_ACCESS_TOKEN=your_token_here", - "-e", - "MCP_LOGGING_DISABLE": "true", "mapbox-mcp-devkit" ] } @@ -112,8 +109,7 @@ If you want to use a local version (need to clone and build from this repo): "command": "/path/to/your/node", "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { - "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "your_token_here" } } } @@ -184,7 +180,6 @@ Enable verbose error reporting by adding the environment variable: "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here", - "MCP_LOGGING_DISABLE": "true" "VERBOSE_ERRORS": "true" } } diff --git a/docs/cursor-integration.md b/docs/cursor-integration.md index be28d1e..b9e23bc 100644 --- a/docs/cursor-integration.md +++ b/docs/cursor-integration.md @@ -32,8 +32,7 @@ docker build -t mapbox-mcp-devkit . "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "" } } } @@ -54,8 +53,6 @@ docker build -t mapbox-mcp-devkit . "--rm", "--env", "MAPBOX_ACCESS_TOKEN=", - "--env", - "MCP_LOGGING_DISABLE=true", "mapbox-mcp-devkit" ] } @@ -72,8 +69,7 @@ docker build -t mapbox-mcp-devkit . "command": "node", "args": ["/dist/esm/index.js"], "env": { - "MAPBOX_ACCESS_TOKEN": "", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "" } } } @@ -84,10 +80,6 @@ docker build -t mapbox-mcp-devkit . ## Important Notes -### Stdio Transport Logging - -The MCP DevKit Server uses stdio (standard input/output) for communication with Cursor. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. - ### Token Scopes Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. @@ -143,9 +135,8 @@ If you get "command not found" errors for `node` or `npx`: If you see JSON-RPC or parsing errors: -1. Ensure `MCP_LOGGING_DISABLE` is set to `"true"` in your configuration -2. If using Node version, verify the path to `dist/esm/index.js` is correct -3. Run `npm run build` to ensure the latest build is available +1. If using Node version, verify the path to `dist/esm/index.js` is correct +2. Run `npm run build` to ensure the latest build is available ### Tool Execution Failures diff --git a/docs/tracing-verification.md b/docs/tracing-verification.md index 8a81c90..f8ce56b 100644 --- a/docs/tracing-verification.md +++ b/docs/tracing-verification.md @@ -73,9 +73,7 @@ npm run tracing:jaeger:stop ### Successful Tracing Setup -✅ **Console output shows**: `OpenTelemetry tracing: enabled` - -✅ **Jaeger UI shows traces** for your service +✅ **Jaeger UI shows traces** for your service after tool execution ✅ **Trace details include**: @@ -193,34 +191,16 @@ OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io/v1/traces OTEL_EXPORTER_OTLP_HEADERS='{"x-honeycomb-team":"YOUR_API_KEY"}' ``` -## Alternative Methods - -### Console Tracing (Development Only) - -**⚠️ Not recommended for stdio transport** - -```bash -# Add to .env (only works well with SSE transport) -OTEL_EXPORTER_CONSOLE_ENABLED=true -``` - -This prints traces to stderr. Only use this for debugging, as it can interfere with MCP's stdio communication. - -### Verifying Different Transports +## Diagnostic Logging -#### stdio Transport (Default) - Silent Operation +By default, OpenTelemetry diagnostic logs are disabled to prevent interference with stdio transport. If you need to troubleshoot OTEL configuration issues, you can enable diagnostic logging: ```bash -# Normal operation -npm run inspect:build +# Add to .env - only for debugging OTEL issues +OTEL_LOG_LEVEL=ERROR ``` -#### SSE Transport - Full Logging - -```bash -# If your inspector supports SSE transport -SERVER_TRANSPORT=sse npm run inspect:build -``` +**⚠️ Warning:** Any console output (including OTEL diagnostic logs) can corrupt stdio communication. Only enable diagnostic logging when actively troubleshooting, and disable it once resolved. ## Production Considerations diff --git a/docs/tracing.md b/docs/tracing.md index e8a70e6..a5d292e 100644 --- a/docs/tracing.md +++ b/docs/tracing.md @@ -2,16 +2,11 @@ This MCP server includes comprehensive distributed tracing using OpenTelemetry (OTEL), providing production-ready observability for tool executions and HTTP requests. -## ⚠️ Important MCP Transport Compatibility +## ⚠️ Important: Stdio Transport Only -**Console tracing should be avoided with stdio transport** as console output interferes with MCP's stdio JSON-RPC communication. +**This server uses stdio transport exclusively.** Only OTLP exporters are supported for tracing. -**Transport-specific recommendations:** - -- **stdio transport (default):** Use OTLP exporters only, avoid console tracing -- **SSE transport:** Console tracing is safe to use for development - -The server automatically detects the transport type and adjusts logging behavior accordingly. +Console output is incompatible with stdio and will corrupt JSON-RPC communication. All diagnostic logging is disabled by default to ensure reliable operation. ## Features @@ -56,14 +51,15 @@ The tracing system supports several configuration options through environment va #### Basic Configuration ```bash -# Enable console tracing (development) -OTEL_EXPORTER_CONSOLE_ENABLED=true - -# OTLP HTTP endpoint (production) +# OTLP HTTP endpoint (required to enable tracing) OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 # Optional OTLP headers for authentication OTEL_EXPORTER_OTLP_HEADERS='{"Authorization": "Bearer your-token"}' + +# Optional: OTEL diagnostic log level (default: NONE) +# Only use for troubleshooting OTEL configuration issues +OTEL_LOG_LEVEL=ERROR ``` #### Service Configuration @@ -82,29 +78,23 @@ OTEL_TRACES_SAMPLER=traceidratio OTEL_TRACES_SAMPLER_ARG=0.1 # Sample 10% of traces ``` -### Transport-Specific Configuration +### Enabling Tracing -**For stdio transport (default):** +Tracing is opt-in and disabled by default. To enable tracing, you must configure an OTLP endpoint: ```bash -# ✅ RECOMMENDED: Use OTLP exporter for stdio transport +# Enable tracing by setting the OTLP endpoint OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 -# ❌ AVOID: Console output interferes with stdio JSON-RPC -# OTEL_EXPORTER_CONSOLE_ENABLED=true -``` - -**For SSE transport:** - -```bash -# ✅ SAFE: Console tracing works with SSE transport -SERVER_TRANSPORT=sse -OTEL_EXPORTER_CONSOLE_ENABLED=true +# Optionally customize the service name +OTEL_SERVICE_NAME=mapbox-mcp-devkit-server -# ✅ ALSO GOOD: OTLP exporter works with any transport -OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318 +# For debugging OTEL configuration issues only +# OTEL_LOG_LEVEL=ERROR ``` +**Note:** Console exporters are not supported due to stdio transport limitations. + ### Verification To verify tracing is working correctly, see the [Tracing Verification Guide](./tracing-verification.md) which shows how to: diff --git a/docs/vscode-integration.md b/docs/vscode-integration.md index a3b5cc5..44541ce 100644 --- a/docs/vscode-integration.md +++ b/docs/vscode-integration.md @@ -37,8 +37,7 @@ docker build -t mapbox-mcp-devkit . "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "" } } } @@ -59,8 +58,6 @@ docker build -t mapbox-mcp-devkit . "--rm", "--env", "MAPBOX_ACCESS_TOKEN=", - "--env", - "MCP_LOGGING_DISABLE=true", "mapbox-mcp-devkit" ] } @@ -79,8 +76,7 @@ docker build -t mapbox-mcp-devkit . "/dist/esm/index.js" ], "env": { - "MAPBOX_ACCESS_TOKEN": "", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "" } } } @@ -97,10 +93,6 @@ After restarting VS Code, you should see "Mapbox DevKit" appear in the GitHub Co ## Important Notes -### Stdio Transport Logging - -The MCP DevKit Server uses stdio (standard input/output) for communication with VS Code. To prevent console logs from corrupting the JSON-RPC protocol, **you must set `MCP_LOGGING_DISABLE=true`** in the environment variables. - ### Token Scopes Your Mapbox access token must have the appropriate scopes for the tools you want to use. See the [main README](../README.md#tools) for required token scopes per tool. @@ -128,8 +120,7 @@ Here's a complete `settings.json` example with the NPM version: "command": "npx", "args": ["-y", "@mapbox/mcp-devkit-server"], "env": { - "MAPBOX_ACCESS_TOKEN": "pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbGV4YW1wbGUifQ.example", - "MCP_LOGGING_DISABLE": "true" + "MAPBOX_ACCESS_TOKEN": "pk.eyJ1IjoiZXhhbXBsZSIsImEiOiJjbGV4YW1wbGUifQ.example" } } } @@ -153,9 +144,9 @@ If the Mapbox DevKit Server doesn't appear in VS Code's MCP servers: If you see JSON-RPC or parsing errors in the Output panel: -1. **Logging disabled**: Ensure `MCP_LOGGING_DISABLE` is set to `"true"` in your configuration -2. **Build fresh**: Run `npm run build` to ensure you have the latest build -3. **Path verification**: For Node version, verify the path to `dist/esm/index.js` is correct and absolute +1. **Build fresh**: Run `npm run build` to ensure you have the latest build +2. **Path verification**: For Node version, verify the path to `dist/esm/index.js` is correct and absolute +3. **Check logs**: Open "Output" panel → Select "MCP" from dropdown to see detailed logs ### Tool Execution Failures diff --git a/package.json b/package.json index ba31119..e2bc20d 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ "format": "prettier --check \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", "format:fix": "prettier --write \"./src/**/*.{ts,tsx,js,json,md}\" \"./test/**/*.{ts,tsx,js,json,md}\"", "generate-version": "node scripts/build-helpers.cjs generate-version", - "inspect:build": "npm run build && npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" -e MCP_LOGGING_DISABLE=true node dist/esm/index.js", - "inspect:dev": "npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" -e MCP_LOGGING_DISABLE=true npx -y tsx src/index.ts", + "inspect:build": "npm run build && npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" node dist/esm/index.js", + "inspect:dev": "npx @modelcontextprotocol/inspector -e MAPBOX_ACCESS_TOKEN=\"$MAPBOX_ACCESS_TOKEN\" npx -y tsx src/index.ts", "lint": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\"", "lint:fix": "eslint \"./src/**/*.{ts,tsx}\" \"./test/**/*.{ts,tsx}\" --fix", "prepare": "husky && node .husky/setup-hooks.js", diff --git a/src/index.ts b/src/index.ts index 46e52b7..8bebca0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -40,20 +40,9 @@ if (existsSync(envPath)) { process.env[key] = value; envLoadedCount++; } - - // Log success if logging is enabled - if (!process.env.MCP_LOGGING_DISABLE) { - console.error( - `✓ Loaded ${envLoadedCount} environment variables from ${envPath}` - ); - } } catch (error) { envLoadError = error instanceof Error ? error : new Error(String(error)); - if (!process.env.MCP_LOGGING_DISABLE) { - console.error( - `⚠️ Warning loading .env: ${error instanceof Error ? error.message : String(error)}` - ); - } + // Error will be logged via MCP logging messages and traced if tracing is enabled } } @@ -91,23 +80,42 @@ resources.forEach((resource) => { resource.installTo(server); }); -// MCP-compatible logging functions -// Completely suppress logging when MCP_LOGGING_DISABLE is set (for MCP inspector compatibility) -function logIfEnabled(level: 'log' | 'warn' | 'error', ...args: unknown[]) { - if (!process.env.MCP_LOGGING_DISABLE) { - console[level](...args); +async function main() { + // Send MCP logging messages about .env loading + if (envLoadError) { + server.server.sendLoggingMessage({ + level: 'warning', + data: `Failed to load .env file: ${envLoadError.message}` + }); + } else if (envLoadedCount > 0) { + server.server.sendLoggingMessage({ + level: 'info', + data: `Loaded ${envLoadedCount} environment variables from ${envPath}` + }); + } else { + server.server.sendLoggingMessage({ + level: 'debug', + data: 'No .env file found or file was empty' + }); } -} -async function main() { // Initialize OpenTelemetry tracing if not in test mode if (process.env.NODE_ENV !== 'test' && !process.env.VITEST) { try { await initializeTracing(); - logIfEnabled( - 'log', - `OpenTelemetry tracing: ${isTracingInitialized() ? 'enabled' : 'disabled'}` - ); + + // Send MCP logging message about tracing status + if (isTracingInitialized()) { + server.server.sendLoggingMessage({ + level: 'info', + data: 'OpenTelemetry tracing enabled' + }); + } else { + server.server.sendLoggingMessage({ + level: 'debug', + data: 'OpenTelemetry tracing disabled (no OTLP endpoint configured)' + }); + } // Record .env loading as a span (retrospectively since it happened before tracing init) if (isTracingInitialized()) { @@ -142,24 +150,21 @@ async function main() { span.end(); } } catch (error) { - logIfEnabled('warn', 'Failed to initialize tracing:', error); + // Log tracing initialization failure + server.server.sendLoggingMessage({ + level: 'warning', + data: `Failed to initialize tracing: ${error instanceof Error ? error.message : String(error)}` + }); } } - // Send MCP logging message about environment variables - server.server.sendLoggingMessage({ - level: 'info', - data: 'Environment variables loaded from .env file' - }); - const relevantEnvVars = Object.freeze({ MAPBOX_ACCESS_TOKEN: process.env.MAPBOX_ACCESS_TOKEN ? '***' : undefined, MAPBOX_API_ENDPOINT: process.env.MAPBOX_API_ENDPOINT, OTEL_SERVICE_NAME: process.env.OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_ENDPOINT: process.env.OTEL_EXPORTER_OTLP_ENDPOINT, - OTEL_EXPORTER_CONSOLE_ENABLED: process.env.OTEL_EXPORTER_CONSOLE_ENABLED, OTEL_TRACING_ENABLED: process.env.OTEL_TRACING_ENABLED, - MCP_LOGGING_DISABLE: process.env.MCP_LOGGING_DISABLE, + OTEL_LOG_LEVEL: process.env.OTEL_LOG_LEVEL, NODE_ENV: process.env.NODE_ENV }); @@ -178,15 +183,31 @@ async function shutdown() { // Shutdown tracing try { await shutdownTracing(); - } catch (e) { - logIfEnabled('error', 'Error shutting down tracing:', e); + server.server.sendLoggingMessage({ + level: 'info', + data: 'Server shutting down gracefully' + }); + } catch (error) { + server.server.sendLoggingMessage({ + level: 'warning', + data: `Error during shutdown: ${error instanceof Error ? error.message : String(error)}` + }); } process.exit(0); } -function exitWithLog(message: string, error: unknown, code = 1) { - logIfEnabled('error', message, error); +function exitWithError(error: unknown, code = 1) { + // Use MCP logging for fatal errors + try { + server.server.sendLoggingMessage({ + level: 'error', + data: `Fatal error: ${error instanceof Error ? error.message : String(error)}` + }); + } catch { + // If MCP logging fails, we have no choice but to use console + console.error('Fatal error:', error); + } process.exit(code); } @@ -200,11 +221,7 @@ function exitWithLog(message: string, error: unknown, code = 1) { }); }); -process.on('uncaughtException', (err) => - exitWithLog('Uncaught exception:', err) -); -process.on('unhandledRejection', (reason) => - exitWithLog('Unhandled rejection:', reason) -); +process.on('uncaughtException', (err) => exitWithError(err)); +process.on('unhandledRejection', (reason) => exitWithError(reason)); -main().catch((error) => exitWithLog('Fatal error starting MCP server:', error)); +main().catch((error) => exitWithError(error)); diff --git a/src/utils/tracing.ts b/src/utils/tracing.ts index 38a491b..eeb7124 100644 --- a/src/utils/tracing.ts +++ b/src/utils/tracing.ts @@ -149,8 +149,8 @@ export function createToolExecutionContext( * Initialize OpenTelemetry tracing * Should be called once at application startup * - * For MCP servers using stdio transport, console output should be avoided. - * This implementation automatically detects and handles MCP compatibility. + * This server uses stdio transport exclusively. Only OTLP exporters are supported. + * Console output is incompatible with stdio and will corrupt JSON-RPC communication. */ export async function initializeTracing(): Promise { // Skip initialization if already initialized or if running in test environment @@ -177,39 +177,24 @@ export async function initializeTracing(): Promise { 'service.git.tag': versionInfo.tag }); - // Configure exporters - const exporters = []; - - // Console exporter for development (avoid in stdio transport) - if (process.env.OTEL_EXPORTER_CONSOLE_ENABLED === 'true') { - const { ConsoleSpanExporter } = await import( - '@opentelemetry/sdk-trace-base' - ); - exporters.push(new ConsoleSpanExporter()); - } - - // OTLP HTTP exporter for production + // OTLP HTTP exporter - only supported exporter for stdio transport const otlpEndpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT; - if (otlpEndpoint) { - exporters.push( - new OTLPTraceExporter({ - url: `${otlpEndpoint}/v1/traces`, - headers: process.env.OTEL_EXPORTER_OTLP_HEADERS - ? JSON.parse(process.env.OTEL_EXPORTER_OTLP_HEADERS) - : {} - }) - ); - } - - // Skip tracing if no exporters configured - if (exporters.length === 0) { + if (!otlpEndpoint) { + // Skip tracing if no OTLP endpoint configured return; } + const exporter = new OTLPTraceExporter({ + url: `${otlpEndpoint}/v1/traces`, + headers: process.env.OTEL_EXPORTER_OTLP_HEADERS + ? JSON.parse(process.env.OTEL_EXPORTER_OTLP_HEADERS) + : {} + }); + // Create SDK instance sdk = new NodeSDK({ resource, - traceExporter: exporters[0], + traceExporter: exporter, instrumentations: [ getNodeAutoInstrumentations({ // Disable instrumentations that might be too noisy From e62d286b0983b2f9516cb6506a2a53a0fc17b9d7 Mon Sep 17 00:00:00 2001 From: Matthew Podwysocki Date: Wed, 5 Nov 2025 11:29:32 -0500 Subject: [PATCH 5/5] [otel] Update Server docs with OTEL information --- docs/claude-code-integration.md | 4 ++-- docs/claude-desktop-integration.md | 4 ++-- docs/cursor-integration.md | 35 +++--------------------------- docs/vscode-integration.md | 35 +++--------------------------- 4 files changed, 10 insertions(+), 68 deletions(-) diff --git a/docs/claude-code-integration.md b/docs/claude-code-integration.md index a3d48fb..c77114e 100644 --- a/docs/claude-code-integration.md +++ b/docs/claude-code-integration.md @@ -95,8 +95,8 @@ If you want to use a local version (need to clone and build from this repo): { "mcpServers": { "mapbox-devkit": { - "command": "/path/to/your/node", - "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], + "command": "node", + "args": ["/absolute/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here" } diff --git a/docs/claude-desktop-integration.md b/docs/claude-desktop-integration.md index 7987263..41381ba 100644 --- a/docs/claude-desktop-integration.md +++ b/docs/claude-desktop-integration.md @@ -106,8 +106,8 @@ If you want to use a local version (need to clone and build from this repo): { "mcpServers": { "mapbox-devkit": { - "command": "/path/to/your/node", - "args": ["/path/to/mapbox-mcp-devkit/dist/esm/index.js"], + "command": "node", + "args": ["/absolute/path/to/mapbox-mcp-devkit/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "your_token_here" } diff --git a/docs/cursor-integration.md b/docs/cursor-integration.md index b9e23bc..fb07a17 100644 --- a/docs/cursor-integration.md +++ b/docs/cursor-integration.md @@ -67,7 +67,7 @@ docker build -t mapbox-mcp-devkit . "MapboxDevKit": { "type": "stdio", "command": "node", - "args": ["/dist/esm/index.js"], + "args": ["/absolute/path/to/repo/dist/esm/index.js"], "env": { "MAPBOX_ACCESS_TOKEN": "" } @@ -99,37 +99,8 @@ Additional environment variables you can set: If the Mapbox DevKit Server doesn't appear in Cursor's MCP tools: 1. Check that your `MAPBOX_ACCESS_TOKEN` is valid -2. Verify `node` and `npx` are in your PATH (run `which node` or `which npx`) -3. For Docker: ensure the image is built with `docker images | grep mapbox-mcp-devkit` -4. Check Cursor's logs for any error messages - -### Command Not Found - -If you get "command not found" errors for `node` or `npx`: - -1. Find the absolute path: - - ```bash - # Mac/Linux - which node - which npx - - # Windows - where node - where npx - ``` - -2. Use the absolute path in your config: - ```json - { - "mcpServers": { - "MapboxDevKit": { - "command": "/usr/local/bin/npx", // Use your actual path - ... - } - } - } - ``` +2. For Docker: ensure the image is built with `docker images | grep mapbox-mcp-devkit` +3. Check Cursor's logs for any error messages ### Connection Errors diff --git a/docs/vscode-integration.md b/docs/vscode-integration.md index 44541ce..27e2914 100644 --- a/docs/vscode-integration.md +++ b/docs/vscode-integration.md @@ -73,7 +73,7 @@ docker build -t mapbox-mcp-devkit . "type": "stdio", "command": "node", "args": [ - "/dist/esm/index.js" + "/absolute/path/to/repo/dist/esm/index.js" ], "env": { "MAPBOX_ACCESS_TOKEN": "" @@ -136,9 +136,8 @@ If the Mapbox DevKit Server doesn't appear in VS Code's MCP servers: 1. **Check GitHub Copilot**: Ensure GitHub Copilot is installed and active 2. **Verify token**: Check that your `MAPBOX_ACCESS_TOKEN` is valid -3. **Verify PATH**: Ensure `node` and `npx` are in your PATH (run `which node` or `which npx`) -4. **Docker image**: If using Docker, verify the image exists: `docker images | grep mapbox-mcp-devkit` -5. **Check Output**: Open "Output" panel → Select "MCP" from dropdown to see logs +3. **Docker image**: If using Docker, verify the image exists: `docker images | grep mapbox-mcp-devkit` +4. **Check Output**: Open "Output" panel → Select "MCP" from dropdown to see logs ### Connection Errors / JSON-RPC Parsing Errors @@ -157,34 +156,6 @@ If tools fail to execute: 3. **Verbose errors**: Add `"VERBOSE_ERRORS": "true"` to the env config for detailed error messages 4. **Network**: Ensure you can reach `api.mapbox.com` from your network -### Command Not Found - -If you get "command not found" errors for `node` or `npx`: - -1. Find the absolute path: - - ```bash - # Mac/Linux - which node - which npx - - # Windows - where node - where npx - ``` - -2. Use the absolute path in your config: - ```json - "mcp": { - "servers": { - "MapboxDevKit": { - "command": "/usr/local/bin/npx", // Use your actual path - ... - } - } - } - ``` - ## Example Usage Once configured, you can use natural language in GitHub Copilot Chat to interact with Mapbox tools: