Skip to content

Conversation

@sidneyswift
Copy link
Contributor

Changes

  • Removed old Google Sheets implementation (858 lines deleted)
  • Composio Tool Router tools now added directly in setupToolsForRequest
  • Fixed tool validation for inputSchema (Composio uses inputSchema not parameters)
  • Fixed callback URL to localhost:3001 (so composio login goes back to chat in dev)

Related

- Use x-api-key auth instead of account_id in request bodies/params
- Add Zod validation for disconnect connector endpoint
- Move DELETE to /api/connectors (KISS - RESTful design)
- Extract getFrontendBaseUrl to own file (SRP)
- Simplify registerComposioTools to return raw tools
- Filter Composio tools to allowed subset in getTools.ts
- Update CLAUDE.md with auth guidelines
…point

- Create validateAuthorizeConnectorBody.ts with Zod schema
- Validate connector (required string) and callback_url (optional URL)
- Update route to use validation function per coding guidelines
- Add verifyConnectorOwnership() to check connected_account_id belongs to user
- DELETE /api/connectors now returns 403 if user doesn't own the connection
- Prevents authorization bypass where users could disconnect other users' connectors
- Remove unsafe type assertion 'as Record<string, ComposioTool>'
- Add isComposioTool() type guard with runtime validation
- Use Object.prototype.hasOwnProperty for safe property access
- Validates description (string), inputSchema (exists), execute (function)

Addresses CodeRabbit's critical issue about unsafe type casting on SDK return values.
- Replace custom ComposioTool interface with Vercel AI SDK's Tool type
- Import Tool and ToolSet types from 'ai' package
- Update isValidTool() to check for 'parameters' (SDK format) instead of 'inputSchema'
- Use ToolSet as return type for getComposioTools()
- Maintains runtime validation while using correct SDK types

This aligns with Tool Router's actual return type when using VercelProvider:
session.tools() returns ToolSet (Record<string, Tool>) from Vercel AI SDK.
- Check for VERCEL_URL to support preview deployments
- Preview URLs need https:// prepended (VERCEL_URL doesn't include protocol)
- Maintains production (chat.recoupable.com) and local (localhost:3001) behavior

Fixes OAuth redirect issue where preview deployments would incorrectly
redirect to localhost, which is unreachable.
- Check VERCEL_GIT_COMMIT_REF for 'test' branch specifically
- Use stable test frontend URL for test deployments
- Maintains preview URL fallback for other feature branches
- Easier to update TEST_FRONTEND_URL constant if domain changes
Match API pattern: test-recoup-api -> test-recoup-chat
- Remove verbose description constant and inline it
- Remove separate schema type definition
- Inline schema directly in registerTool call
- Keep same functionality: passes raw results from getComposioTools
- Tool filtering handled by ALLOWED_TOOLS in getTools.ts
- Remove getToolResultSuccess and getToolResultError wrapper imports
- Use getCallToolResult(JSON.stringify(...)) directly
- Follows KISS: pass raw results without unnecessary wrappers
- Frontend (Recoup-Chat) runs on port 3000, not 3001
- API (Recoup-API) runs on port 3001
- getFrontendBaseUrl should return frontend port
- Remove JSDoc comments
- Remove try/catch wrapper
- Simplify description and schema
- Just pass through results from getComposioTools directly
- Add ENABLED_TOOLKITS constant for easy expansion later
- Pass toolkits option to session.create() per Composio docs
- Currently only googlesheets is enabled
- Remove account_id from composio tool input schema
- Get accountId from MCP auth info via resolveAccountId
- Keep room_id as optional input for OAuth redirect
- Follows API auth pattern used by other MCP tools
- Update CLAUDE.md Authentication section
- Add MCP tools pattern using resolveAccountId
- Clarify both API keys and Privy tokens resolve to accountId
…Router directly

- Remove googleSheetsAgent and related files
- Remove MCP composio wrapper tool
- Add Composio tools directly in setupToolsForRequest
- Fix tool validation to check for inputSchema (Composio format)
- Fix frontend callback URL for local development (localhost:3001)
@vercel
Copy link

vercel bot commented Jan 20, 2026

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

Project Deployment Review Updated (UTC)
recoup-api Ready Ready Preview Jan 20, 2026 9:07pm

@coderabbitai
Copy link

coderabbitai bot commented Jan 20, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


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

❤️ Share

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

Copy link
Contributor

Choose a reason for hiding this comment

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

rollback changes to this file.

Copy link

@vercel vercel bot left a comment

Choose a reason for hiding this comment

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

Additional Suggestion:

Missing null/undefined check before using the 'in' operator on session.tools() result causes TypeError if the Composio API returns null or undefined

View Details
📝 Patch Details
diff --git a/lib/composio/toolRouter/getTools.ts b/lib/composio/toolRouter/getTools.ts
index 3d71342..2c66191 100644
--- a/lib/composio/toolRouter/getTools.ts
+++ b/lib/composio/toolRouter/getTools.ts
@@ -58,6 +58,11 @@ export async function getComposioTools(
   // Filter to only allowed tools with runtime validation
   const filteredTools: ToolSet = {};
 
+  // Check if allTools is a valid object before using the 'in' operator
+  if (!allTools || typeof allTools !== "object") {
+    return filteredTools;
+  }
+
   for (const toolName of ALLOWED_TOOLS) {
     if (toolName in allTools) {
       const tool = (allTools as Record<string, unknown>)[toolName];

Analysis

Bug Analysis

Why it happens:

The getComposioTools function in lib/composio/toolRouter/getTools.ts calls session.tools() and immediately uses the result with the in operator without validating it. In JavaScript, the in operator requires its right operand to be an object. If session.tools() returns null or undefined, the code throws a TypeError: "Cannot use 'in' operator to search for [toolName] in null/undefined".

When it manifests:

This error could occur in several scenarios:

  1. Network failures when calling the Composio API
  2. Unexpected API responses from Composio
  3. Session creation failures that return an invalid session object
  4. API changes or library bugs in Composio that return null instead of an object

While Composio likely returns a valid object in normal operation, defensive programming requires handling these edge cases, especially for external API calls.

Impact:

  • Runtime TypeError crash that would terminate the chat request
  • User's chat would fail to load tools
  • Application would return a 500 error to the client
  • No graceful fallback to continue chat without Composio tools

Fix Applied

Added a null/undefined check immediately after calling session.tools():

// Check if allTools is a valid object before using the 'in' operator
if (!allTools || typeof allTools !== "object") {
  return filteredTools;
}

This check:

  1. Validates that allTools is not null or undefined
  2. Ensures it's actually an object type
  3. Returns an empty ToolSet (which is the correct type) if validation fails
  4. Prevents the TypeError while maintaining proper behavior

The fix is safe because:

  • An empty ToolSet is a valid return value
  • It allows the chat to continue without Composio tools rather than crashing
  • The existing code already handles empty objects correctly (the loop just doesn't execute)
  • It's consistent with defensive programming practices for external API calls

Resolve conflicts in setupToolsForRequest.ts by combining:
- HTTP MCP transport (from test) for proper auth
- Composio tool router (from composio-tool-router) for Google Sheets
  and other connectors

Updated tests to reflect the new HTTP MCP + Composio architecture.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@sweetmantech sweetmantech merged commit 3a403f6 into test Jan 20, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants