Skip to content

Conversation

@ngoiyaeric
Copy link
Collaborator

@ngoiyaeric ngoiyaeric commented Jan 4, 2026

User description

Overview

This PR migrates the Mapbox integration from Smithery to Composio, providing better authentication management, improved security, and more robust tool execution.

Changes

Dependencies

  • ❌ Removed: @smithery/cli, @smithery/sdk, smithery
  • ✅ Added: @composio/core (v0.5.0)

Modified Files (5)

  1. package.json - Updated dependencies
  2. mapbox_mcp/hooks.ts - Replaced Smithery with Composio authentication
  3. mapbox_mcp/index.ts - Updated test script for Composio
  4. mapbox_mcp_config.json - New Composio configuration structure
  5. .env.local.example - Updated environment variables

New Files (3)

  1. mapbox_mcp/composio-mapbox.ts - Core Composio client setup
  2. mapbox_mcp/README.md - Complete integration documentation
  3. COMPOSIO_MIGRATION.md - Detailed migration guide

Key Improvements

Better Authentication - Centralized auth config management
Enhanced Security - API keys stored securely in Composio
Improved Scalability - Better handling of integrations
Built-in Monitoring - Dashboard for logs and status
Backward Compatible - Same API interface maintained

Environment Variables

New environment variables required:

COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_MAPBOX_CONFIG_ID"
COMPOSIO_USER_ID="user@example.com"
MAPBOX_ACCESS_TOKEN="your_mapbox_api_key"

Setup Instructions

  1. Install dependencies: bun install
  2. Sign up at https://composio.dev
  3. Create auth config for Mapbox
  4. Update environment variables in .env.local
  5. Test: bun run mapbox_mcp/index.ts

Documentation

  • Integration guide: mapbox_mcp/README.md
  • Migration guide: COMPOSIO_MIGRATION.md

Testing

  • Environment variables configured
  • Connection test passes
  • Geocoding works
  • Distance calculation works
  • Nearby places search works

Breaking Changes

⚠️ Requires new environment variables and Composio account setup.

Related Issues

Closes #[issue_number] (if applicable)


For detailed migration instructions, see COMPOSIO_MIGRATION.md.


PR Type

Enhancement


Description

  • Migrate Mapbox integration from Smithery to Composio platform

  • Replace Smithery SDK with @composio/core dependency

  • Implement Composio authentication and tool execution

  • Update environment variables and configuration structure

  • Add comprehensive migration guide and documentation


Diagram Walkthrough

flowchart LR
  Smithery["Smithery MCP Server<br/>@smithery/cli, @smithery/sdk"]
  Composio["Composio Platform<br/>@composio/core"]
  Auth["API Key Authentication<br/>via Composio"]
  Tools["Mapbox Tools<br/>geocode, distance, places"]
  
  Smithery -->|"Remove dependencies"| Composio
  Composio -->|"Initialize connection"| Auth
  Auth -->|"Execute actions"| Tools
Loading

File Walkthrough

Relevant files
Enhancement
composio-mapbox.ts
Core Composio client setup and authentication                       

mapbox_mcp/composio-mapbox.ts

  • New file implementing Composio client initialization and
    authentication
  • Provides authenticateToolkit() function for API Key authentication
  • Exports initializeComposioMapbox() for connection setup
  • Exports getComposioClient() to retrieve Composio instance
+63/-0   
hooks.ts
Replace Smithery with Composio in React hooks                       

mapbox_mcp/hooks.ts

  • Replace useMcp hook from 'use-mcp/react' with Composio SDK
  • Update connection logic to use initializeComposioMapbox()
  • Change tool execution from mcp.callTool() to
    composioClient.executeAction()
  • Add connectionId state and composioClientRef for Composio client
    management
  • Update all tool methods (geocode, distance, places) to use Composio
    API
  • Simplify connection state management with direct Composio checks
+79/-64 
index.ts
Update test script for Composio integration                           

mapbox_mcp/index.ts

  • Replace Smithery connection logic with Composio initialization
  • Update environment variable checks from Smithery to Composio variables
  • Change tool invocation from client.callTool() to
    composioClient.executeAction()
  • Simplify result parsing to use direct result.data instead of JSON
    extraction
  • Update logging and error messages to reference Composio
+41/-69 
Configuration changes
.env.local.example
Update environment variables for Composio                               

.env.local.example

  • Remove Smithery environment variables (SMITHERY_PROFILE_ID,
    SMITHERY_API_KEY)
  • Add Composio variables (COMPOSIO_MAPBOX_AUTH_CONFIG_ID,
    COMPOSIO_USER_ID)
  • Add MAPBOX_ACCESS_TOKEN variable
  • Add public-facing Composio environment variables for client-side usage
+11/-4   
mapbox_mcp_config.json
Replace MCP config with Composio structure                             

mapbox_mcp_config.json

  • Replace MCP server configuration with Composio configuration structure
  • Remove Smithery CLI command and arguments
  • Add Composio mapbox auth config with authConfigId and userId
  • Include description for configuration reference
+5/-13   
Dependencies
package.json
Update dependencies from Smithery to Composio                       

package.json

  • Remove @smithery/cli (^1.2.5) dependency
  • Remove @smithery/sdk (^1.0.4) dependency
  • Remove smithery (^0.5.2) dependency
  • Add @composio/core (^0.5.0) dependency
+2/-3     
Documentation
COMPOSIO_MIGRATION.md
Add detailed Smithery to Composio migration guide               

COMPOSIO_MIGRATION.md

  • New comprehensive migration guide from Smithery to Composio
  • Document all dependency changes and environment variable mappings
  • Provide before/after code examples for connection and tool execution
  • Include step-by-step migration instructions
  • Add troubleshooting section with common issues and solutions
  • List benefits of Composio and rollback instructions
+253/-0 
README.md
Add Mapbox Composio integration documentation                       

mapbox_mcp/README.md

  • New documentation for Composio-based Mapbox integration
  • Provide setup instructions and environment variable configuration
  • Document available functions and usage examples in React components
  • Include migration notes from Smithery implementation
  • Add troubleshooting section for common issues
+128/-0 

Summary by CodeRabbit

  • Updates

    • Migrated Mapbox integration to Composio; geocoding, distance, and place-search now use Composio-backed Mapbox actions.
  • Configuration

    • Replaced legacy credentials with Composio and Mapbox variables; several tokens moved to unquoted/public-friendly formats for client/server usage.
  • Documentation

    • Added a Migration Guide and a dedicated integration README with setup, usage, troubleshooting, and rollback instructions.
  • Chores

    • Updated dependencies to add Composio support and removed legacy provider packages.

✏️ Tip: You can customize this high-level summary in your review settings.

- Remove @smithery/cli, @smithery/sdk, and smithery dependencies
- Add @composio/core dependency
- Create new composio-mapbox.ts for Composio client setup
- Update hooks.ts to use Composio authentication and tool execution
- Update index.ts test script for Composio
- Replace mapbox_mcp_config.json with Composio configuration
- Update .env.local.example with Composio environment variables
- Add comprehensive README.md for Mapbox integration
- Add COMPOSIO_MIGRATION.md migration guide

This migration provides better authentication management, improved security,
and more robust tool execution for Mapbox services.
@charliecreates charliecreates bot requested a review from CharlieHelps January 4, 2026 09:52
@vercel
Copy link
Contributor

vercel bot commented Jan 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
qcx Ready Ready Preview, Comment Jan 5, 2026 1:33pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 4, 2026

Walkthrough

Migrates QCX Mapbox integration from Smithery/MCP to Composio: swaps Smithery dependencies and env vars for Composio equivalents, adds a Composio client module, refactors hooks and runtime to call Composio actions for Mapbox tooling, updates config and env examples, and adds migration docs and README.

Changes

Cohort / File(s) Summary
Environment & Example
\.env.local.example``
Replaced SMITHERY_PROFILE_ID / SMITHERY_API_KEY with COMPOSIO_API_KEY, COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID; added MAPBOX_ACCESS_TOKEN and NEXT_PUBLIC_ variants; several env values changed from quoted to unquoted.
Project Manifest
\package.json``
Removed Smithery packages (@smithery/cli, @smithery/sdk, smithery); added @composio/core (^0.3.3).
Composio Integration Module
\mapbox_mcp/composio-mapbox.ts``
New module exposing authenticateToolkit, initializeComposioMapbox, and getComposioClient(); validates env, initiates Composio APIKey auth with Mapbox token, verifies connected account, and returns client/connection details.
Hook & Runtime Logic
\mapbox_mcp/hooks.ts`, `mapbox_mcp/index.ts``
Replaced MCP/useMcp flows with Composio lifecycle: dynamic client init, connectionId state, fetch tools via getTools({ apps: ['mapbox'] }), invoke actions via executeAction (e.g., mapbox_geocode_location), updated error/log messaging and renamed test helper to testComposioConnection. Public hook signature preserved.
Config Schema
\mapbox_mcp_config.json``
Removed mcpServers runner config; added composio.mapbox object with authConfigId, userId, and descriptive placeholders for new env vars.
Docs & Guides
\COMPOSIO_MIGRATION.md`, `mapbox_mcp/README.md``
Added migration guide and README covering installation, env var schema, Composio auth flow, example usage, available Composio Mapbox actions, troubleshooting, and rollback steps.
Agent Geospatial Tooling
\lib/agents/tools/geospatial.tsx``
Replaced Smithery URL/sdk usage with direct Composio URL construction and query params (api_key, user_id), updated env var names/validation/logs, and removed Smithery helper usage.

Sequence Diagram

sequenceDiagram
    participant App as React Component
    participant Hook as useMCPMapClient Hook
    participant Composio as Composio Client
    participant Auth as Composio Auth Service
    participant Mapbox as Mapbox API

    rect rgba(200,230,255,0.25)
    Note over App,Hook: Init & Connect
    App->>Hook: mount / connect()
    Hook->>Composio: getComposioClient()
    Composio-->>Hook: client instance
    Hook->>Composio: authenticateToolkit(userId, authConfigId, mapboxApiKey)
    Composio->>Auth: connectedAccounts.initiate(APIKey)
    Auth-->>Composio: connectionId
    Composio->>Composio: connectedAccounts.get(connectionId)
    Composio-->>Hook: connectionId + connectedAccount
    Hook-->>App: isConnected = true
    end

    rect rgba(230,245,220,0.25)
    Note over App,Mapbox: Tool Execution
    App->>Hook: geocodeLocation(query)
    Hook->>Composio: executeAction("mapbox_geocode_location", {query, connectedAccountId})
    Composio->>Mapbox: proxied Mapbox API call
    Mapbox-->>Composio: geocode result
    Composio-->>Hook: result.data
    Hook-->>App: structured result
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

Possible security concern

Poem

🐇 I swapped some keys and hopped the gate,

Smithery bowed out, Composio joined the crate.
Mapbox maps now bounce through a new stream,
Connections hum and tools dance in a beam,
A tiny migration — nibble, hop, celebrate! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main objective of the changeset: migrating the Mapbox integration from Smithery to Composio.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a460272 and 18a4ac2.

📒 Files selected for processing (1)
  • lib/agents/tools/geospatial.tsx
🔇 Additional comments (2)
lib/agents/tools/geospatial.tsx (2)

37-47: Improved environment variable handling.

Good security improvements here:

  • Removed NEXT_PUBLIC_ prefix from environment variables (compared to earlier versions), preventing client-side exposure
  • Truncating credentials in logs (lines 42-44) is a security best practice
  • Comprehensive validation ensuring all required variables are present and non-empty

252-298: Tool selection and retry logic looks sound.

The tool selection logic (lines 252-265) appropriately uses a prefer() helper to find available tools from the MCP server, with sensible fallbacks for each query type.

The retry logic (lines 285-298) is well-implemented with:

  • 3 retry attempts with 1-second backoff
  • 30-second timeout per attempt
  • Clear error messaging on final failure

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 4, 2026

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Client-side secret exposure

Description: The new Composio authentication flow is implemented in a module that is imported by a
React hook (mapbox_mcp/hooks.ts), meaning API-key based authentication (via
MAPBOX_ACCESS_TOKEN) and sensitive connection details (connectedAccount) may be
executed/logged in a client-side context, risking exposure of secrets or account metadata
in the browser console/bundled code.
composio-mapbox.ts [4-55]

Referred Code
// Replace these with your actual values
const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application

const composio = new Composio();

/**
 * Authenticate Mapbox toolkit using Composio
 * @param userId - User ID from database/application
 * @param authConfigId - Auth config ID for Mapbox
 * @returns Connection ID
 */
