-
-
Notifications
You must be signed in to change notification settings - Fork 7
Replace Smithery with Composio for Mapbox integration #397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- 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.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughMigrates 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
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro 📒 Files selected for processing (1)
🔇 Additional comments (2)
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. Comment |
PR Compliance Guide 🔍Below is a summary of compliance checks for this PR:
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.
PR Code Suggestions ✨Explore these optional code suggestions:
|
||||||||||||||||||
There was a problem hiding this 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 referencesNEXT_PUBLIC_MAPBOX_ACCESS_TOKEN(line 13-15).Clarify when to use each:
MAPBOX_ACCESS_TOKEN: For server-side Composio integrationNEXT_PUBLIC_MAPBOX_ACCESS_TOKEN: For client-side mapbox-gl renderingConsider adding a comment explaining this distinction.
mapbox_mcp/hooks.ts (1)
96-161: Critical: Composio tools are incompatible with Vercel AI SDK'sgenerateText.Line 105 passes
toolsRef.current(raw Composio tool descriptors fromgetTools()) directly togenerateText. The Vercel AI SDK requires tools to have Zod schemas andexecutefunctions, but raw Composio tools lack this structure.Composio provides official adapters (
@composio/vercelprovider orVercelAIToolSet) 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:
- Use
VercelAIToolSetfrom@composio/coreto convert tools before passing togenerateText- Use the
@composio/vercelprovider during Composio initialization- Remove AI-assisted query processing and use direct action execution instead
📜 Review details
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (8)
.env.local.exampleCOMPOSIO_MIGRATION.mdmapbox_mcp/README.mdmapbox_mcp/composio-mapbox.tsmapbox_mcp/hooks.tsmapbox_mcp/index.tsmapbox_mcp_config.jsonpackage.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.jsonand.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/coreversion 0.5.0 does not exist.The scoped package
@composio/corehas a latest version of 0.1.50. Version 0.5.0 exists only for the unscoped packagecomposio-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 expectsapiKey(minimum required),baseURL,allowTracking, andallowTracing—notauthConfigId,userId, or nestedcomposio.mapboxstructure.Additionally:
- The placeholder value
ac_YOUR_MAPBOX_CONFIG_IDis hardcoded in the config file rather than loaded from environment variables (despite the description claiming env vars should be set).- The
authConfigIdanduserIdappear 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
apiKeyat 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
geocodeActionexistence 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
connectfunction has proper error handling, state management withtry/catch/finally, and defensive checks before accessingcomposioClientRef.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 ofconnectionIdforconnectedAccountIdcorrectly associates actions with the authenticated connection.
| # 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/ | ||
| ``` | ||
|
|
There was a problem hiding this comment.
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.
| ### 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" | ||
| ``` |
There was a problem hiding this comment.
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:
- The guide doesn't explain how to get a Composio API key for authenticating the SDK itself
- "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.
| ## 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/ | ||
| ``` | ||
|
|
There was a problem hiding this comment.
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.
| ```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 | ||
| ``` |
There was a problem hiding this comment.
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:
- Missing blank lines around fenced code blocks (lines 36, 50)
- 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.
| 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 | ||
| ``` |
There was a problem hiding this comment.
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.
There was a problem hiding this 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 usestoolsRef.currentas thetoolspassed intogenerateText(), butconnect()currently loads tools fromcomposioClient.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 likegeocode_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.exampleto Composio variables likeCOMPOSIO_MAPBOX_AUTH_CONFIG_ID,COMPOSIO_USER_ID, andMAPBOX_ACCESS_TOKEN - Replaced
mapbox_mcp_config.jsonfrom an MCP server config to acomposio.mapboxconfig object
New Composio client module
- Added
mapbox_mcp/composio-mapbox.tswith helper functions:authenticateToolkit(...)initializeComposioMapbox()getComposioClient()
Hook + test script migration
- Updated
mapbox_mcp/hooks.tsto:- Initialize a Composio client on mount
- Establish a connected account via
initializeComposioMapbox() - Execute Mapbox operations via
executeAction({ action: 'mapbox_*', ... })
- Updated
mapbox_mcp/index.tsto test Composio connection and run a samplemapbox_geocode_locationaction
Docs
- Added
mapbox_mcp/README.mdandCOMPOSIO_MIGRATION.mddescribing setup, env vars, and migration steps
mapbox_mcp/composio-mapbox.ts
Outdated
| // 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; | ||
| } |
There was a problem hiding this comment.
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_idfalls back to a placeholder stringuserIdfalls back touser@example.comuserApiKeyfalls back toyour_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.
mapbox_mcp/composio-mapbox.ts
Outdated
| // 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; | ||
| } |
There was a problem hiding this comment.
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 singleCOMPOSIO_USER_IDfor 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.
mapbox_mcp/hooks.ts
Outdated
| // 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]); | ||
| }, []); |
There was a problem hiding this comment.
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:
- 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 });
}- 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.
mapbox_mcp/hooks.ts
Outdated
| 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); | ||
| }, []); |
There was a problem hiding this comment.
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.
mapbox_mcp/index.ts
Outdated
| 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'] | ||
| }); |
There was a problem hiding this comment.
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.
.env.local.example
Outdated
| # 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" |
There was a problem hiding this comment.
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.
There was a problem hiding this 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",
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.
There was a problem hiding this 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/coreSDK requiresCOMPOSIO_API_KEYfor 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 incomposio-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: Replaceanytype with properComposiotype.Using
anyforcomposioClientloses type safety and defeats TypeScript's compile-time checks. Import theComposiotype from@composio/coreand 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()andinitializeComposioMapbox(), and have the client hook fetch the resultingconnectionIdfrom 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
connectfunction):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
useMCPMapClientbut now uses Composio instead of MCP. Consider renaming touseComposioMapClientfor 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:composioClientRefmay be null whendisconnect()or tool methods are called.The
useEffectinitializescomposioClientRef.currentasynchronously. If a consumer callsdisconnect(),geocodeLocation(),calculateDistance(), orsearchNearbyPlaces()before the effect completes,composioClientRef.currentwill benulland 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
📒 Files selected for processing (6)
.env.local.examplemapbox_mcp/README.mdmapbox_mcp/composio-mapbox.tsmapbox_mcp/hooks.tsmapbox_mcp/index.tspackage.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
composiosingleton andvalidateEnvironmentVariables()readCOMPOSIO_USER_IDonce 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_IDrepresents the application (single-tenant) rather than end-users, this design is acceptable. However, if this integration will serve multiple authenticated users, consider acceptinguserIdas a parameter toinitializeComposioMapbox()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
validateEnvironmentVariablesfunction 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.
| # 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.comBased 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.
| # 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.
There was a problem hiding this 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
defaultcase. IfqueryTypedoesn't match any case,toolNameisundefined, 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
📒 Files selected for processing (3)
.env.local.examplelib/agents/tools/geospatial.tsxmapbox_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.examplecould 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/corev0.5.0 API compatibility forAuthScheme.APIKey()method.The code calls
AuthScheme.APIKey({ api_key: ... })on line 78, but current public documentation for Composio SDK shows authentication configured viaAuthSchemeTypes.API_KEYenum withcredentials: { 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.
| # 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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).
| 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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 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 -nRepository: 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 2Repository: QueueLab/QCX
Length of output: 570
🏁 Script executed:
# Check the environment variables being used
rg "NEXT_PUBLIC|composioApiKey|composioUserId" lib/agents/tools/geospatial.tsx -nRepository: 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:
- 1: https://docs.composio.dev/docs/mcp-quickstart?utm_source=openai
- 2: https://mcp-cloud.ai/docs/authentication/client-auth?utm_source=openai
- 3: https://mcp-cloud.ai/docs/authentication/client-auth?utm_source=openai
- 4: https://mcp-cloud.ai/docs/authentication/client-auth?utm_source=openai
- 5: https://mcp-framework.com/docs/Authentication/overview/?utm_source=openai
- 6: https://v3.docs.composio.dev/api-reference/mcp/post-mcp-servers?utm_source=openai
- 7: https://mcp-framework.com/docs/Authentication/overview/?utm_source=openai
- 8: https://mcp-cloud.ai/docs/authentication/overview?utm_source=openai
- 9: https://mcp-cloud.ai/docs/authentication/overview?utm_source=openai
- 10: https://mcp-cloud.ai/docs/authentication/client-auth?utm_source=openai
- 11: https://v3.docs.composio.dev/api-reference/mcp/post-mcp-servers?utm_source=openai
- 12: https://mcp-cloud.ai/docs/authentication/overview?utm_source=openai
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.
| 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; | ||
| } | ||
| } |
There was a problem hiding this comment.
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.
|
@coderabbitai integrated as a tool or as an MCP |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: 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:
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 NamingThe directory is still named |
|
@coderabbitai what env variables for composio are needed |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 3537 @ngoiyaeric Here are all the Composio environment variables needed for the Mapbox integration: Required Server-Side VariablesThese must be set in your # 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_keyOptional Client-Side VariablesOnly 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.comHow to Get These Values
Security Best Practices
The README.md recommends using server-side API routes instead of client-side direct access for better security. |
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
@smithery/cli,@smithery/sdk,smithery@composio/core(v0.5.0)Modified Files (5)
New Files (3)
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:
Setup Instructions
bun install.env.localbun run mapbox_mcp/index.tsDocumentation
mapbox_mcp/README.mdCOMPOSIO_MIGRATION.mdTesting
Breaking Changes
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
File Walkthrough
composio-mapbox.ts
Core Composio client setup and authenticationmapbox_mcp/composio-mapbox.ts
authentication
authenticateToolkit()function for API Key authenticationinitializeComposioMapbox()for connection setupgetComposioClient()to retrieve Composio instancehooks.ts
Replace Smithery with Composio in React hooksmapbox_mcp/hooks.ts
useMcphook from 'use-mcp/react' with Composio SDKinitializeComposioMapbox()mcp.callTool()tocomposioClient.executeAction()connectionIdstate andcomposioClientReffor Composio clientmanagement
API
index.ts
Update test script for Composio integrationmapbox_mcp/index.ts
client.callTool()tocomposioClient.executeAction()result.datainstead of JSONextraction
.env.local.example
Update environment variables for Composio.env.local.example
SMITHERY_API_KEY)
COMPOSIO_USER_ID)
mapbox_mcp_config.json
Replace MCP config with Composio structuremapbox_mcp_config.json
package.json
Update dependencies from Smithery to Composiopackage.json
@smithery/cli(^1.2.5) dependency@smithery/sdk(^1.0.4) dependencysmithery(^0.5.2) dependency@composio/core(^0.5.0) dependencyCOMPOSIO_MIGRATION.md
Add detailed Smithery to Composio migration guideCOMPOSIO_MIGRATION.md
README.md
Add Mapbox Composio integration documentationmapbox_mcp/README.md
Summary by CodeRabbit
Updates
Configuration
Documentation
Chores
✏️ Tip: You can customize this high-level summary in your review settings.