From 090bfd7fd5d3e4246334e93d746a7cfe406e284f Mon Sep 17 00:00:00 2001 From: ngoiyaeric <115367894+ngoiyaeric@users.noreply.github.com> Date: Sat, 3 Jan 2026 07:58:31 -0500 Subject: [PATCH] Revert "Replace Smithery with Composio for Mapbox integration" This reverts commit 9479f0aa0aaf8e5e050030e2a9eaef9833266951. --- .env.local.example | 15 +- COMPOSIO_MIGRATION.md | 253 ---------------------------------- mapbox_mcp/README.md | 128 ----------------- mapbox_mcp/composio-mapbox.ts | 63 --------- mapbox_mcp/hooks.ts | 143 +++++++++---------- mapbox_mcp/index.ts | 110 +++++++++------ mapbox_mcp_config.json | 18 ++- package.json | 5 +- 8 files changed, 153 insertions(+), 582 deletions(-) delete mode 100644 COMPOSIO_MIGRATION.md delete mode 100644 mapbox_mcp/README.md delete mode 100644 mapbox_mcp/composio-mapbox.ts diff --git a/.env.local.example b/.env.local.example index 58e87235..928ed6f6 100644 --- a/.env.local.example +++ b/.env.local.example @@ -1,14 +1,7 @@ -# 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" +# Mapbox MCP Server Credentials +# Replace with your actual Smithery profile ID and API key +SMITHERY_PROFILE_ID="your_smithery_profile_id_here" +SMITHERY_API_KEY="your_smithery_api_key_here" # NEXT_PUBLIC_MAPBOX_ACCESS_TOKEN is already used by mapbox-map.tsx # Ensure it's also in your .env.local file if you haven't set it up yet. diff --git a/COMPOSIO_MIGRATION.md b/COMPOSIO_MIGRATION.md deleted file mode 100644 index 6c8f7e53..00000000 --- a/COMPOSIO_MIGRATION.md +++ /dev/null @@ -1,253 +0,0 @@ -# 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/ -``` - -However, we recommend staying with Composio for the improved features and maintainability. diff --git a/mapbox_mcp/README.md b/mapbox_mcp/README.md deleted file mode 100644 index 791d7ed4..00000000 --- a/mapbox_mcp/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# Mapbox Integration with Composio - -This directory contains the Composio-based Mapbox integration for QCX, replacing the previous Smithery implementation. - -## Overview - -The integration uses [Composio](https://composio.dev) to manage authentication and tool execution for Mapbox services. This provides a more robust and scalable approach to integrating external services. - -## Files - -- **composio-mapbox.ts**: Core Composio client setup and authentication logic -- **hooks.ts**: React hooks for using Mapbox functionality in components -- **index.ts**: Test script for verifying the Composio connection -- **README.md**: This file - -## Environment Variables - -Set the following environment variables in your `.env.local` file: - -```bash -# Composio Configuration -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 -``` - -## 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 - - 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 - ``` - -## Usage - -### In React Components - -```typescript -import { useMCPMapClient } from '@/mapbox_mcp/hooks'; - -function MyComponent() { - const { - isConnected, - isLoading, - error, - connect, - geocodeLocation - } = useMCPMapClient(); - - useEffect(() => { - connect(); - }, [connect]); - - const handleGeocode = async () => { - try { - const result = await geocodeLocation('Eiffel Tower'); - console.log(result); - } catch (err) { - console.error('Geocoding failed:', err); - } - }; - - return ( -
- {isConnected ? 'Connected' : 'Disconnected'} - -
- ); -} -``` - -### Available Functions - -- **connect()**: Initialize connection to Composio Mapbox -- **disconnect()**: Close the connection -- **processLocationQuery(query: string)**: Process natural language location queries -- **geocodeLocation(address: string)**: Convert address to coordinates -- **calculateDistance(from: string, to: string, profile: 'driving' | 'walking' | 'cycling')**: Calculate distance between two locations -- **searchNearbyPlaces(location: string, query: string, radius?: number, limit?: number)**: Search for nearby places - -## Migration from Smithery - -The following changes were made to migrate from Smithery to Composio: - -1. **Dependencies**: Replaced `@smithery/cli` and `@smithery/sdk` with `@composio/core` -2. **Authentication**: Changed from Smithery SSE transport to Composio's API Key authentication -3. **Tool Execution**: Updated tool calls to use Composio's `executeAction` method -4. **Configuration**: Replaced `mapbox_mcp_config.json` with Composio-specific configuration - -## Troubleshooting - -### Connection Errors - -- Verify environment variables are set correctly -- Check that your Composio auth config ID is valid -- Ensure your Mapbox access token has the necessary permissions - -### Tool Execution Errors - -- Verify the action names match Composio's Mapbox integration -- Check that the connection ID is valid -- Review Composio logs in the dashboard - -## Resources - -- [Composio Documentation](https://docs.composio.dev) -- [Mapbox API Documentation](https://docs.mapbox.com) -- [QCX Documentation](https://deepwiki.com/QueueLab/QCX) diff --git a/mapbox_mcp/composio-mapbox.ts b/mapbox_mcp/composio-mapbox.ts deleted file mode 100644 index c09aeb47..00000000 --- a/mapbox_mcp/composio-mapbox.ts +++ /dev/null @@ -1,63 +0,0 @@ -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 - -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; -} diff --git a/mapbox_mcp/hooks.ts b/mapbox_mcp/hooks.ts index a9df72b4..06342b3f 100644 --- a/mapbox_mcp/hooks.ts +++ b/mapbox_mcp/hooks.ts @@ -1,6 +1,7 @@ -import { useState, useCallback, useRef, useEffect } from 'react'; +import { useState, useCallback, useRef } from 'react'; import { generateText } from 'ai'; -import { getComposioClient, initializeComposioMapbox } from './composio-mapbox'; +import { useMcp } from 'use-mcp/react'; + // Define Tool type locally if needed type Tool = { @@ -40,62 +41,57 @@ interface PlaceResult { } /** - * Custom React hook to interact with Mapbox via Composio. + * Custom React hook to interact with the Mapbox MCP server. * Manages client connection, tool invocation, and state (loading, error, connection status). - * Uses Composio SDK for authentication and tool execution. + * Uses `useMcp` from 'use-mcp/react' for communication. */ export const useMCPMapClient = () => { const [isConnected, setIsConnected] = useState(false); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); - const [connectionId, setConnectionId] = useState(null); - // Refs to hold available tools and Composio client + // Refs to hold available tools const toolsRef = useRef(null); - const composioClientRef = useRef(null); - // Initialize Composio client on mount - useEffect(() => { - composioClientRef.current = getComposioClient(); - }, []); + // Configure MCP client using useMcp hook + const mcp = useMcp({ + //https://server.smithery.ai/@Waldzell-Agentics/mcp-server/mcp + 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, + }); - // Connect to Composio Mapbox + // Update connection status based on MCP state 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) { - const tools = await composioClientRef.current.getTools({ - apps: ['mapbox'] - }); - toolsRef.current = tools; + 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); } - - 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]); const disconnect = useCallback(async () => { - toolsRef.current = null; - setIsConnected(false); - setConnectionId(null); - }, []); + if (mcp.state === 'ready') { + await mcp.disconnect(); + toolsRef.current = null; + setIsConnected(false); + } + }, [mcp.state]); const processLocationQuery = useCallback(async (query: string) => { - if (!isConnected || !toolsRef.current) { - throw new Error('Composio client not connected'); + if (mcp.state !== 'ready' || !toolsRef.current) { + throw new Error('MCP client not connected'); } setIsLoading(true); setError(null); @@ -158,74 +154,63 @@ Focus on extracting and presenting factual data from the tools.`, } finally { setIsLoading(false); } - }, [isConnected]); + }, [mcp.state, mcp.tools]); const geocodeLocation = useCallback(async (address: string): Promise => { - if (!isConnected || !composioClientRef.current || !connectionId) { - throw new Error('Composio client not connected'); + if (mcp.state !== 'ready') { + throw new Error('MCP client not connected'); } try { - const result = await composioClientRef.current.executeAction({ - action: 'mapbox_geocode_location', - params: { - query: address, - includeMapPreview: true, - }, - connectedAccountId: connectionId, + const result = await mcp.callTool('geocode_location', { + query: address, + includeMapPreview: true, }); - return result.data; + const match = result.content[1]?.text?.match(/```json\n([\s\S]*?)\n```/); + return JSON.parse(match?.[1] || '{}'); } catch (err) { console.error('Geocoding error:', err); setError(`Geocoding error: ${err}`); throw err; } - }, [isConnected, connectionId]); + }, [mcp.state, mcp.callTool]); const calculateDistance = useCallback(async (from: string, to: string, profile: 'driving' | 'walking' | 'cycling' = 'driving'): Promise => { - if (!isConnected || !composioClientRef.current || !connectionId) { - throw new Error('Composio client not connected'); + if (mcp.state !== 'ready') { + throw new Error('MCP client not connected'); } try { - const result = await composioClientRef.current.executeAction({ - action: 'mapbox_calculate_distance', - params: { - from, - to, - profile, - includeRouteMap: true, - }, - connectedAccountId: connectionId, + const result = await mcp.callTool('calculate_distance', { + from, + to, + profile, + includeRouteMap: true, }); - return result.data; + return JSON.parse(result.content[1]?.text?.match(/```json\n(.*?)\n```/s)?.[1] || '{}'); } catch (err) { console.error('Distance calculation error:', err); setError(`Distance calculation error: ${err}`); throw err; } - }, [isConnected, connectionId]); + }, [mcp.state, mcp.callTool]); const searchNearbyPlaces = useCallback(async (location: string, query: string, radius: number = 1000, limit: number = 5): Promise => { - if (!isConnected || !composioClientRef.current || !connectionId) { - throw new Error('Composio client not connected'); + if (mcp.state !== 'ready') { + throw new Error('MCP client not connected'); } try { - const result = await composioClientRef.current.executeAction({ - action: 'mapbox_search_nearby_places', - params: { - location, - query, - radius, - limit, - }, - connectedAccountId: connectionId, + const result = await mcp.callTool('search_nearby_places', { + location, + query, + radius, + limit, }); - return result.data; + return JSON.parse(result.content[1]?.text?.match(/```json\n(.*?)\n```/s)?.[1] || '{}'); } catch (err) { console.error('Places search error:', err); setError(`Places search error: ${err}`); throw err; } - }, [isConnected, connectionId]); + }, [mcp.state, mcp.callTool]); return { isConnected, diff --git a/mapbox_mcp/index.ts b/mapbox_mcp/index.ts index ec7730b2..f11f7577 100644 --- a/mapbox_mcp/index.ts +++ b/mapbox_mcp/index.ts @@ -1,64 +1,92 @@ -import { getComposioClient, initializeComposioMapbox } from './composio-mapbox'; +import type { Tool } from 'use-mcp/react'; +import { useMcp } from 'use-mcp/react'; -// Environment variables required by this script to connect to Composio. -// - COMPOSIO_MAPBOX_AUTH_CONFIG_ID: Your Composio auth config ID for Mapbox. -// - COMPOSIO_USER_ID: Your user ID. -// - MAPBOX_ACCESS_TOKEN: Your Mapbox access token. -const authConfigId = process.env.COMPOSIO_MAPBOX_AUTH_CONFIG_ID; -const userId = process.env.COMPOSIO_USER_ID; -const mapboxToken = process.env.MAPBOX_ACCESS_TOKEN; -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."); +// 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."); return; // Return early if essential credentials are missing. } - let composioClient: any; + // 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. try { - console.log(`Attempting to connect to Composio Mapbox...`); + // 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}...`); - // Initialize the Composio client and authenticate - const { connectionId, connectedAccount } = await initializeComposioMapbox(); - composioClient = getComposioClient(); + // 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', + }); - console.log("✅ Successfully connected to Composio Mapbox."); - console.log("Connection ID:", connectionId); + console.log("✅ Successfully connected to MCP server."); - // Fetch and list available tools from Composio - const tools = await composioClient.getTools({ - apps: ['mapbox'] - }); - console.log("🛠️ Available tools:", tools.map((tool: any) => tool.name)); + // Fetch and list available tools from the server. + const tools = await client.tools(); + console.log("🛠️ Available tools:", tools.map((tool: Tool) => tool.name)); - // Perform a sample tool call if 'mapbox_geocode_location' action is available. - const geocodeAction = tools.find((tool: any) => tool.name === 'mapbox_geocode_location'); - if (geocodeAction) { - console.log("\n📞 Attempting to call 'mapbox_geocode_location' action for 'Eiffel Tower'..."); + // Perform a sample tool call if 'geocode_location' tool is available. + if (tools.some((tool: Tool) => tool.name === 'geocode_location')) { + console.log("\n📞 Attempting to call 'geocode_location' tool for 'Eiffel Tower'..."); + const geocodeParams = { query: "Eiffel Tower", includeMapPreview: true }; try { - const geocodeResult = await composioClient.executeAction({ - action: 'mapbox_geocode_location', - params: { - query: "Eiffel Tower", - includeMapPreview: true - }, - connectedAccountId: connectionId, - }); + const geocodeResult = await client.callTool('geocode_location', geocodeParams); - console.log("🗺️ Geocode Result:", JSON.stringify(geocodeResult.data, null, 2)); + // Parse the structured JSON from the tool result (assumes same server response format). + let resultOutput = geocodeResult; + if (Array.isArray(geocodeResult?.content) && geocodeResult.content.length > 0) { + const lastContentItem = geocodeResult.content[geocodeResult.content.length - 1]; + if (lastContentItem && typeof lastContentItem.text === 'string') { + const jsonMatch = lastContentItem.text.match(/```json\n([\s\S]*?)\n```/); + if (jsonMatch && jsonMatch[1]) { + try { + resultOutput = JSON.parse(jsonMatch[1]); + } catch (parseError) { + console.warn("Could not parse JSON from tool result text block, logging raw text."); + resultOutput = lastContentItem.text; + } + } else { + resultOutput = geocodeResult.content.map((c: any) => c.text).join('\n'); + } + } + } + console.log("🗺️ Geocode Result:", JSON.stringify(resultOutput, null, 2)); } catch (toolError) { - console.error("❌ Error calling 'mapbox_geocode_location':", toolError); + console.error("❌ Error calling 'geocode_location':", toolError); } } else { - console.warn("⚠️ 'mapbox_geocode_location' action not found, skipping sample call."); + console.warn("⚠️ 'geocode_location' tool not found, skipping sample call."); } } catch (error) { - console.error("❌ Composio connection or operation failed:", error); + console.error("❌ MCP connection or operation failed:", error); + } finally { + // Close the client connection if it exists. + if (client) { + console.log("\nClosing MCP client connection..."); + await client.close(); + console.log("🔌 Client connection closed."); + } } } // Run the test connection function. -testComposioConnection(); +testMCPConnection(); diff --git a/mapbox_mcp_config.json b/mapbox_mcp_config.json index deeedf86..180d8491 100644 --- a/mapbox_mcp_config.json +++ b/mapbox_mcp_config.json @@ -1,9 +1,17 @@ { - "composio": { - "mapbox": { - "authConfigId": "ac_YOUR_MAPBOX_CONFIG_ID", - "userId": "user@example.com", - "description": "Composio configuration for Mapbox integration. Set COMPOSIO_MAPBOX_AUTH_CONFIG_ID, COMPOSIO_USER_ID, and MAPBOX_ACCESS_TOKEN environment variables." + "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" + ] } } } diff --git a/package.json b/package.json index b423bc9b..92ccfe4d 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "@radix-ui/react-tabs": "^1.1.9", "@radix-ui/react-toast": "^1.2.11", "@radix-ui/react-tooltip": "^1.2.3", - "@composio/core": "^0.5.0", + "@smithery/cli": "^1.2.5", + "@smithery/sdk": "^1.0.4", "@supabase/ssr": "^0.3.0", "@supabase/supabase-js": "^2.0.0", "@tailwindcss/typography": "^0.5.16", @@ -86,7 +87,7 @@ "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", "remark-math": "^6.0.0", - + "smithery": "^0.5.2", "sonner": "^1.7.4", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7",