export async function authenticateToolkit(userId: string, authConfigId: string) {
  // TODO: Replace this with a method to retrieve the API key from the user.
  // In production, this should be securely retrieved from your database or user input.
  // For example: const userApiKey = await getUserApiKey(userId);
  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key

  const connectionRequest = await composio.connectedAccounts.initiate(
    userId,
    authConfigId,


 ... (clipped 31 lines)
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🔴
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status:
Non-idiomatic naming: New identifiers use inconsistent/non-idiomatic TypeScript naming (e.g., snake_case
mapbox_auth_config_id) which reduces readability and self-documentation.

Referred Code
const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Weak error handling: Errors are converted to strings via template interpolation (e.g., ${err}) and rethrown
without normalization/typed handling, making edge cases and actionable diagnostics
unreliable.

Referred Code
} catch (err) {
  setError(`Failed to connect to Composio Mapbox: ${err}`);
  console.error('❌ Composio connection error:', err);
} finally {
  setIsLoading(false);
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Error details exposed: Potentially sensitive internal error objects are embedded into UI-facing state via
setError(</code>...${err}<code>), which can leak stack traces or internal details to end users.

Referred Code
} catch (err) {
  setError(`Failed to connect to Composio Mapbox: ${err}`);
  console.error('❌ Composio connection error:', err);
} finally {

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
PII/unstructured logging: The new code logs raw userId and full connectedAccount objects via unstructured
console.log, which can expose PII and sensitive metadata in logs.

Referred Code
  console.log(`Successfully connected Mapbox for user ${userId}`);
  console.log(`Connection status: ${connectionRequest.status}`);

  return connectionRequest.id;
}

/**
 * Initialize Composio connection for Mapbox
 */
export async function initializeComposioMapbox() {
  try {
    // Authenticate the toolkit
    const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);

    // Verify the connection
    const connectedAccount = await composio.connectedAccounts.get(connectionId);
    console.log("Connected account:", connectedAccount);

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
Unsafe default secrets: Authentication pulls credentials from environment variables but falls back to hard-coded
placeholder values (including an API key placeholder), risking insecure/invalid
configurations being used without validation.

Referred Code
const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application

const composio = new Composio();

/**
 * Authenticate Mapbox toolkit using Composio
 * @param userId - User ID from database/application
 * @param authConfigId - Auth config ID for Mapbox
 * @returns Connection ID
 */
export async function authenticateToolkit(userId: string, authConfigId: string) {
  // TODO: Replace this with a method to retrieve the API key from the user.
  // In production, this should be securely retrieved from your database or user input.
  // For example: const userApiKey = await getUserApiKey(userId);
  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Incomplete audit context: The new connection/authentication flow logs ad-hoc console messages but does not implement
a consistent audit-trail record (user ID, timestamp, action, outcome) for
authentication/tool execution events.

Referred Code
  // API Key authentication is immediate - no redirect needed
  console.log(`Successfully connected Mapbox for user ${userId}`);
  console.log(`Connection status: ${connectionRequest.status}`);

  return connectionRequest.id;
}

/**
 * Initialize Composio connection for Mapbox
 */
export async function initializeComposioMapbox() {
  try {
    // Authenticate the toolkit
    const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);

    // Verify the connection
    const connectedAccount = await composio.connectedAccounts.get(connectionId);
    console.log("Connected account:", connectedAccount);

    return { connectionId, connectedAccount };
  } catch (error) {


 ... (clipped 3 lines)

Learn more about managing compliance generic rules or creating your own custom rules

  • Update
Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

The initial version ^0.5.0 does not exist. Updated to the latest
available version ^0.3.3 from npm registry.
@qodo-code-review
Copy link
Contributor

qodo-code-review bot commented Jan 4, 2026

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Refactor authentication to prevent executing server-side logic on the client
Suggestion Impact:The commit acknowledges and partially addresses the concern by marking the Composio/Mapbox auth functions as server-side only, adding explicit warnings, validating required env vars, and switching the hook to dynamic imports to reduce bundling of server code into the client. However, it does not implement the core suggested change (a dedicated API route + client fetch); the hook still calls initializeComposioMapbox directly (just via dynamic import).

code diff:

 /**
  * Custom React hook to interact with Mapbox via Composio.
  * Manages client connection, tool invocation, and state (loading, error, connection status).
- * Uses Composio SDK for authentication and tool execution.
+ * 
+ * WARNING: This hook should NOT be used directly in client components as it requires
+ * server-side environment variables (MAPBOX_ACCESS_TOKEN). Instead, create a server-side
+ * API route that handles Composio authentication and tool execution.
  */
 export const useMCPMapClient = () => {
   const [isConnected, setIsConnected] = useState(false);
@@ -56,15 +58,27 @@
 
   // Initialize Composio client on mount
   useEffect(() => {
-    composioClientRef.current = getComposioClient();
+    // Import dynamically to avoid bundling server-side code in client
+    const initClient = async () => {
+      try {
+        const { getComposioClient } = await import('./composio-mapbox');
+        composioClientRef.current = getComposioClient();
+      } catch (err) {
+        console.error('Failed to initialize Composio client:', err);
+        setError('Failed to initialize Composio client. This may be due to missing environment variables.');
+      }
+    };
+    initClient();
   }, []);
 
-  // Connect to Composio Mapbox
+  // Connect to Composio Mapbox - should be called from server-side
   const connect = useCallback(async () => {
     try {
       setIsLoading(true);
       setError(null);
       
+      // Import server-side function
+      const { initializeComposioMapbox } = await import('./composio-mapbox');
       const { connectionId: connId, connectedAccount } = await initializeComposioMapbox();
       setConnectionId(connId);
       
@@ -80,18 +94,31 @@
       console.log('✅ Connected to Composio Mapbox');
       console.log('Connection ID:', connId);
     } catch (err) {
-      setError(`Failed to connect to Composio Mapbox: ${err}`);
+      const errorMessage = `Failed to connect to Composio Mapbox: ${err}`;
+      setError(errorMessage);
       console.error('❌ Composio connection error:', err);
+      throw new Error(errorMessage);
     } finally {
       setIsLoading(false);
     }
-  }, []);
+  }, []); // Empty deps - function doesn't depend on external state
 
   const disconnect = useCallback(async () => {
-    toolsRef.current = null;
-    setIsConnected(false);
-    setConnectionId(null);
-  }, []);
+    try {
+      // Clean up Composio connection if it exists
+      if (composioClientRef.current && connectionId) {
+        // Note: Composio SDK may not have a direct disconnect method for connected accounts
+        // This is a placeholder for proper cleanup if the SDK provides it
+        console.log('Disconnecting from Composio...');
+      }
+      
+      toolsRef.current = null;
+      setIsConnected(false);
+      setConnectionId(null);
+    } catch (err) {
+      console.error('Error during disconnect:', err);
+    }
+  }, [connectionId]); // Depends on connectionId
 
   const processLocationQuery = useCallback(async (query: string) => {
     if (!isConnected || !toolsRef.current) {
@@ -104,11 +131,12 @@
         model: getModel(),
         tools: toolsRef.current,
         system: `You are an expert location data processing engine. Your role is to accurately use the available tools to answer location-based queries and provide structured data.
+
 Available tools and their purpose:
-- geocode_location: Converts addresses or place names to geographic coordinates. Also provides a map preview URL for the location.
-- calculate_distance: Calculates the travel distance and duration between two locations for various profiles (driving, walking, cycling). Also provides a map preview URL for the route.
-- search_nearby_places: Searches for points of interest (e.g., 'restaurants', 'gas stations') near a specified location. Provides details for each place including a map preview URL.
-- generate_map_link: Generates static and interactive map links for a given location.
+- mapbox_geocode_location: Converts addresses or place names to geographic coordinates. Also provides a map preview URL for the location.
+- mapbox_calculate_distance: Calculates the travel distance and duration between two locations for various profiles (driving, walking, cycling). Also provides a map preview URL for the route.
+- mapbox_search_nearby_places: Searches for points of interest (e.g., 'restaurants', 'gas stations') near a specified location. Provides details for each place including a map preview URL.
+- mapbox_generate_map_link: Generates static and interactive map links for a given location.
 
 For any user query, determine the most appropriate tool or sequence of tools to achieve the user's goal.
 Prioritize calling tools to get structured data. The text response you generate should summarize the findings and must include any relevant map URLs or key information provided by the tools.
@@ -153,12 +181,13 @@
         shouldShowMap,
       };
     } catch (err) {
-      setError(`Query processing failed: ${err}`);
-      throw err;
+      const errorMessage = `Query processing failed: ${err}`;
+      setError(errorMessage);
+      throw new Error(errorMessage);
     } finally {
       setIsLoading(false);
     }
-  }, [isConnected]);
+  }, [isConnected]); // Depends on isConnected
 
   const geocodeLocation = useCallback(async (address: string): Promise<LocationResult> => {
     if (!isConnected || !composioClientRef.current || !connectionId) {
@@ -176,12 +205,17 @@
       return result.data;
     } catch (err) {
       console.error('Geocoding error:', err);
-      setError(`Geocoding error: ${err}`);
-      throw err;
-    }
-  }, [isConnected, connectionId]);
-
-  const calculateDistance = useCallback(async (from: string, to: string, profile: 'driving' | 'walking' | 'cycling' = 'driving'): Promise<DistanceResult> => {
+      const errorMessage = `Geocoding error: ${err}`;
+      setError(errorMessage);
+      throw new Error(errorMessage);
+    }
+  }, [isConnected, connectionId]); // Depends on isConnected and connectionId
+
+  const calculateDistance = useCallback(async (
+    from: string,
+    to: string,
+    profile: 'driving' | 'walking' | 'cycling' = 'driving'
+  ): Promise<DistanceResult> => {
     if (!isConnected || !composioClientRef.current || !connectionId) {
       throw new Error('Composio client not connected');
     }
@@ -199,12 +233,18 @@
       return result.data;
     } catch (err) {
       console.error('Distance calculation error:', err);
-      setError(`Distance calculation error: ${err}`);
-      throw err;
-    }
-  }, [isConnected, connectionId]);
-
-  const searchNearbyPlaces = useCallback(async (location: string, query: string, radius: number = 1000, limit: number = 5): Promise<PlaceResult> => {
+      const errorMessage = `Distance calculation error: ${err}`;
+      setError(errorMessage);
+      throw new Error(errorMessage);
+    }
+  }, [isConnected, connectionId]); // Depends on isConnected and connectionId
+
+  const searchNearbyPlaces = useCallback(async (
+    location: string,
+    query: string,
+    radius: number = 1000,
+    limit: number = 5
+  ): Promise<PlaceResult> => {
     if (!isConnected || !composioClientRef.current || !connectionId) {
       throw new Error('Composio client not connected');
     }
@@ -222,10 +262,11 @@
       return result.data;
     } catch (err) {
       console.error('Places search error:', err);
-      setError(`Places search error: ${err}`);
-      throw err;
-    }
-  }, [isConnected, connectionId]);
+      const errorMessage = `Places search error: ${err}`;
+      setError(errorMessage);
+      throw new Error(errorMessage);
+    }
+  }, [isConnected, connectionId]); // Depends on isConnected and connectionId
 
   return {
     isConnected,

# File: mapbox_mcp/composio-mapbox.ts
@@ -1,30 +1,70 @@
 import { Composio } from '@composio/core';
 import { AuthScheme } from '@composio/core';
 
-// Replace these with your actual values
-const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
-const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application
+/**
+ * Validate required environment variables
+ * @throws Error if any required environment variable is missing
+ */
+function validateEnvironmentVariables(): {
+  authConfigId: string;
+  userId: string;
+  mapboxToken: string;
+} {
+  const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
+  const userId = process.env.COMPOSIO_USER_ID;
+  const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN;
+
+  if (!authConfigId) {
+    throw new Error(
+      'COMPOSIO_MAPBOX_AUTH_CONFIG_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!userId) {
+    throw new Error(
+      'COMPOSIO_USER_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!mapboxToken) {
+    throw new Error(
+      'MAPBOX_ACCESS_TOKEN environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  return { authConfigId, userId, mapboxToken };
+}
 
 const composio = new Composio();
 
 /**
  * Authenticate Mapbox toolkit using Composio
+ * This should only be called server-side to avoid exposing API keys
  * @param userId - User ID from database/application
  * @param authConfigId - Auth config ID for Mapbox
+ * @param apiKey - Mapbox API key (should be retrieved securely)
  * @returns Connection ID
  */
-export async function authenticateToolkit(userId: string, authConfigId: string) {
-  // TODO: Replace this with a method to retrieve the API key from the user.
-  // In production, this should be securely retrieved from your database or user input.
-  // For example: const userApiKey = await getUserApiKey(userId);
-  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key
-  
+export async function authenticateToolkit(
+  userId: string,
+  authConfigId: string,
+  apiKey: string
+): Promise<string> {
+  if (!userId || !authConfigId || !apiKey) {
+    throw new Error(
+      'userId, authConfigId, and apiKey are required for authentication'
+    );
+  }
+
   const connectionRequest = await composio.connectedAccounts.initiate(
     userId,
     authConfigId,
     {
       config: AuthScheme.APIKey({
-        api_key: userApiKey
+        api_key: apiKey
       })
     }
   );
@@ -38,11 +78,15 @@
 
 /**
  * Initialize Composio connection for Mapbox
+ * This should only be called server-side to avoid exposing API keys
+ * @throws Error if environment variables are missing or connection fails
  */
 export async function initializeComposioMapbox() {
+  const { authConfigId, userId, mapboxToken } = validateEnvironmentVariables();
+
   try {
     // Authenticate the toolkit
-    const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);
+    const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken);
     
     // Verify the connection
     const connectedAccount = await composio.connectedAccounts.get(connectionId);

The server-side authentication logic, which uses a secret API key, is currently
running in a client-side React hook. This should be moved to a dedicated API
route to ensure secrets remain on the server and the connection can be
established securely.

Examples:

mapbox_mcp/hooks.ts [63-88]
  const connect = useCallback(async () => {
    try {
      setIsLoading(true);
      setError(null);
      
      const { connectionId: connId, connectedAccount } = await initializeComposioMapbox();
      setConnectionId(connId);
      
      // Get available tools from Composio
      if (composioClientRef.current) {

 ... (clipped 16 lines)
mapbox_mcp/composio-mapbox.ts [16-37]
export async function authenticateToolkit(userId: string, authConfigId: string) {
  // TODO: Replace this with a method to retrieve the API key from the user.
  // In production, this should be securely retrieved from your database or user input.
  // For example: const userApiKey = await getUserApiKey(userId);
  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key
  
  const connectionRequest = await composio.connectedAccounts.initiate(
    userId,
    authConfigId,
    {

 ... (clipped 12 lines)

Solution Walkthrough:

Before:

// mapbox_mcp/hooks.ts
export const useMCPMapClient = () => {
  const connect = useCallback(async () => {
    // This hook is for client-side components, but it calls server-side logic directly.
    const { connectionId } = await initializeComposioMapbox();
    setConnectionId(connectionId);
    // ...
  }, []);
  // ...
};

// mapbox_mcp/composio-mapbox.ts
export async function initializeComposioMapbox() {
  const connectionId = await authenticateToolkit(...);
  return { connectionId };
}

export async function authenticateToolkit(...) {
  // This uses a server-side secret, which is undefined in the browser.
  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN; 
  // ... uses userApiKey to connect, which will fail.
}

After:

// pages/api/mapbox/connect.ts (New File)
export default async function handler(req, res) {
  // This API route runs securely on the server.
  try {
    // Authentication logic is moved here.
    const userApiKey = process.env.MAPBOX_ACCESS_TOKEN;
    const composio = new Composio();
    const connectionRequest = await composio.connectedAccounts.initiate(...);
    res.status(200).json({ connectionId: connectionRequest.id });
  } catch (error) {
    res.status(500).json({ error: "Failed to connect" });
  }
}

// mapbox_mcp/hooks.ts (Modified)
export const useMCPMapClient = () => {
  const connect = useCallback(async () => {
    // The client-side hook now calls the secure API endpoint.
    const response = await fetch('/api/mapbox/connect');
    const { connectionId } = await response.json();
    setConnectionId(connectionId);
    // ...
  }, []);
  // ...
};
Suggestion importance[1-10]: 9

__

Why: The suggestion correctly identifies a critical architectural flaw where server-side authentication logic using the secret MAPBOX_ACCESS_TOKEN is incorrectly placed in a client-side React hook, which will cause the feature to fail in the browser.

High
Security
Remove hardcoded fallback API key
Suggestion Impact:The commit removed the hardcoded "your_mapbox_api_key" fallback and added explicit environment validation that throws an error when MAPBOX_ACCESS_TOKEN is missing. It also refactored authentication to require the API key to be passed in, using the validated token.

code diff:

+/**
+ * Validate required environment variables
+ * @throws Error if any required environment variable is missing
+ */
+function validateEnvironmentVariables(): {
+  authConfigId: string;
+  userId: string;
+  mapboxToken: string;
+} {
+  const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
+  const userId = process.env.COMPOSIO_USER_ID;
+  const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN;
+
+  if (!authConfigId) {
+    throw new Error(
+      'COMPOSIO_MAPBOX_AUTH_CONFIG_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!userId) {
+    throw new Error(
+      'COMPOSIO_USER_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!mapboxToken) {
+    throw new Error(
+      'MAPBOX_ACCESS_TOKEN environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  return { authConfigId, userId, mapboxToken };
+}
 
 const composio = new Composio();
 
 /**
  * Authenticate Mapbox toolkit using Composio
+ * This should only be called server-side to avoid exposing API keys
  * @param userId - User ID from database/application
  * @param authConfigId - Auth config ID for Mapbox
+ * @param apiKey - Mapbox API key (should be retrieved securely)
  * @returns Connection ID
  */
-export async function authenticateToolkit(userId: string, authConfigId: string) {
-  // TODO: Replace this with a method to retrieve the API key from the user.
-  // In production, this should be securely retrieved from your database or user input.
-  // For example: const userApiKey = await getUserApiKey(userId);
-  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key
-  
+export async function authenticateToolkit(
+  userId: string,
+  authConfigId: string,
+  apiKey: string
+): Promise<string> {
+  if (!userId || !authConfigId || !apiKey) {
+    throw new Error(
+      'userId, authConfigId, and apiKey are required for authentication'
+    );
+  }
+
   const connectionRequest = await composio.connectedAccounts.initiate(
     userId,
     authConfigId,
     {
       config: AuthScheme.APIKey({
-        api_key: userApiKey
+        api_key: apiKey
       })
     }
   );
@@ -38,11 +78,15 @@
 
 /**
  * Initialize Composio connection for Mapbox
+ * This should only be called server-side to avoid exposing API keys
+ * @throws Error if environment variables are missing or connection fails
  */
 export async function initializeComposioMapbox() {
+  const { authConfigId, userId, mapboxToken } = validateEnvironmentVariables();
+
   try {
     // Authenticate the toolkit
-    const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);
+    const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken);
     

Remove the hardcoded fallback for MAPBOX_ACCESS_TOKEN and throw an error if the
environment variable is not set.

mapbox_mcp/composio-mapbox.ts [17-20]

 // TODO: Replace this with a method to retrieve the API key from the user.
 // In production, this should be securely retrieved from your database or user input.
 // For example: const userApiKey = await getUserApiKey(userId);
-const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key
+const userApiKey = process.env.MAPBOX_ACCESS_TOKEN;
+if (!userApiKey) {
+  throw new Error("MAPBOX_ACCESS_TOKEN environment variable is not set.");
+}

[Suggestion processed]

Suggestion importance[1-10]: 7

__

Why: This suggestion correctly identifies a potential issue where a missing MAPBOX_ACCESS_TOKEN would cause the code to use a placeholder value. Enforcing the presence of the variable improves security and makes configuration errors more explicit.

Medium
Possible issue
Fail fast on missing variables
Suggestion Impact:The commit removed the fallback placeholder values and introduced explicit validation that throws errors when required env vars are missing (including COMPOSIO_MAPBOX_AUTH_CONFIG_ID and COMPOSIO_USER_ID). It also expanded the validation to require MAPBOX_ACCESS_TOKEN and threaded the validated values into initialization/authentication.

code diff:

+/**
+ * Validate required environment variables
+ * @throws Error if any required environment variable is missing
+ */
+function validateEnvironmentVariables(): {
+  authConfigId: string;
+  userId: string;
+  mapboxToken: string;
+} {
+  const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
+  const userId = process.env.COMPOSIO_USER_ID;
+  const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN;
+
+  if (!authConfigId) {
+    throw new Error(
+      'COMPOSIO_MAPBOX_AUTH_CONFIG_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!userId) {
+    throw new Error(
+      'COMPOSIO_USER_ID environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  if (!mapboxToken) {
+    throw new Error(
+      'MAPBOX_ACCESS_TOKEN environment variable is required. ' +
+      'Please set it in your .env.local file.'
+    );
+  }
+
+  return { authConfigId, userId, mapboxToken };
+}
 
 const composio = new Composio();
 
 /**
  * Authenticate Mapbox toolkit using Composio
+ * This should only be called server-side to avoid exposing API keys
  * @param userId - User ID from database/application
  * @param authConfigId - Auth config ID for Mapbox
+ * @param apiKey - Mapbox API key (should be retrieved securely)
  * @returns Connection ID
  */
-export async function authenticateToolkit(userId: string, authConfigId: string) {
-  // TODO: Replace this with a method to retrieve the API key from the user.
-  // In production, this should be securely retrieved from your database or user input.
-  // For example: const userApiKey = await getUserApiKey(userId);
-  const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key
-  
+export async function authenticateToolkit(
+  userId: string,
+  authConfigId: string,
+  apiKey: string
+): Promise<string> {
+  if (!userId || !authConfigId || !apiKey) {
+    throw new Error(
+      'userId, authConfigId, and apiKey are required for authentication'
+    );
+  }
+
   const connectionRequest = await composio.connectedAccounts.initiate(
     userId,
     authConfigId,
     {
       config: AuthScheme.APIKey({
-        api_key: userApiKey
+        api_key: apiKey
       })
     }
   );
@@ -38,11 +78,15 @@
 
 /**
  * Initialize Composio connection for Mapbox
+ * This should only be called server-side to avoid exposing API keys
+ * @throws Error if environment variables are missing or connection fails
  */
 export async function initializeComposioMapbox() {
+  const { authConfigId, userId, mapboxToken } = validateEnvironmentVariables();
+
   try {
     // Authenticate the toolkit
-    const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);
+    const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken);
     

Instead of using fallback values for COMPOSIO_MAPBOX_AUTH_CONFIG_ID and
COMPOSIO_USER_ID, check for their existence and throw an error if they are not
set.

mapbox_mcp/composio-mapbox.ts [4-6]

-// Replace these with your actual values
-const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
-const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application
+const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
+const userId = process.env.COMPOSIO_USER_ID;
 
+if (!mapbox_auth_config_id || !userId) {
+  throw new Error("Missing required Composio environment variables: COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID");
+}
+

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: This is a valid suggestion that improves robustness by ensuring the application fails fast with a clear error message if required environment variables are missing, rather than using placeholder values that would cause issues later.

Low
General
Stabilize callbacks to prevent re-renders

To prevent unnecessary re-renders, store connectionId in a useRef and remove it
from the useCallback dependency array to stabilize the function's identity.

mapbox_mcp/hooks.ts [163-182]

+const connectionIdRef = useRef<string | null>(null);
+...
+// in connect function
+setConnectionId(connId);
+connectionIdRef.current = connId;
+...
+
 const geocodeLocation = useCallback(async (address: string): Promise<LocationResult> => {
-  if (!isConnected || !composioClientRef.current || !connectionId) {
+  if (!isConnected || !composioClientRef.current || !connectionIdRef.current) {
     throw new Error('Composio client not connected');
   }
   try {
     const result = await composioClientRef.current.executeAction({
       action: 'mapbox_geocode_location',
       params: {
         query: address,
         includeMapPreview: true,
       },
-      connectedAccountId: connectionId,
+      connectedAccountId: connectionIdRef.current,
     });
     return result.data;
   } catch (err) {
     console.error('Geocoding error:', err);
     setError(`Geocoding error: ${err}`);
     throw err;
   }
-}, [isConnected, connectionId]);
+}, [isConnected]); // or even [] if isConnected check is also based on a ref

[To ensure code accuracy, apply this suggestion manually]

Suggestion importance[1-10]: 5

__

Why: The suggestion proposes a valid optimization to stabilize callback identities using refs, which can prevent unnecessary re-renders. While correct, this is a performance micro-optimization and the current implementation is functionally correct.

Low
  • Update

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
.env.local.example (1)

1-15: Clarify the difference between MAPBOX_ACCESS_TOKEN variants.

The example defines both MAPBOX_ACCESS_TOKEN (line 7) and references NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN (line 13-15).

Clarify when to use each:

  • MAPBOX_ACCESS_TOKEN: For server-side Composio integration
  • NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN: For client-side mapbox-gl rendering

Consider adding a comment explaining this distinction.

mapbox_mcp/hooks.ts (1)

96-161: Critical: Composio tools are incompatible with Vercel AI SDK's generateText.

Line 105 passes toolsRef.current (raw Composio tool descriptors from getTools()) directly to generateText. The Vercel AI SDK requires tools to have Zod schemas and execute functions, but raw Composio tools lack this structure.

Composio provides official adapters (@composio/vercel provider or VercelAIToolSet) to convert tools to the correct format, but they are not being used. This will cause runtime failures when the model attempts to call tools.

You need to either:

  1. Use VercelAIToolSet from @composio/core to convert tools before passing to generateText
  2. Use the @composio/vercel provider during Composio initialization
  3. Remove AI-assisted query processing and use direct action execution instead
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d30030 and cf9024c.

📒 Files selected for processing (8)
  • .env.local.example
  • COMPOSIO_MIGRATION.md
  • mapbox_mcp/README.md
  • mapbox_mcp/composio-mapbox.ts
  • mapbox_mcp/hooks.ts
  • mapbox_mcp/index.ts
  • mapbox_mcp_config.json
  • package.json
🧰 Additional context used
🧬 Code graph analysis (4)
mapbox_mcp/composio-mapbox.ts (2)
components/map/mapbox-map.tsx (1)
  • map (422-459)
components/map/geojson-layer.tsx (1)
  • map (16-97)
.env.local.example (1)
lib/agents/tools/geospatial.tsx (1)
  • MapboxConfig (27-31)
mapbox_mcp/hooks.ts (2)
mapbox_mcp/composio-mapbox.ts (2)
  • getComposioClient (61-63)
  • initializeComposioMapbox (42-56)
lib/agents/tools/geospatial.tsx (1)
  • getConnectedMcpClient (36-129)
mapbox_mcp/index.ts (1)
mapbox_mcp/composio-mapbox.ts (2)
  • initializeComposioMapbox (42-56)
  • getComposioClient (61-63)
🪛 dotenv-linter (4.0.0)
.env.local.example

[warning] 3-3: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 4-4: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 7-7: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 10-10: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)


[warning] 11-11: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)

🪛 LanguageTool
COMPOSIO_MIGRATION.md

[grammar] ~31-~31: Ensure spelling is correct
Context: ...your_smithery_api_key_here" **New (Composio):**bash COMPOSIO_MAPBOX_AUTH_CONFIG...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)
mapbox_mcp/README.md

36-36: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


41-41: Bare URL used

(MD034, no-bare-urls)


47-47: Bare URL used

(MD034, no-bare-urls)


50-50: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

COMPOSIO_MIGRATION.md

24-24: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


32-32: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


42-42: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


45-45: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


66-66: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


83-83: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


93-93: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


101-101: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


109-109: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


136-136: Bare URL used

(MD034, no-bare-urls)


145-145: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🔇 Additional comments (10)
mapbox_mcp/README.md (1)

101-108: LGTM!

The migration summary appropriately references the detailed guide and covers the key changes at a high level.

COMPOSIO_MIGRATION.md (3)

11-38: LGTM!

The dependencies and environment variables sections accurately document the changes from Smithery to Composio, matching the updates in package.json and .env.local.example.


40-76: Configuration changes accurately documented.

The old and new configuration structures are clearly shown. The migration from MCP server command-based config to Composio's structured config is well-documented.


189-216: Troubleshooting section provides good coverage.

The troubleshooting section covers common issues and their solutions. The action names listed should be verified against Composio's actual Mapbox integration (already requested in previous comment).

package.json (1)

44-44: Correct the package name or version: @composio/core version 0.5.0 does not exist.

The scoped package @composio/core has a latest version of 0.1.50. Version 0.5.0 exists only for the unscoped package composio-core (latest 0.5.39). Verify which package is intended and update the dependency accordingly.

Likely an incorrect or invalid review comment.

mapbox_mcp_config.json (1)

1-9: Fix configuration structure: authConfigId and userId are not Composio SDK fields.

The configuration file is loaded by lib/agents/tools/geospatial.tsx, but the JSON structure does not match Composio @composio/core SDK requirements. The SDK expects apiKey (minimum required), baseURL, allowTracking, and allowTracing—not authConfigId, userId, or nested composio.mapbox structure.

Additionally:

  • The placeholder value ac_YOUR_MAPBOX_CONFIG_ID is hardcoded in the config file rather than loaded from environment variables (despite the description claiming env vars should be set).
  • The authConfigId and userId appear to be custom application fields, not Composio SDK configuration. If these are needed, they should be documented separately or moved to a different configuration layer.

Either update the structure to match Composio SDK requirements (with apiKey at minimum) or clarify this is a custom application config and adjust the description accordingly.

Likely an incorrect or invalid review comment.

mapbox_mcp/composio-mapbox.ts (1)

42-56: LGTM with caveat on upstream validation.

The function has good error handling with try/catch and proper logging. The connection verification via composio.connectedAccounts.get(connectionId) is a good practice. This will work correctly once the upstream environment variable validation issues are addressed.

mapbox_mcp/index.ts (1)

36-56: LGTM - Good defensive programming.

The tool discovery and conditional execution pattern is well implemented. The check for geocodeAction existence before attempting execution prevents runtime errors if the action isn't available, and the separate try/catch for the tool call provides clear error isolation.

mapbox_mcp/hooks.ts (2)

63-88: LGTM - Solid connection handling.

The connect function has proper error handling, state management with try/catch/finally, and defensive checks before accessing composioClientRef.current. The logging provides good debugging visibility.


163-228: LGTM - Consistent action execution pattern.

The three action functions (geocodeLocation, calculateDistance, searchNearbyPlaces) follow a consistent pattern with proper connection checks, error handling, and structured parameters. The use of connectionId for connectedAccountId correctly associates actions with the authenticated connection.

Comment on lines +1 to +252
# Migration Guide: Smithery to Composio

This document outlines the migration from Smithery to Composio for the Mapbox integration in QCX.

## Overview

The QCX project has migrated from using Smithery's MCP server hosting to Composio's integration platform for Mapbox functionality. This change provides better scalability, more robust authentication, and improved tool management.

## What Changed

### 1. Dependencies

**Removed:**
- `@smithery/cli` (^1.2.5)
- `@smithery/sdk` (^1.0.4)
- `smithery` (^0.5.2)

**Added:**
- `@composio/core` (^0.5.0)

### 2. Environment Variables

**Old (Smithery):**
```bash
SMITHERY_PROFILE_ID="your_smithery_profile_id_here"
SMITHERY_API_KEY="your_smithery_api_key_here"
NEXT_PUBLIC_SMITHERY_PROFILE_ID="your_smithery_profile_id_here"
NEXT_PUBLIC_SMITHERY_API_KEY="your_smithery_api_key_here"
```

**New (Composio):**
```bash
COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_MAPBOX_CONFIG_ID"
COMPOSIO_USER_ID="user@example.com"
MAPBOX_ACCESS_TOKEN="your_mapbox_api_key"
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_MAPBOX_CONFIG_ID"
NEXT_PUBLIC_COMPOSIO_USER_ID="user@example.com"
```

### 3. Configuration Files

**mapbox_mcp_config.json**

**Old:**
```json
{
"mcpServers": {
"mapbox-mcp-server": {
"command": "npx",
"args": [
"-y",
"@smithery/cli@latest",
"run",
"@ngoiyaeric/mapbox-mcp-server",
"--key",
"705b0222-a657-4cd2-b180-80c406cf6179",
"--profile",
"smooth-lemur-vfUbUE"
]
}
}
}
```

**New:**
```json
{
"composio": {
"mapbox": {
"authConfigId": "ac_YOUR_MAPBOX_CONFIG_ID",
"userId": "user@example.com",
"description": "Composio configuration for Mapbox integration"
}
}
}
```

### 4. Code Changes

#### mapbox_mcp/hooks.ts

**Old Connection Method:**
```typescript
const mcp = useMcp({
url: `https://server.smithery.ai/@Waldzell-Agentics/mcp-server/mcp?profile=${process.env.NEXT_PUBLIC_SMITHERY_PROFILE_ID}&api_key=${process.env.NEXT_PUBLIC_SMITHERY_API_KEY}`,
debug: process.env.NODE_ENV === 'development',
autoReconnect: true,
autoRetry: 5000,
});
```

**New Connection Method:**
```typescript
const composioClient = getComposioClient();
const { connectionId, connectedAccount } = await initializeComposioMapbox();
```

#### Tool Execution

**Old:**
```typescript
const result = await mcp.callTool('geocode_location', {
query: address,
includeMapPreview: true,
});
```

**New:**
```typescript
const result = await composioClient.executeAction({
action: 'mapbox_geocode_location',
params: {
query: address,
includeMapPreview: true,
},
connectedAccountId: connectionId,
});
```

## Migration Steps

### Step 1: Install Composio

```bash
bun install @composio/core
```

### Step 2: Remove Smithery Dependencies

```bash
bun remove @smithery/cli @smithery/sdk smithery
```

### Step 3: Set Up Composio Account

1. Sign up at https://composio.dev
2. Create a new auth config for Mapbox
3. Select "API Key" as the authentication method
4. Note your auth config ID (starts with `ac_`)

### Step 4: Update Environment Variables

1. Copy `.env.local.example` to `.env.local` (if not already done)
2. Replace Smithery variables with Composio variables:
```bash
COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_ACTUAL_CONFIG_ID"
COMPOSIO_USER_ID="your_email@example.com"
MAPBOX_ACCESS_TOKEN="your_mapbox_token"
```

### Step 5: Update Code References

The following files have been updated automatically:
- `mapbox_mcp/composio-mapbox.ts` (new file)
- `mapbox_mcp/hooks.ts` (updated)
- `mapbox_mcp/index.ts` (updated)
- `mapbox_mcp_config.json` (updated)
- `package.json` (updated)
- `.env.local.example` (updated)

### Step 6: Test the Integration

```bash
# Test the connection
bun run mapbox_mcp/index.ts

# Run the development server
bun run dev
```

## API Compatibility

The `useMCPMapClient` hook maintains the same interface, so existing components using it should continue to work without changes:

```typescript
const {
isConnected,
isLoading,
error,
connect,
disconnect,
processLocationQuery,
geocodeLocation,
calculateDistance,
searchNearbyPlaces,
} = useMCPMapClient();
```

## Troubleshooting

### Issue: "Composio client not connected"

**Solution:** Ensure you've called `connect()` before using any tool functions:

```typescript
useEffect(() => {
connect();
}, [connect]);
```

### Issue: "Invalid auth config ID"

**Solution:** Verify your `COMPOSIO_MAPBOX_AUTH_CONFIG_ID` starts with `ac_` and is copied correctly from the Composio dashboard.

### Issue: "Mapbox API key invalid"

**Solution:** Check that your `MAPBOX_ACCESS_TOKEN` is valid and has the necessary scopes enabled in your Mapbox account.

### Issue: Tool execution fails

**Solution:** Verify the action names match Composio's Mapbox integration. Common actions:
- `mapbox_geocode_location`
- `mapbox_calculate_distance`
- `mapbox_search_nearby_places`
- `mapbox_generate_map_link`

## Benefits of Composio

1. **Better Authentication Management**: Centralized auth config management
2. **Improved Security**: API keys stored securely in Composio
3. **Scalability**: Better handling of multiple integrations
4. **Monitoring**: Built-in logging and monitoring in Composio dashboard
5. **Flexibility**: Easier to add new tools and integrations

## Resources

- [Composio Documentation](https://docs.composio.dev)
- [Composio GitHub](https://github.com/ComposioHQ/composio)
- [Mapbox API Documentation](https://docs.mapbox.com)
- [QCX Documentation](https://deepwiki.com/QueueLab/QCX)

## Support

If you encounter issues during migration:
1. Check the Composio dashboard for connection status
2. Review the logs in your development console
3. Consult the [mapbox_mcp/README.md](./mapbox_mcp/README.md) file
4. Open an issue in the QCX repository

## Rollback

If you need to rollback to Smithery:

```bash
# Reinstall Smithery packages
bun install @smithery/cli@^1.2.5 @smithery/sdk@^1.0.4 smithery@^0.5.2

# Restore old environment variables in .env.local
# Restore old code from git history
git checkout HEAD~1 -- mapbox_mcp/
```

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Fix markdown formatting issues throughout the document.

Static analysis detected multiple formatting issues:

  • Missing blank lines before/after fenced code blocks (MD031)
  • Bare URLs that should be wrapped in angle brackets (MD034)
  • Emphasis used instead of heading for "Old:" and "New:" labels (MD036)

These are minor but should be fixed for consistency with markdown best practices.

🧰 Tools
🪛 LanguageTool

[grammar] ~31-~31: Ensure spelling is correct
Context: ...your_smithery_api_key_here" **New (Composio):**bash COMPOSIO_MAPBOX_AUTH_CONFIG...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)

24-24: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


32-32: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


42-42: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


45-45: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


66-66: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


83-83: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


93-93: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


101-101: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


109-109: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


136-136: Bare URL used

(MD034, no-bare-urls)


145-145: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
In COMPOSIO_MIGRATION.md lines 1-252, fix Markdown lint issues by ensuring there
is a blank line before and after every fenced code block throughout the document
(MD031), wrap all bare URLs in angle brackets (e.g., <https://...>) (MD034), and
replace emphasized "Old:" and "New:" labels with proper subheadings or bolded
labels (e.g., use "### Old" / "### New" or bold text) so they are treated as
headings (MD036); apply these edits consistently for each section (Dependencies,
Environment Variables, Configuration Files, Code Changes, Migration Steps,
Troubleshooting, Resources, Rollback) to resolve the formatting warnings.

Comment on lines +134 to +149
### Step 3: Set Up Composio Account

1. Sign up at https://composio.dev
2. Create a new auth config for Mapbox
3. Select "API Key" as the authentication method
4. Note your auth config ID (starts with `ac_`)

### Step 4: Update Environment Variables

1. Copy `.env.local.example` to `.env.local` (if not already done)
2. Replace Smithery variables with Composio variables:
```bash
COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_ACTUAL_CONFIG_ID"
COMPOSIO_USER_ID="your_email@example.com"
MAPBOX_ACCESS_TOKEN="your_mapbox_token"
```
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Clarify authentication setup steps.

Step 3 mentions creating an auth config for Mapbox and selecting "API Key" as the authentication method. This could be confusing because:

  1. The guide doesn't explain how to get a Composio API key for authenticating the SDK itself
  2. "API Key" refers to Mapbox's auth method, not Composio's

Consider adding a step to obtain the Composio API key before creating the Mapbox auth config.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

136-136: Bare URL used

(MD034, no-bare-urls)


145-145: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
In COMPOSIO_MIGRATION.md around lines 134 to 149, clarify the authentication
setup by adding a step to obtain a Composio SDK API key (and where to
find/create it in the Composio dashboard) before instructing users to create the
Mapbox auth config; explicitly state that the "API Key" selection in Step 3
refers to Mapbox's authentication method (not Composio's) and show which
environment variable should hold the Composio API key (e.g., COMPOSIO_API_KEY)
in the Step 4 env example alongside COMPOSIO_MAPBOX_AUTH_CONFIG_ID,
COMPOSIO_USER_ID and MAPBOX_ACCESS_TOKEN so users know both keys are required
and where to paste each.

Comment on lines +240 to +252
## Rollback

If you need to rollback to Smithery:

```bash
# Reinstall Smithery packages
bun install @smithery/cli@^1.2.5 @smithery/sdk@^1.0.4 smithery@^0.5.2

# Restore old environment variables in .env.local
# Restore old code from git history
git checkout HEAD~1 -- mapbox_mcp/
```

Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Clarify rollback command.

The rollback command git checkout HEAD~1 -- mapbox_mcp/ assumes the previous commit contains the Smithery code, which may not be accurate if this PR includes multiple commits or if the branch has been rebased.

Consider updating to:

# Check out from the commit before this PR was merged
git checkout <commit-hash-before-pr> -- mapbox_mcp/

Or provide instructions to check git history first.

🤖 Prompt for AI Agents
In COMPOSIO_MIGRATION.md around lines 240-252, the rollback step uses a fragile
command git checkout HEAD~1 -- mapbox_mcp/; update the instructions to tell
users to check out the exact commit hash before the PR (e.g. git checkout
<commit-hash-before-pr> -- mapbox_mcp/) and add a brief note on how to find that
hash (suggest running git log --oneline or git reflog to identify the correct
commit) so they use an explicit commit rather than HEAD~1.

Comment on lines 36 to 52
```bash
bun install @composio/core
```

2. **Create Mapbox Auth Config in Composio**:
- Sign up for a Composio account at https://composio.dev
- Create an auth config for Mapbox with API Key authentication
- Note the auth config ID (starts with `ac_`)

3. **Set Environment Variables**:
- Copy the values from your Composio dashboard
- Add your Mapbox access token from https://account.mapbox.com

4. **Test the Connection**:
```bash
bun run mapbox_mcp/index.ts
```
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Fix markdown formatting issues.

Static analysis detected minor formatting issues:

  1. Missing blank lines around fenced code blocks (lines 36, 50)
  2. Bare URLs should be wrapped in angle brackets (lines 41, 47)
🔎 Proposed formatting fixes
 1. **Install Composio SDK**:
+
    ```bash
    bun install @composio/core
    ```
 
 2. **Create Mapbox Auth Config in Composio**:
-   - Sign up for a Composio account at https://composio.dev
+   - Sign up for a Composio account at <https://composio.dev>
    - Create an auth config for Mapbox with API Key authentication
    - Note the auth config ID (starts with `ac_`)
 
 3. **Set Environment Variables**:
    - Copy the values from your Composio dashboard
-   - Add your Mapbox access token from https://account.mapbox.com
+   - Add your Mapbox access token from <https://account.mapbox.com>
 
 4. **Test the Connection**:
+
    ```bash
    bun run mapbox_mcp/index.ts
    ```
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

36-36: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


41-41: Bare URL used

(MD034, no-bare-urls)


47-47: Bare URL used

(MD034, no-bare-urls)


50-50: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
mapbox_mcp/README.md lines 36-52: the fenced code blocks and bare URLs are
improperly formatted; add blank lines before and after each triple-backtick
fenced block, wrap bare URLs in angle brackets (e.g. <https://composio.dev>,
<https://account.mapbox.com>), and normalize the surrounding list
indentation/bullets so the code fence stands on its own line; ensure the final
"Test the Connection" header is followed by a blank line then the ```bash block
and a blank line after the closing ``` to satisfy Markdown formatting.

Comment on lines 40 to 52
2. **Create Mapbox Auth Config in Composio**:
- Sign up for a Composio account at https://composio.dev
- Create an auth config for Mapbox with API Key authentication
- Note the auth config ID (starts with `ac_`)

3. **Set Environment Variables**:
- Copy the values from your Composio dashboard
- Add your Mapbox access token from https://account.mapbox.com

4. **Test the Connection**:
```bash
bun run mapbox_mcp/index.ts
```
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Clarify Composio account authentication setup.

The setup instructions mention creating an auth config in the Composio dashboard but don't explain how to obtain API credentials for authenticating the Composio SDK itself. Users will need a Composio API key to make SDK calls, separate from the Mapbox auth config.

Consider adding a step like:

2. **Get Composio API Key**:
   - Log into your Composio dashboard
   - Navigate to Settings > API Keys
   - Generate a new API key and save it as `COMPOSIO_API_KEY`
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

41-41: Bare URL used

(MD034, no-bare-urls)


47-47: Bare URL used

(MD034, no-bare-urls)


50-50: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
In mapbox_mcp/README.md around lines 40 to 52, the instructions skip how to
obtain and set a Composio API key required for authenticating SDK calls; add a
step before creating the Mapbox auth config that instructs users to log into the
Composio dashboard, go to Settings > API Keys (or equivalent), generate a new
API key, and export it as an environment variable (e.g., COMPOSIO_API_KEY) so
the SDK can authenticate when creating the Mapbox auth config.

Copy link

@charliecreates charliecreates bot left a comment

Choose a reason for hiding this comment

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

Key issues are around security boundaries and runtime correctness: the React hook currently performs Composio connection initiation using MAPBOX_ACCESS_TOKEN (a server secret), which risks exposing credentials in client bundles. Additionally, composio-mapbox.ts uses placeholder fallbacks for required env vars, leading to non-deterministic failures and making it easy to accidentally ship code that authenticates with dummy values. Finally, disconnect() doesn’t clean up Composio-side connections and index.ts validates env vars that aren’t necessarily the ones used during initialization.

Additional notes (1)
  • Maintainability | mapbox_mcp/hooks.ts:96-101
    The hook uses toolsRef.current as the tools passed into generateText(), but connect() currently loads tools from composioClient.getTools({ apps: ['mapbox'] }). Those tool identifiers appear to be Composio action names (e.g. mapbox_geocode_location), while the system prompt still describes MCP tool names like geocode_location, calculate_distance, etc.

This mismatch can degrade tool selection and cause the model to call non-existent tools/actions (or call the wrong ones) because the instructions and available tool schema don’t align.

Summary of changes

Summary

This PR migrates the Mapbox integration from Smithery / MCP to Composio.

Dependency updates

  • Removed Smithery packages (e.g. @smithery/cli, @smithery/sdk, smithery)
  • Added @composio/core@^0.5.0

Configuration & env

  • Updated .env.local.example to Composio variables like COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID, and MAPBOX_ACCESS_TOKEN
  • Replaced mapbox_mcp_config.json from an MCP server config to a composio.mapbox config object

New Composio client module

  • Added mapbox_mcp/composio-mapbox.ts with helper functions:
    • authenticateToolkit(...)
    • initializeComposioMapbox()
    • getComposioClient()

Hook + test script migration

  • Updated mapbox_mcp/hooks.ts to:
    • Initialize a Composio client on mount
    • Establish a connected account via initializeComposioMapbox()
    • Execute Mapbox operations via executeAction({ action: 'mapbox_*', ... })
  • Updated mapbox_mcp/index.ts to test Composio connection and run a sample mapbox_geocode_location action

Docs

  • Added mapbox_mcp/README.md and COMPOSIO_MIGRATION.md describing setup, env vars, and migration steps

Comment on lines 4 to 37
// Replace these with your actual values
const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application

const composio = new Composio();

/**
* Authenticate Mapbox toolkit using Composio
* @param userId - User ID from database/application
* @param authConfigId - Auth config ID for Mapbox
* @returns Connection ID
*/
export async function authenticateToolkit(userId: string, authConfigId: string) {
// TODO: Replace this with a method to retrieve the API key from the user.
// In production, this should be securely retrieved from your database or user input.
// For example: const userApiKey = await getUserApiKey(userId);
const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key

const connectionRequest = await composio.connectedAccounts.initiate(
userId,
authConfigId,
{
config: AuthScheme.APIKey({
api_key: userApiKey
})
}
);

// API Key authentication is immediate - no redirect needed
console.log(`Successfully connected Mapbox for user ${userId}`);
console.log(`Connection status: ${connectionRequest.status}`);

return connectionRequest.id;
}
Copy link

Choose a reason for hiding this comment

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

initializeComposioMapbox() uses module-level defaults:

  • mapbox_auth_config_id falls back to a placeholder string
  • userId falls back to user@example.com
  • userApiKey falls back to your_mapbox_api_key

This means the hook/test can “successfully” attempt to connect with bogus values and only fail deep in Composio, producing noisy runtime behavior. It also makes it easy to accidentally ship code that attempts auth with placeholder credentials.

Prefer failing fast when required env vars are missing, and avoid hard-coded placeholders in runtime logic (placeholders belong in .env.local.example and docs, not executable code).

Suggestion

Fail fast and remove runtime fallbacks to placeholder strings. For example:

const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
const userId = process.env.COMPOSIO_USER_ID;
const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN;

function requireEnv(name: string, value: string | undefined): string {
  if (!value) throw new Error(`${name} is required`);
  return value;
}

export async function initializeComposioMapbox() {
  const resolvedUserId = requireEnv('COMPOSIO_USER_ID', userId);
  const resolvedAuthConfigId = requireEnv('COMPOSIO_MAPBOX_AUTH_CONFIG_ID', authConfigId);
  const resolvedToken = requireEnv('MAPBOX_ACCESS_TOKEN', mapboxToken);

  const connectionId = await authenticateToolkit(resolvedUserId, resolvedAuthConfigId, resolvedToken);
  // ...
}

export async function authenticateToolkit(userId: string, authConfigId: string, token: string) {
  const connectionRequest = await composio.connectedAccounts.initiate(userId, authConfigId, {
    config: AuthScheme.APIKey({ api_key: token }),
  });
  return connectionRequest.id;
}

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

Comment on lines 4 to 63
// Replace these with your actual values
const mapbox_auth_config_id = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID || "ac_YOUR_MAPBOX_CONFIG_ID"; // Auth config ID created above
const userId = process.env.COMPOSIO_USER_ID || "user@example.com"; // User ID from database/application

const composio = new Composio();

/**
* Authenticate Mapbox toolkit using Composio
* @param userId - User ID from database/application
* @param authConfigId - Auth config ID for Mapbox
* @returns Connection ID
*/
export async function authenticateToolkit(userId: string, authConfigId: string) {
// TODO: Replace this with a method to retrieve the API key from the user.
// In production, this should be securely retrieved from your database or user input.
// For example: const userApiKey = await getUserApiKey(userId);
const userApiKey = process.env.MAPBOX_ACCESS_TOKEN || "your_mapbox_api_key"; // Replace with actual API key

const connectionRequest = await composio.connectedAccounts.initiate(
userId,
authConfigId,
{
config: AuthScheme.APIKey({
api_key: userApiKey
})
}
);

// API Key authentication is immediate - no redirect needed
console.log(`Successfully connected Mapbox for user ${userId}`);
console.log(`Connection status: ${connectionRequest.status}`);

return connectionRequest.id;
}

/**
* Initialize Composio connection for Mapbox
*/
export async function initializeComposioMapbox() {
try {
// Authenticate the toolkit
const connectionId = await authenticateToolkit(userId, mapbox_auth_config_id);

// Verify the connection
const connectedAccount = await composio.connectedAccounts.get(connectionId);
console.log("Connected account:", connectedAccount);

return { connectionId, connectedAccount };
} catch (error) {
console.error("Failed to initialize Composio Mapbox connection:", error);
throw error;
}
}

/**
* Get Composio instance for Mapbox operations
*/
export function getComposioClient() {
return composio;
}
Copy link

Choose a reason for hiding this comment

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

mapbox_mcp/composio-mapbox.ts creates a module-level singleton composio = new Composio() and also performs connection initiation using fallback placeholder secrets (e.g., "your_mapbox_api_key", "ac_YOUR_MAPBOX_CONFIG_ID"). This is risky:

  • In non-test environments, missing env vars will silently proceed with invalid credentials, producing confusing failures.
  • Module-level singletons can leak state across requests in server runtimes (e.g., Next.js serverless/edge) and across users; plus the current initializeComposioMapbox() uses a single COMPOSIO_USER_ID for everyone.

At minimum, treat missing env vars as a hard error and avoid placeholders for anything that resembles a credential. Also consider making getComposioClient() create per-request/per-user clients (or at least isolating connected account per user) if this hook is used by multiple signed-in users.

Suggestion

Tighten configuration + remove secret placeholders. Example:

const requireEnv = (key: string): string => {
  const v = process.env[key];
  if (!v) throw new Error(`${key} is required`);
  return v;
};

export const getConfig = () => ({
  authConfigId: requireEnv('COMPOSIO_MAPBOX_AUTH_CONFIG_ID'),
  userId: requireEnv('COMPOSIO_USER_ID'),
  mapboxToken: requireEnv('MAPBOX_ACCESS_TOKEN'),
});

export async function authenticateToolkit(userId: string, authConfigId: string, mapboxToken: string) {
  const connectionRequest = await composio.connectedAccounts.initiate(userId, authConfigId, {
    config: AuthScheme.APIKey({ api_key: mapboxToken }),
  });
  return connectionRequest.id;
}

export async function initializeComposioMapbox() {
  const { userId, authConfigId, mapboxToken } = getConfig();
  const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken);
  const connectedAccount = await composio.connectedAccounts.get(connectionId);
  return { connectionId, connectedAccount };
}

This makes failures explicit and prevents accidental use of placeholder credentials in production. Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

Comment on lines 57 to 88
// Initialize Composio client on mount
useEffect(() => {
composioClientRef.current = getComposioClient();
}, []);

// Update connection status based on MCP state
// Connect to Composio Mapbox
const connect = useCallback(async () => {
if (mcp.state === 'ready') {
try {
setIsLoading(true);
setError(null);
toolsRef.current = mcp.tools;
setIsConnected(true);
console.log('✅ Connected to MCP server');
console.log('Available tools:', mcp.tools.map((tool: Tool) => tool.name));
} catch (err) {
setError(`Failed to connect to MCP server: ${err}`);
console.error('❌ MCP connection error:', err);
} finally {
setIsLoading(false);
try {
setIsLoading(true);
setError(null);

const { connectionId: connId, connectedAccount } = await initializeComposioMapbox();
setConnectionId(connId);

// Get available tools from Composio
if (composioClientRef.current) {
const tools = await composioClientRef.current.getTools({
apps: ['mapbox']
});
toolsRef.current = tools;
}

setIsConnected(true);
console.log('✅ Connected to Composio Mapbox');
console.log('Connection ID:', connId);
} catch (err) {
setError(`Failed to connect to Composio Mapbox: ${err}`);
console.error('❌ Composio connection error:', err);
} finally {
setIsLoading(false);
}
}, [mcp.state, mcp.tools]);
}, []);
Copy link

Choose a reason for hiding this comment

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

This file appears to implement client-side React hooks (useEffect, useState) but calls initializeComposioMapbox() which (in composio-mapbox.ts) reads process.env.MAPBOX_ACCESS_TOKEN and initiates a connected account using a raw Mapbox API key.

If this hook is used in the browser (likely, given NEXT_PUBLIC_* env vars were added), this risks exposing server secrets (Mapbox token) and potentially performing privileged Composio operations directly from the client.

Even if your bundler replaces process.env.* at build time, shipping an API key to the browser is a security issue. The presence of NEXT_PUBLIC_COMPOSIO_* suggests the intended usage might be client-side—this needs a clear separation:

  • Browser should never have MAPBOX_ACCESS_TOKEN.
  • Connecting/authentication should happen server-side (API route / server action), returning a short-lived token/connectedAccountId if needed.

Right now the code path makes it too easy to accidentally do the unsafe thing.

Suggestion

Move Composio authentication + connected-account initiation to a server-only endpoint, and have the hook call that endpoint to obtain a connectedAccountId.

Example shape:

  1. Server route /api/composio/mapbox/connect:
// runs on server
export async function POST() {
  // read COMPOSIO_* and MAPBOX_ACCESS_TOKEN (server env only)
  const { connectionId } = await initializeComposioMapbox();
  return Response.json({ connectionId });
}
  1. Hook:
const res = await fetch('/api/composio/mapbox/connect', { method: 'POST' });
const { connectionId } = await res.json();
setConnectionId(connectionId);

Also: drop NEXT_PUBLIC_COMPOSIO_USER_ID unless there is a strong reason to expose it.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

Comment on lines 90 to 94
const disconnect = useCallback(async () => {
if (mcp.state === 'ready') {
await mcp.disconnect();
toolsRef.current = null;
setIsConnected(false);
}
}, [mcp.state]);
toolsRef.current = null;
setIsConnected(false);
setConnectionId(null);
}, []);
Copy link

Choose a reason for hiding this comment

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

disconnect() only clears local state and refs, but does not revoke/close anything on the Composio side. If connect() creates a new connected account each time (likely, since it calls connectedAccounts.initiate(...)), repeated connect/disconnect cycles can leak connected accounts and clutter Composio.

At minimum, consider reusing an existing connectionId or providing a cleanup path (delete/revoke) when disconnecting.

Suggestion

Avoid creating a new connected account on every connect() call. Options:

  • Cache/persist connectionId (e.g. localStorage or backend) and reuse it.
  • Or, implement a server endpoint to revoke/delete the connected account and call it from disconnect().

Sketch:

const disconnect = useCallback(async () => {
  if (connectionId) await fetch('/api/composio/mapbox/disconnect', { method: 'POST', body: JSON.stringify({ connectionId }) });
  // then clear state
}, [connectionId]);

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

Comment on lines 7 to 33
const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID;
const userId = process.env.COMPOSIO_USER_ID;
const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN;

// Environment variables required by this script to connect to the Smithery-hosted MCP server.
// - SMITHERY_PROFILE_ID: Your Smithery profile ID.
// - SMITHERY_API_KEY: Your Smithery API key for authentication.
// Note: The Mapbox Access Token (MAPBOX_ACCESS_TOKEN) is configured on the server-side (on Smithery)
// and is not directly passed by this client script during the connection setup for this particular example.
const profileId = process.env.SMITHERY_PROFILE_ID;
const apiKey = process.env.SMITHERY_API_KEY;
const serverName = "mapbox-mcp-server"; // The unique name of your MCP server deployed on Smithery.

async function testMCPConnection() {
// Check for required environment variables for Smithery connection.
if (!profileId || !apiKey) {
console.error("SMITHERY_PROFILE_ID and SMITHERY_API_KEY environment variables are required for this script.");
async function testComposioConnection() {
// Check for required environment variables for Composio connection.
if (!authConfigId || !userId || !mapboxToken) {
console.error("COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID, and MAPBOX_ACCESS_TOKEN environment variables are required for this script.");
return; // Return early if essential credentials are missing.
}

// Construct the server URL for SSE (Server-Sent Events) transport.
const serverUrl = `https://server.smithery.ai/${serverName}/mcp?profile=${profileId}&api_key=${apiKey}`;

// Declare client variable for cleanup in finally block.
let client: any; // Type would ideally be defined by use-mcp's Node.js client type.
let composioClient: any;

try {
// Log the connection attempt (masking API key for security).
const urlToLog = serverUrl.split('?')[0] + `?profile=${profileId}&api_key=****`;
console.log(`Attempting to connect to MCP server at ${urlToLog}...`);
console.log(`Attempting to connect to Composio Mapbox...`);

// Initialize the MCP client using createMcpClient (assumed Node.js equivalent of useMcp).
client = await useMcp({
url: serverUrl,
autoReconnect: true,
autoRetry: 5000,
debug: process.env.NODE_ENV === 'development',
});
// Initialize the Composio client and authenticate
const { connectionId, connectedAccount } = await initializeComposioMapbox();
composioClient = getComposioClient();

console.log("✅ Successfully connected to MCP server.");
console.log("✅ Successfully connected to Composio Mapbox.");
console.log("Connection ID:", connectionId);

// Fetch and list available tools from the server.
const tools = await client.tools();
console.log("🛠️ Available tools:", tools.map((tool: Tool) => tool.name));
// Fetch and list available tools from Composio
const tools = await composioClient.getTools({
apps: ['mapbox']
});
Copy link

Choose a reason for hiding this comment

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

The test script checks env vars (COMPOSIO_*, MAPBOX_ACCESS_TOKEN) but then calls initializeComposioMapbox() which currently uses module-level constants with placeholder fallbacks and ignores the local authConfigId/userId/mapboxToken variables.

So the upfront env validation in this script may not actually guarantee the values used for authentication are the ones validated here.

Suggestion

Thread the validated env vars into initializeComposioMapbox() (or into authenticateToolkit) so the script validates the same values it uses.

For example:

const { connectionId } = await initializeComposioMapbox({
  userId,
  authConfigId,
  mapboxToken,
});

…and update initializeComposioMapbox accordingly.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

Comment on lines 1 to 11
# Composio Mapbox Integration
# Replace with your actual Composio auth config ID and user ID
COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_MAPBOX_CONFIG_ID"
COMPOSIO_USER_ID="user@example.com"

# Mapbox Access Token
MAPBOX_ACCESS_TOKEN="your_mapbox_api_key"

# For client-side usage (if needed)
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID="ac_YOUR_MAPBOX_CONFIG_ID"
NEXT_PUBLIC_COMPOSIO_USER_ID="user@example.com"
Copy link

Choose a reason for hiding this comment

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

.env.local.example and docs introduce NEXT_PUBLIC_COMPOSIO_* values. If COMPOSIO_USER_ID represents an email/identifier, exposing it client-side may be unnecessary and increases the chance of coupling client identity to a backend concept.

Also, if the intended design is server-side Composio auth (recommended), the NEXT_PUBLIC_* variables should likely be removed to prevent accidental secret/identifier exposure.

Suggestion

Remove NEXT_PUBLIC_COMPOSIO_USER_ID (and potentially NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID) unless the browser truly needs them.

If you do need a client identifier, consider a non-sensitive opaque user handle (not an email) and keep auth config IDs server-side.

Reply with "@CharlieHelps yes please" if you'd like me to add a commit with this suggestion.

@charliecreates charliecreates bot removed the request for review from CharlieHelps January 4, 2026 09:58
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
package.json (1)

89-89: Optional: Remove empty line for cleaner formatting.

This empty line was previously flagged and can be removed to improve consistency.

🔎 Proposed fix
     "remark-math": "^6.0.0",
-
     "sonner": "^1.7.4",
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf9024c and 3e65c6f.

📒 Files selected for processing (1)
  • package.json

Security fixes:
- Remove hardcoded fallback values in composio-mapbox.ts
- Add proper environment variable validation with fail-fast behavior
- Add security warnings in hooks.ts and README about server-side only usage
- Document that MAPBOX_ACCESS_TOKEN should never be exposed to client

Functionality fixes:
- Update system prompt in hooks.ts to use correct Composio action names (mapbox_* prefix)
- Add proper disconnect cleanup logic
- Fix environment variable validation in index.ts to match actual usage
- Add dynamic import to avoid bundling server-side code in client

Code quality improvements:
- Stabilize all callbacks with proper dependency arrays
- Remove quotes from environment variables in .env.local.example
- Remove empty line in package.json (line 89)
- Add comprehensive security best practices section to README
- Add server-side API route example in README

All TypeScript files now follow best practices with proper error handling,
type safety, and clear separation between client and server code.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (7)
mapbox_mcp/README.md (2)

28-39: Add COMPOSIO_API_KEY to environment variables documentation.

The @composio/core SDK requires COMPOSIO_API_KEY for authentication (as confirmed in past review research). This critical variable is missing from the documentation, which will cause initialization failures.

Additionally, documenting NEXT_PUBLIC_COMPOSIO_* variables contradicts the security warnings (lines 11-15) that emphasize server-side-only usage. If Composio initialization happens exclusively server-side in composio-mapbox.ts, these client-side variables are unnecessary and should be removed to prevent accidental exposure.

🔎 Proposed fix
 ## Environment Variables
 
 Set the following environment variables in your `.env.local` file:
 
 ```bash
 # Composio Configuration (Server-side only)
+COMPOSIO_API_KEY=your_composio_api_key_here
 COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
 COMPOSIO_USER_ID=user@example.com
 
 # Mapbox Access Token (Server-side only - DO NOT expose to client)
 MAPBOX_ACCESS_TOKEN=your_mapbox_api_key
-
-# For client-side usage (if needed for display purposes only)
-NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
-NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com

</details>

Based on learnings from past reviews.

---

`45-63`: **Add setup step for obtaining Composio API key and fix markdown formatting.**

The setup instructions omit the critical step of obtaining a `COMPOSIO_API_KEY` before creating the Mapbox auth config. Users need this key to authenticate SDK calls.

Additionally, static analysis flagged markdown formatting issues: trailing space (line 11), bare URLs should be wrapped in angle brackets (lines 51, 57), and fenced code blocks need surrounding blank lines (lines 46, 61).




<details>
<summary>🔎 Proposed fix</summary>

```diff
 ## Setup
 
 1. **Install Composio SDK**:
+
    ```bash
    bun install @composio/core
    ```
 
-2. **Create Mapbox Auth Config in Composio**:
-   - Sign up for a Composio account at https://composio.dev
+2. **Get Composio API Key**:
+   - Sign up for a Composio account at <https://composio.dev>
+   - Navigate to Settings > API Keys
+   - Generate a new API key and save it as `COMPOSIO_API_KEY` in `.env.local`
+
+3. **Create Mapbox Auth Config in Composio**:
    - Create an auth config for Mapbox with API Key authentication
    - Note the auth config ID (starts with `ac_`)
 
-3. **Set Environment Variables**:
+4. **Set Environment Variables**:
    - Copy the values from your Composio dashboard
-   - Add your Mapbox access token from https://account.mapbox.com
+   - Add your Mapbox access token from <https://account.mapbox.com>
    - **Never commit `.env.local` to version control**
 
-4. **Test the Connection**:
+5. **Test the Connection**:
+
    ```bash
    bun run mapbox_mcp/index.ts
    ```

Also, remove the trailing space on line 11.

Based on learnings from past reviews and static analysis hints.

mapbox_mcp/index.ts (1)

4-4: Replace any type with proper Composio type.

Using any for composioClient loses type safety and defeats TypeScript's compile-time checks. Import the Composio type from @composio/core and use it here.

🔎 Proposed fix
-import { getComposioClient, initializeComposioMapbox } from './composio-mapbox';
+import { Composio } from '@composio/core';
+import { getComposioClient, initializeComposioMapbox } from './composio-mapbox';
 
 async function testComposioConnection() {
-  let composioClient: any;
+  let composioClient: Composio | undefined;

Based on learnings from past reviews.

mapbox_mcp/hooks.ts (4)

45-47: Warning is insufficient—architectural security issue remains.

While the warning comment is helpful, the fundamental problem persists: this hook can still be imported and called from client components, which would expose MAPBOX_ACCESS_TOKEN (via the dynamic import of ./composio-mapbox). As noted in past reviews, authentication and connected-account creation should happen server-side only.

Consider one of these approaches:

  • Move the hook entirely to a server-only module (e.g., hooks.server.ts) and provide a separate client hook that calls an API route.
  • Or, split responsibilities: create a server action/API route for connect() and initializeComposioMapbox(), and have the client hook fetch the resulting connectionId from that endpoint.
🔎 Example: Server-side API route approach

Server route (app/api/composio/mapbox/connect/route.ts):

import { initializeComposioMapbox } from '@/mapbox_mcp/composio-mapbox';

export async function POST() {
  const { connectionId } = await initializeComposioMapbox();
  return Response.json({ connectionId });
}

Client hook (updated connect function):

 const connect = useCallback(async () => {
   try {
     setIsLoading(true);
     setError(null);
     
-    // Import server-side function
-    const { initializeComposioMapbox } = await import('./composio-mapbox');
-    const { connectionId: connId, connectedAccount } = await initializeComposioMapbox();
+    // Call server-side API route
+    const res = await fetch('/api/composio/mapbox/connect', { method: 'POST' });
+    const { connectionId: connId } = await res.json();
     setConnectionId(connId);
     
     // Get available tools from Composio
     if (composioClientRef.current) {
       const tools = await composioClientRef.current.getTools({
         apps: ['mapbox']
       });
       toolsRef.current = tools;
     }
     
     setIsConnected(true);
     console.log('✅ Connected to Composio Mapbox');
     console.log('Connection ID:', connId);
   } catch (err) {
     // ... error handling
   }
 }, []);

49-49: Hook name no longer reflects Composio usage.

The hook is still named useMCPMapClient but now uses Composio instead of MCP. Consider renaming to useComposioMapClient for clarity, and export a deprecated alias for backward compatibility:

export const useComposioMapClient = () => { /* ... */ };
/** @deprecated Use useComposioMapClient instead */
export const useMCPMapClient = useComposioMapClient;

106-121: Missing cleanup: disconnect() does not revoke the Composio connection.

Past reviews confirmed that the Composio SDK provides composio.connectedAccounts.delete(connectionId) to revoke credentials and clean up the connection. The comment at lines 110-112 is outdated—the SDK does provide this method.

Without calling delete(), the backend connection persists with active credentials, and repeated connect/disconnect cycles will leak connected accounts in Composio.

🔎 Proposed fix
 const disconnect = useCallback(async () => {
   try {
-    // Clean up Composio connection if it exists
     if (composioClientRef.current && connectionId) {
-      // Note: Composio SDK may not have a direct disconnect method for connected accounts
-      // This is a placeholder for proper cleanup if the SDK provides it
-      console.log('Disconnecting from Composio...');
+      await composioClientRef.current.connectedAccounts.delete(connectionId);
+      console.log('Disconnected and revoked Composio connection');
     }
     
     toolsRef.current = null;
     setIsConnected(false);
     setConnectionId(null);
   } catch (err) {
     console.error('Error during disconnect:', err);
   }
 }, [connectionId]);

59-72: Potential race: composioClientRef may be null when disconnect() or tool methods are called.

The useEffect initializes composioClientRef.current asynchronously. If a consumer calls disconnect(), geocodeLocation(), calculateDistance(), or searchNearbyPlaces() before the effect completes, composioClientRef.current will be null and those functions will fail (lines 109, 193, 219, 248).

While connect() re-imports the client dynamically, the other methods rely on the ref populated by this effect.

🔎 Proposed fix: Initialize synchronously

Since getComposioClient() returns a singleton, you can initialize the ref synchronously:

-  // Refs to hold available tools and Composio client
   const toolsRef = useRef<any>(null);
-  const composioClientRef = useRef<any>(null);
-
-  // Initialize Composio client on mount
-  useEffect(() => {
-    // Import dynamically to avoid bundling server-side code in client
-    const initClient = async () => {
-      try {
-        const { getComposioClient } = await import('./composio-mapbox');
-        composioClientRef.current = getComposioClient();
-      } catch (err) {
-        console.error('Failed to initialize Composio client:', err);
-        setError('Failed to initialize Composio client. This may be due to missing environment variables.');
-      }
-    };
-    initClient();
-  }, []);
+  // Initialize Composio client synchronously (only import once at module level if needed)
+  const composioClientRef = useRef<any>(() => {
+    // This still requires addressing the server-side secret issue
+    const { getComposioClient } = require('./composio-mapbox');
+    return getComposioClient();
+  });

Note: This still exposes server secrets client-side. The proper fix is to move initialization server-side (see previous comment).

📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3e65c6f and 0602e75.

📒 Files selected for processing (6)
  • .env.local.example
  • mapbox_mcp/README.md
  • mapbox_mcp/composio-mapbox.ts
  • mapbox_mcp/hooks.ts
  • mapbox_mcp/index.ts
  • package.json
🧰 Additional context used
🧬 Code graph analysis (2)
mapbox_mcp/index.ts (2)
mapbox_mcp/composio-mapbox.ts (2)
  • initializeComposioMapbox (84-100)
  • getComposioClient (105-107)
lib/agents/tools/geospatial.tsx (1)
  • getConnectedMcpClient (36-129)
mapbox_mcp/hooks.ts (2)
mapbox_mcp/composio-mapbox.ts (2)
  • getComposioClient (105-107)
  • initializeComposioMapbox (84-100)
lib/agents/tools/geospatial.tsx (1)
  • getConnectedMcpClient (36-129)
🪛 dotenv-linter (4.0.0)
.env.local.example

[warning] 23-23: [UnorderedKey] The NEXT_PUBLIC_SUPABASE_ANON_KEY key should go before the NEXT_PUBLIC_SUPABASE_URL key

(UnorderedKey)


[warning] 25-25: [UnorderedKey] The DATABASE_URL key should go before the NEXT_PUBLIC_SUPABASE_ANON_KEY key

(UnorderedKey)

🪛 markdownlint-cli2 (0.18.1)
mapbox_mcp/README.md

11-11: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)


46-46: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


51-51: Bare URL used

(MD034, no-bare-urls)


57-57: Bare URL used

(MD034, no-bare-urls)


61-61: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🔇 Additional comments (3)
mapbox_mcp/composio-mapbox.ts (2)

41-41: Consider multi-user implications of module-level singleton.

The module-level composio singleton and validateEnvironmentVariables() read COMPOSIO_USER_ID once at startup. In a multi-user scenario, all requests would share the same connected account, which could lead to:

  • Permission issues (all users share one set of credentials)
  • Data isolation problems (one user's API usage attributed to another)
  • Incorrect audit trails

If COMPOSIO_USER_ID represents the application (single-tenant) rather than end-users, this design is acceptable. However, if this integration will serve multiple authenticated users, consider accepting userId as a parameter to initializeComposioMapbox() and managing per-user connections.

Could you clarify the intended user model? If this is multi-user, we should refactor to support per-user authentication. If single-tenant, this concern can be disregarded.

Based on learnings from past reviews.


8-39: Excellent fail-fast environment validation.

The validateEnvironmentVariables function provides clear, actionable error messages and prevents the application from starting with missing configuration. This is a significant improvement over the previous placeholder fallback approach.

mapbox_mcp/index.ts (1)

3-52: Well-structured test implementation.

The test function correctly uses the new Composio-based flow with proper error handling, connection verification, tool discovery, and a sample action call. The integration with initializeComposioMapbox() ensures environment variables are validated before proceeding.

Comment on lines 1 to 11
# Composio Mapbox Integration
# Replace with your actual Composio auth config ID and user ID
COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
COMPOSIO_USER_ID=user@example.com

# Mapbox Access Token
MAPBOX_ACCESS_TOKEN=your_mapbox_api_key

# For client-side usage (if needed)
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add COMPOSIO_API_KEY and reconsider client-side variable exposure.

Past review investigations confirmed that the @composio/core SDK expects a COMPOSIO_API_KEY environment variable for authentication. This critical variable is missing from the example configuration.

Additionally, NEXT_PUBLIC_COMPOSIO_USER_ID and NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID expose server-side authentication identifiers to the client. Since the README emphasizes server-side-only usage and the composio-mapbox.ts module initializes Composio server-side, these client-side variables appear unnecessary and increase the risk of accidental exposure.

🔎 Proposed fix
 # Composio Mapbox Integration
-# Replace with your actual Composio auth config ID and user ID
+# Get your Composio API key from https://app.composio.dev/settings/api-keys
+COMPOSIO_API_KEY=your_composio_api_key_here
+
+# Replace with your actual Composio auth config ID and user ID
 COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
 COMPOSIO_USER_ID=user@example.com
 
 # Mapbox Access Token
 MAPBOX_ACCESS_TOKEN=your_mapbox_api_key
-
-# For client-side usage (if needed)
-NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
-NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com

Based on learnings from past reviews.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Composio Mapbox Integration
# Replace with your actual Composio auth config ID and user ID
COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
COMPOSIO_USER_ID=user@example.com
# Mapbox Access Token
MAPBOX_ACCESS_TOKEN=your_mapbox_api_key
# For client-side usage (if needed)
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com
# Composio Mapbox Integration
# Get your Composio API key from https://app.composio.dev/settings/api-keys
COMPOSIO_API_KEY=your_composio_api_key_here
# Replace with your actual Composio auth config ID and user ID
COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
COMPOSIO_USER_ID=user@example.com
# Mapbox Access Token
MAPBOX_ACCESS_TOKEN=your_mapbox_api_key
🤖 Prompt for AI Agents
In .env.local.example around lines 1 to 11, the example is missing
COMPOSIO_API_KEY and unnecessarily exposes server-side IDs via NEXT_PUBLIC_
variables; add a COMPOSIO_API_KEY=your_composio_api_key entry near the other
server-side settings and remove (or comment out)
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID and NEXT_PUBLIC_COMPOSIO_USER_ID to
avoid client-side exposure, keeping only server-side environment variables and a
short inline comment that these keys must remain server-only.

Critical fixes:
- Add COMPOSIO_API_KEY to environment variable validation in composio-mapbox.ts
- Update validateEnvironmentVariables() to include apiKey in return type
- Pass COMPOSIO_API_KEY to Composio() constructor for SDK authentication
- Update getComposioClient() to validate and use COMPOSIO_API_KEY

Remove stale Smithery imports:
- Remove 'import { createSmitheryUrl } from @smithery/sdk' from geospatial.tsx
- Replace Smithery URL construction with direct Composio URL building
- Update environment variables from SMITHERY_* to COMPOSIO_*
- Replace NEXT_PUBLIC_SMITHERY_API_KEY with NEXT_PUBLIC_COMPOSIO_API_KEY
- Replace NEXT_PUBLIC_SMITHERY_PROFILE_ID with NEXT_PUBLIC_COMPOSIO_USER_ID

Environment variable updates:
- Add COMPOSIO_API_KEY to .env.local.example
- Add NEXT_PUBLIC_COMPOSIO_API_KEY to .env.local.example
- Document all required Composio environment variables

This fixes runtime errors caused by missing @smithery/sdk dependency
and ensures proper Composio SDK authentication.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/agents/tools/geospatial.tsx (2)

54-68: Simplify redundant nested try/catch.

The inner try/catch (lines 57-63) catches and immediately rethrows the same error, adding no value. The outer catch handles it anyway.

🔎 Proposed simplification
   try {
     // Use static import for config
-    let mapboxMcpConfig;
-    try {
-      mapboxMcpConfig = require('../../../mapbox_mcp_config.json');
-      config = { ...mapboxMcpConfig, mapboxAccessToken };
-      console.log('[GeospatialTool] Config loaded successfully');
-    } catch (configError: any) {
-      throw configError;
-    }
+    const mapboxMcpConfig = require('../../../mapbox_mcp_config.json');
+    config = { ...mapboxMcpConfig, mapboxAccessToken };
+    console.log('[GeospatialTool] Config loaded successfully');
   } catch (configError: any) {
     console.error('[GeospatialTool] Failed to load mapbox config:', configError.message);
     config = { mapboxAccessToken, version: '1.0.0', name: 'mapbox-mcp-server' };
     console.log('[GeospatialTool] Using fallback config');
   }

257-265: Add explicit handling for unrecognized query types.

The switch statement has no default case. If queryType doesn't match any case, toolName is undefined, and the fallback to 'unknown_tool' (line 288) will cause the MCP call to fail with an unclear error.

🔎 Proposed fix
         switch (queryType) {
           case 'directions': return prefer('directions_tool') 
           case 'distance': return prefer('matrix_tool');
           case 'search': return prefer( 'isochrone_tool','category_search_tool') || 'poi_search_tool';
           case 'map': return prefer('static_map_image_tool') 
           case 'reverse': return prefer('reverse_geocode_tool');
           case 'geocode': return prefer('forward_geocode_tool');
+          default: 
+            console.warn(`[GeospatialTool] Unknown queryType: ${queryType}`);
+            return undefined;
         }
📜 Review details

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0602e75 and a460272.

📒 Files selected for processing (3)
  • .env.local.example
  • lib/agents/tools/geospatial.tsx
  • mapbox_mcp/composio-mapbox.ts
🧰 Additional context used
🧬 Code graph analysis (1)
mapbox_mcp/composio-mapbox.ts (3)
mapbox_mcp/hooks.ts (1)
  • mcp (66-82)
mapbox_mcp/index.ts (1)
  • testMCPConnection (14-89)
components/map/map-query-handler.tsx (1)
  • GeospatialToolOutput (18-23)
🪛 dotenv-linter (4.0.0)
.env.local.example

[warning] 25-25: [UnorderedKey] The NEXT_PUBLIC_SUPABASE_ANON_KEY key should go before the NEXT_PUBLIC_SUPABASE_URL key

(UnorderedKey)


[warning] 27-27: [UnorderedKey] The DATABASE_URL key should go before the NEXT_PUBLIC_SUPABASE_ANON_KEY key

(UnorderedKey)

🔇 Additional comments (5)
lib/agents/tools/geospatial.tsx (1)

36-50: Approve validation and environment checks.

The environment variable validation correctly checks for both presence and non-empty values. The logging properly masks sensitive values by showing only the first 8 characters.

mapbox_mcp/composio-mapbox.ts (4)

8-48: LGTM: Environment validation is thorough and fail-fast.

The function validates all four required environment variables (COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID, MAPBOX_ACCESS_TOKEN, COMPOSIO_API_KEY) with clear error messages. No placeholder fallbacks remain, addressing previous security concerns.


59-89: Implementation looks correct; minor PII consideration.

The function properly validates all inputs before use and correctly initializes the Composio SDK. The logging on line 85 includes userId, which per the .env.local.example could be an email address. Since this is server-side only, it's acceptable, but consider whether logging user identifiers aligns with your data handling policies.


121-132: LGTM: Simple factory with proper validation.

The function correctly validates the API key before instantiation and provides a clear error message if missing.


1-2: Verify @composio/core v0.5.0 API compatibility for AuthScheme.APIKey() method.

The code calls AuthScheme.APIKey({ api_key: ... }) on line 78, but current public documentation for Composio SDK shows authentication configured via AuthSchemeTypes.API_KEY enum with credentials: { apiKey: ... } (camelCase). This API pattern and parameter naming difference cannot be verified against v0.5.0 documentation, which is not publicly available. Confirm with the SDK maintainers or v0.5.0 release notes that this method signature and parameter names are correct for the specified version.

Comment on lines +10 to +13
# For client-side usage (if needed)
NEXT_PUBLIC_COMPOSIO_API_KEY=your_composio_api_key
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 4, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Critical security risk: Remove NEXT_PUBLIC_COMPOSIO_API_KEY — API keys must never be exposed client-side.

Exposing COMPOSIO_API_KEY via a NEXT_PUBLIC_ prefix makes it accessible in browser bundles, allowing anyone to extract and misuse your API key. The README and composio-mapbox.ts both emphasize server-side-only usage.

If client-side code needs to interact with Composio, implement a server-side API route that proxies requests without exposing credentials.

🔎 Proposed fix
-# For client-side usage (if needed)
-NEXT_PUBLIC_COMPOSIO_API_KEY=your_composio_api_key
-NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
-NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com
+# Note: Composio credentials should remain server-side only.
+# If client-side access is needed, use a server-side API route to proxy requests.
🤖 Prompt for AI Agents
In .env.local.example around lines 10-13, the example exposes
NEXT_PUBLIC_COMPOSIO_API_KEY (client-side) which is a critical security risk;
remove the NEXT_PUBLIC_COMPOSIO_API_KEY entry and replace it with a server-only
variable name (e.g., COMPOSIO_API_KEY) in the example, add a short comment that
this key must be kept server-side only, and update the example/README to
instruct developers to create a server-side API route that proxies calls to
Composio using the server-only COMPOSIO_API_KEY (ensure composio-mapbox.ts and
any other code reference the server env var, not a NEXT_PUBLIC_* variable).

Comment on lines 74 to +82
try {
serverUrlToUse = createSmitheryUrl(mcpServerBaseUrl, smitheryUrlOptions);
// Construct URL with Composio credentials
const baseUrl = 'https://api.composio.dev/v1/mcp/mapbox';
serverUrlToUse = new URL(baseUrl);
serverUrlToUse.searchParams.set('api_key', composioApiKey);
serverUrlToUse.searchParams.set('user_id', composioUserId);

const urlDisplay = serverUrlToUse.toString().split('?')[0];
console.log('[GeospatialTool] MCP Server URL created:', urlDisplay);
console.log('[GeospatialTool] Composio MCP Server URL created:', urlDisplay);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the actual file to confirm the code structure
head -n 100 lib/agents/tools/geospatial.tsx | cat -n

Repository: QueueLab/QCX

Length of output: 4459


🏁 Script executed:

# Search for the TODO comment mentioned in the review
rg "TODO|Smithery" lib/agents/tools/geospatial.tsx -n -B 2 -A 2

Repository: QueueLab/QCX

Length of output: 570


🏁 Script executed:

# Check the environment variables being used
rg "NEXT_PUBLIC|composioApiKey|composioUserId" lib/agents/tools/geospatial.tsx -n

Repository: QueueLab/QCX

Length of output: 739


🌐 Web query:

Composio MCP server API authentication best practices security

💡 Result:

Below are concise best-practice recommendations for authenticating and securing a Composio / MCP server API, with source citations.

Key recommendations

  • Require TLS (HTTPS) for all MCP endpoints and SSE connections. (docs.composio.dev)
  • Use strong, least-privilege credentials: long random API keys or short-lived tokens scoped to only required tools/actions. Rotate and revoke keys regularly. (mcp-cloud.ai)
  • Store secrets in a secrets manager or environment variables (do not hardcode keys in source or client-side code). (mcp-cloud.ai)
  • Prefer short-lived access tokens (with refresh tokens where needed) over long-lived static keys for user-facing flows; enforce sensible expirations for server-to-server tokens. (mcp-cloud.ai)
  • Protect both HTTP endpoints and SSE (stream) endpoints with authentication and enable auth on SSE in production. (mcp-framework.com)
  • Enforce fine-grained auth: create separate auth configurations per MCP server/instance and expose only required toolkits and scopes. (v3.docs.composio.dev)
  • Use mTLS or OAuth2 for higher-security integrations where possible (server-to-server or enterprise deployments). (mcp-framework.com)
  • Implement rate limiting, monitoring and alerting for failed auth attempts, and audit logging for key usage and token issuance/revocation. (mcp-cloud.ai)
  • Validate and sanitize client-supplied data and implement strict timeouts on connections to reduce abuse and resource exhaustion. (mcp-cloud.ai)

Practical operational steps

  • Use a secrets manager (AWS/GCP/Azure/HashiCorp) for production keys and rotate them on a schedule. (mcp-cloud.ai)
  • Limit MCP server allowed_tools and auth_config_ids to the minimum set required per instance. (v3.docs.composio.dev)
  • Log and review authentication failures; alert on unusual patterns and automatically revoke keys that appear compromised. (mcp-cloud.ai)

If you want, I can produce a checklist or example configuration (OAuth2, JWT, or API-key) tailored to your deployment (self-hosted vs Composio-managed) — tell me which environment you’re using.

Citations:


Security risk: API key exposed in URL query parameters.

Passing api_key as a URL query parameter (line 78) exposes credentials in server access logs, browser history, and HTTP referrer headers, violating MCP/Composio authentication best practices which explicitly recommend against passing sensitive data in URLs.

Additionally, using NEXT_PUBLIC_ environment variables for this server-side code (geospatial.tsx uses React Server Components) unnecessarily exposes these credentials to the client bundle.

The TODO comment on lines 71-72 correctly identifies the need to migrate to the Composio SDK directly. Prioritize this migration or implement a server-side proxy endpoint that uses secure authentication headers (e.g., Bearer tokens) instead of query parameters.

🤖 Prompt for AI Agents
In lib/agents/tools/geospatial.tsx around lines 74 to 82, the code currently
injects the Composio api_key into the URL query string which exposes
credentials; instead, stop adding sensitive keys to the URL and move to a secure
server-side call: either use the Composio SDK on the server or call an internal
server-side proxy endpoint that reads a non-public environment variable (remove
NEXT_PUBLIC_ prefix and store composioApiKey/composioUserId in server-only envs)
and forwards requests with the API key in an Authorization header (e.g., Bearer
<key>) or in request body as per SDK requirements; ensure any console logs do
not print secrets and that this file runs only server-side (no client bundling)
so the credentials are never exposed to browser or logs.

Comment on lines +96 to +115
export async function initializeComposioMapbox() {
const { authConfigId, userId, mapboxToken, apiKey } = validateEnvironmentVariables();

try {
// Authenticate the toolkit
const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken, apiKey);

// Initialize Composio client with API key for subsequent operations
const composio = new Composio({ apiKey });

// Verify the connection
const connectedAccount = await composio.connectedAccounts.get(connectionId);
console.log("Connected account:", connectedAccount);

return { connectionId, connectedAccount, composio };
} catch (error) {
console.error("Failed to initialize Composio Mapbox connection:", error);
throw error;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider returning the Composio instance from authenticateToolkit to avoid redundant instantiation.

authenticateToolkit (line 72) and initializeComposioMapbox (line 104) both create separate Composio instances with the same API key. While this works, returning the instance from authenticateToolkit would reduce redundancy.

🔎 Proposed refactor
 export async function authenticateToolkit(
   userId: string,
   authConfigId: string,
   mapboxApiKey: string,
   composioApiKey: string
-): Promise<string> {
+): Promise<{ connectionId: string; composio: Composio }> {
   // ... validation ...
   
   const composio = new Composio({ apiKey: composioApiKey });
   const connectionRequest = await composio.connectedAccounts.initiate(/* ... */);
   
-  return connectionRequest.id;
+  return { connectionId: connectionRequest.id, composio };
 }

 export async function initializeComposioMapbox() {
   const { authConfigId, userId, mapboxToken, apiKey } = validateEnvironmentVariables();

   try {
-    const connectionId = await authenticateToolkit(userId, authConfigId, mapboxToken, apiKey);
-    const composio = new Composio({ apiKey });
+    const { connectionId, composio } = await authenticateToolkit(userId, authConfigId, mapboxToken, apiKey);
     
     const connectedAccount = await composio.connectedAccounts.get(connectionId);
     // ...
   }
 }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In mapbox_mcp/composio-mapbox.ts around lines 96 to 115 (and note
authenticateToolkit at ~72), the code creates two Composio instances: one in
authenticateToolkit and another in initializeComposioMapbox; change
authenticateToolkit to return both the connectionId and the instantiated
Composio client (e.g., { connectionId, composio }) instead of only connectionId,
update initializeComposioMapbox to use the returned composio instance rather
than creating a new one, and adjust types/signatures and any callers
accordingly; preserve existing error handling and ensure the returned object
from initializeComposioMapbox contains connectionId, connectedAccount, and the
reused composio instance.

@ngoiyaeric
Copy link
Collaborator Author

@coderabbitai integrated as a tool or as an MCP

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the Composio integration files to understand the architecture
echo "=== composio-mapbox.ts ==="
cat mapbox_mcp/composio-mapbox.ts
echo -e "\n=== hooks.ts (key sections) ==="
cat mapbox_mcp/hooks.ts | head -100
echo -e "\n=== index.ts ==="
cat mapbox_mcp/index.ts

Length of output: 9328


@ngoiyaeric The Mapbox integration is now implemented as a Tool via Composio, not as an MCP.

Here's the architecture breakdown:

Current Implementation (Post-Migration)

Tool-based via Composio:

  • Uses Composio SDK (@composio/core) as a tool orchestration platform
  • Mapbox actions are exposed as executable tools through Composio's action API:
    • mapbox_geocode_location
    • mapbox_calculate_distance
    • mapbox_search_nearby_places
    • mapbox_generate_map_link
  • Tools are invoked via composioClient.executeAction() calls
  • Authentication is handled through Composio's connected accounts system

Code Evidence

// From index.ts - Getting tools from Composio
const tools = await composioClient.getTools({
  apps: ['mapbox']
});

// From hooks.ts - Executing actions as tools
const geocodeResult = await composioClientRef.current.executeAction({
  action: 'mapbox_geocode_location',
  params: { query: location, includeMapPreview: true },
  connectedAccountId: connectionId,
});

Note on Directory Naming

The directory is still named mapbox_mcp/ which is legacy naming from the previous MCP-based implementation. The PR migrated away from the Model Context Protocol (MCP) to Composio's tool execution framework, but the directory wasn't renamed to avoid breaking imports.

@ngoiyaeric
Copy link
Collaborator Author

@coderabbitai what env variables for composio are needed

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the .env.local.example file to get all Composio environment variables
echo "=== .env.local.example ==="
cat .env.local.example

echo -e "\n\n=== README.md Environment Variables Section ==="
cat mapbox_mcp/README.md | grep -A 50 "Environment Variables"

Length of output: 3537


@ngoiyaeric Here are all the Composio environment variables needed for the Mapbox integration:

Required Server-Side Variables

These must be set in your .env.local file:

# Composio API Key (from composio.dev dashboard)
COMPOSIO_API_KEY=your_composio_api_key

# Composio Mapbox Auth Config ID (starts with 'ac_')
COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID

# Composio User ID (your email or user identifier)
COMPOSIO_USER_ID=user@example.com

# Mapbox Access Token (from mapbox.com)
MAPBOX_ACCESS_TOKEN=your_mapbox_api_key

⚠️ All four variables are required - the application will fail with clear error messages if any are missing.

Optional Client-Side Variables

Only add these if you need client-side access (not recommended for security):

# Client-side Composio variables (use with caution)
NEXT_PUBLIC_COMPOSIO_API_KEY=your_composio_api_key
NEXT_PUBLIC_COMPOSIO_MAPBOX_AUTH_CONFIG_ID=ac_YOUR_MAPBOX_CONFIG_ID
NEXT_PUBLIC_COMPOSIO_USER_ID=user@example.com

How to Get These Values

  1. COMPOSIO_API_KEY:

  2. COMPOSIO_MAPBOX_AUTH_CONFIG_ID:

    • In Composio dashboard, create an auth config for Mapbox
    • Use API Key authentication method
    • Copy the config ID (starts with ac_)
  3. COMPOSIO_USER_ID:

    • Your email or user identifier used in Composio
  4. MAPBOX_ACCESS_TOKEN:

Security Best Practices

  • ✅ Keep server-side variables in .env.local (never commit this file)
  • ✅ Use server-side API routes for Mapbox operations (as shown in README.md)
  • ❌ Avoid using NEXT_PUBLIC_ prefixed variables unless absolutely necessary
  • ❌ Never expose API keys to client-side code

The README.md recommends using server-side API routes instead of client-side direct access for better security.

@ngoiyaeric ngoiyaeric merged commit 68befad into main Jan 5, 2026
5 checks passed
@coderabbitai coderabbitai bot mentioned this pull request Feb 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant