Skip to content

Implement mcp integration system#814

Merged
elie222 merged 57 commits intomainfrom
cursor/implement-mcp-integration-system-cc46
Oct 2, 2025
Merged

Implement mcp integration system#814
elie222 merged 57 commits intomainfrom
cursor/implement-mcp-integration-system-cc46

Conversation

@elie222
Copy link
Owner

@elie222 elie222 commented Sep 22, 2025

Adds the core Model Context Protocol (MCP) foundation, including database schema, credential encryption, a reusable package, and API routes for tool discovery and execution.

This initial implementation establishes the backend infrastructure for AI agents to interact with external services via MCP. It focuses on data models, secure credential handling, a modular MCP package for orchestration and client interactions, and basic API endpoints. UI and full OAuth flows are intentionally deferred to subsequent PRs to maintain a focused scope.


Open in Cursor Open in Web


Note

Introduce full MCP integration stack: schema/migrations, secure token handling, OAuth flows, server/client utilities, APIs, agent tooling and a UI to connect/manage tools; plus AI prompt helpers and reply drafting improvements.

  • MCP Platform (backend):
    • Add Prisma models and migrations: McpIntegration, McpConnection, McpTool with encrypted credentials and indexes; extend Prisma token encryption for MCP.
    • Implement OAuth utilities (PKCE, dynamic client registration), token exchange/refresh, and integration registry (MCP_INTEGRATIONS).
    • Introduce generic MCP client and tool sync/test utilities (utils/mcp/*).
    • New API routes: GET /api/mcp/registry, GET /api/mcp/connections, GET /api/mcp/[integration]/auth-url, GET /api/mcp/[integration]/callback, GET /api/mcp/[integration]/test.
    • Server actions to connect via API key, toggle/disable, disconnect connections, toggle tools, and test agent.
  • AI Agent & Prompts:
    • Add mcpAgent to research via MCP tools; integrate optional mcpContext into aiDraftWithKnowledge flow.
    • Centralize prompt helpers (getUserInfoPrompt, getUserRulesPrompt, getEmailListPrompt, getTodayForLLM) and update AI modules to use them.
  • UI (Integrations):
    • New pages/components to view/connect/manage MCP integrations and tools: Integrations, IntegrationRow, ConnectApiTokenModal, RequestAccessDialog, and test page.
    • Hooks: useIntegrations, useMcpConnections.
  • Other changes:
    • Add @modelcontextprotocol/sdk, @vitest/ui; adjust test-ai script and add AI/MCP tests.
    • Update fetchWithAccount usage; minor callback route typings/log improvements.
    • Env: add MCP client ID/secret vars for Notion/Monday/HubSpot.

Written by Cursor Bugbot for commit 6a100e5. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • New Features

    • Introduced Integrations page to connect and manage MCP integrations (e.g., Notion, HubSpot, Stripe, Monday).
    • OAuth connection flow with redirect, state handling, and tool syncing.
    • Per-integration tool management: view, enable/disable, and disconnect.
    • Request Access dialog to ask for new integrations.
    • MCP Agent Test page to run sample queries and view tool-call traces.
  • Improvements

    • Draft replies can incorporate MCP-sourced context for better responses.
  • Documentation

    • Added guidance to use shared test helpers.
  • Tests

    • Added comprehensive AI/MCP agent and prompt helper test suites.
  • Chores

    • Version bump to v2.13.0; added coverage to .gitignore; dependency updates.

Co-authored-by: eliesteinbock <eliesteinbock@gmail.com>
@cursor
Copy link

cursor bot commented Sep 22, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@vercel
Copy link

vercel bot commented Sep 22, 2025

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

Project Deployment Preview Updated (UTC)
inbox-zero Error Error Oct 2, 2025 8:50pm

@CLAassistant
Copy link

CLAassistant commented Sep 22, 2025

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ elie222
❌ cursoragent
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 22, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds MCP integrations end-to-end: database models/migration, Prisma encryption extension, OAuth (discovery/registration/token exchange/refresh), tool listing/aggregation, sync, API routes, UI (integrations pages/components), server actions, and an MCP agent with tests. Introduces shared AI prompt helpers and refactors many AI prompts to use them. Updates fetch helper signature and related usages.

Changes

Cohort / File(s) Summary
MCP Data Model & Persistence
apps/web/prisma/schema.prisma, apps/web/prisma/migrations/.../20251001142931_mcp/migration.sql, apps/web/utils/prisma-extensions.ts
Adds McpIntegration/McpConnection/McpTool models with relations and indices; migration creating tables and FKs; Prisma extension to encrypt/decrypt MCP tokens on result/query for mcpConnection.
MCP OAuth & Tokens
apps/web/utils/mcp/oauth.ts, apps/web/utils/oauth/state.ts, apps/web/utils/mcp/transport.ts, apps/web/utils/mcp/integrations.ts, apps/web/utils/mcp/list-tools.ts
Implements OAuth discovery/registration/token flows, state/pkce helpers, HTTP transport, integrations registry (names/scopes/allowed tools), and tool listing via MCP client using Bearer tokens.
MCP Tool Sync & Aggregation
apps/web/utils/mcp/sync-tools.ts, apps/web/utils/ai/mcp/mcp-tools.ts
Syncs tools into DB (filtering by allowedTools) and aggregates enabled tools across active connections; manages token refresh and client cleanup.
MCP Agent & Actions
apps/web/utils/ai/mcp/mcp-agent.ts, apps/web/utils/actions/mcp.ts, apps/web/utils/actions/mcp.validation.ts, apps/web/utils/reply-tracker/generate-draft.ts
Adds MCP agent runner (tool-augmented text gen) and server actions to disconnect/toggle connections/tools and test agent; wires agent context into draft generation.
MCP API Routes
apps/web/app/api/mcp/[integration]/auth-url/route.ts, apps/web/app/api/mcp/[integration]/callback/route.ts, apps/web/app/api/mcp/integrations/route.ts
Adds OAuth auth URL and callback handlers with cookie/state/PKCE and sync; adds integrations listing endpoint (merging config with per-account connections/tools).
MCP UI
apps/web/app/(app)/[emailAccountId]/integrations/Integrations.tsx, apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx, apps/web/app/(app)/[emailAccountId]/integrations/RequestAccessDialog.tsx, apps/web/app/(app)/[emailAccountId]/integrations/page.tsx, apps/web/app/(app)/[emailAccountId]/integrations/test/McpAgentTest.tsx, apps/web/app/(app)/[emailAccountId]/integrations/test/page.tsx, apps/web/app/(app)/(redirects)/integrations/page.tsx
Adds integrations listing page/UI with connect/toggle/tools/disconnect, request-access dialog, test page for MCP agent, and redirects page.
AI Prompt Helpers Refactor
apps/web/utils/ai/helpers.ts, apps/web/utils/ai/helpers.test.ts, apps/web/utils/ai/assistant/process-user-request.ts, apps/web/utils/ai/calendar/availability.ts, apps/web/utils/ai/choose-rule/ai-choose-args.ts, apps/web/utils/ai/choose-rule/ai-choose-rule.ts, apps/web/utils/ai/choose-rule/ai-detect-recurring-pattern.ts, apps/web/utils/ai/digest/summarize-email-for-digest.ts, apps/web/utils/ai/knowledge/extract-from-email-history.ts, apps/web/utils/ai/knowledge/extract.ts, apps/web/utils/ai/knowledge/persona.ts, apps/web/utils/ai/knowledge/writing-style.ts, apps/web/utils/ai/reply/check-if-needs-reply.ts, apps/web/utils/ai/reply/draft-with-knowledge.ts, apps/web/utils/ai/reply/generate-nudge.ts, apps/web/utils/ai/reply/reply-context-collector.ts, apps/web/utils/ai/report/summarize-emails.ts, apps/web/utils/ai/rule/generate-rules-prompt.ts, apps/web/utils/ai/snippets/find-snippets.ts, apps/web/utils/llms/helpers.ts
Adds helper utilities (today, user info, rules, email list) and tests; replaces inline prompt blocks with helper outputs across AI flows; removes getTodayForLLM from llms/helpers; adds mcpContext to draft-with-knowledge.
Tests
apps/web/__tests__/ai-mcp-agent.test.ts, apps/web/__tests__/ai/reply/draft-with-knowledge.test.ts, .cursor/rules/llm-test.mdc
Adds MCP agent test suite with mocked tools; updates draft-with-knowledge tests to include new optional args; updates test best-practices doc.
Fetch and Client Utilities
apps/web/utils/fetch.ts, apps/web/app/(app)/[emailAccountId]/calendars/ConnectCalendarButton.tsx, apps/web/store/archive-sender-queue.ts, apps/web/utils/middleware.ts, apps/web/utils/logger.ts
Makes fetchWithAccount emailAccountId parameter required (nullable) and updates callers; minor code style/middleware comment removal; logger now stringifies Errors as messages via recursive processing.
Hooks & Package & Misc
apps/web/hooks/useIntegrations.tsx, apps/web/package.json, .gitignore, version.txt, apps/web/app/(landing)/welcome-upgrade/page.tsx
Adds useIntegrations SWR hook; updates scripts/dependencies; ignores coverage; bumps version to v2.13.0; minor landing page layout tweak.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant UI as Integrations UI
  participant API as GET /api/mcp/[integration]/auth-url
  participant OAuth as OAuth Provider
  participant CB as GET /api/mcp/[integration]/callback
  participant DB as Prisma

  User->>UI: Click "Connect"
  UI->>API: Request auth URL (with Email-Account header)
  API->>DB: Validate integration / load creds
  API->>API: generateAuthorizationUrl + set state/PKCE cookies
  API-->>UI: { url }
  UI->>OAuth: Redirect to authorization URL
  OAuth-->>CB: Redirect back with code/state
  CB->>DB: Validate state/PKCE, find emailAccount
  CB->>CB: Exchange code for tokens
  CB->>DB: Upsert connection + tokens
  CB->>CB: syncMcpTools (best-effort)
  CB-->>User: Redirect to /[emailAccount]/integrations?connected=1
Loading
sequenceDiagram
  autonumber
  actor User
  participant UI as McpAgentTest / Reply Tracker
  participant Actions as testMcpAction / generateDraft
  participant Agent as mcpAgent
  participant Tools as createMcpToolsForAgent
  participant DB as Prisma

  User->>UI: Submit test / trigger draft
  UI->>Actions: invoke with emailAccountId + inputs
  Actions->>Tools: createMcpToolsForAgent(emailAccountId)
  Tools->>DB: Load active connections + tools
  Tools->>Tools: Get/refresh access tokens
  Tools->>Tools: Create MCP clients, fetch tools
  Actions->>Agent: run with messages + tools
  Agent-->>Actions: { response | null, getToolCalls }
  Actions-->>UI: Result + tool calls
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related issues

  • MCP Integration System #813 — Implements the MCP integration system (models, OAuth, tool discovery, agent, sync, UI, routes), matching the added components and flows.

Possibly related PRs

Suggested reviewers

  • johnlowe399-blip
  • anakarentorosserrano-star

Poem

Hop hop hooray, new bridges abound,
Tokens refreshed, tools neatly found.
OAuth dances, tables align,
Agents converse in promptified rhyme.
I nibble on logs, errors now tame—
MCP’s in town; integrations take aim! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.94% which is insufficient. The required threshold is 80.00%. You can run `@coderabbitai generate docstrings` to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit's high-level summary is enabled.
Title Check ✅ Passed The title “Implement mcp integration system” directly reflects the core purpose of the changeset, which is to introduce the full MCP integration foundation across models, APIs, OAuth flows, AI tools, and UI components. It is concise, specific, and clearly communicates the primary change.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/implement-mcp-integration-system-cc46

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.

Integrates Model Context Protocol (MCP) to enrich AI email drafts with external tool data. This includes fetching contact details from CRM and searching documents in knowledge bases. The changes add new utilities for collecting MCP context, update AI drafting logic to include this context, and expand MCP integration configurations.

Co-authored-by: eliesteinbock <eliesteinbock@gmail.com>
Co-authored-by: eliesteinbock <eliesteinbock@gmail.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/web/utils/ai/mcp/mcp-tools.ts (1)

128-130: Prevent tool name collisions across integrations.

When merging tools from multiple integrations, using the raw toolName as the key (line 129) can cause silent overwrites if two integrations expose identically named tools. This was flagged in a previous review but remains unaddressed.

Prefix each tool key with the integration name to avoid collisions:

         // Merge tools
         Object.entries(filteredTools).forEach(([toolName, toolDef]) => {
-          allTools[toolName] = toolDef;
+          allTools[`${integration.name}_${toolName}`] = toolDef;
         });

Ensure downstream consumers (e.g., mcpAgent) are updated to use the namespaced keys when invoking tools.

🧹 Nitpick comments (3)
apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx (1)

137-175: Consider using a custom dialog for disconnect confirmation.

The function correctly handles the disconnect flow with proper error handling and state management. However, the native confirm() dialog is less consistent with the app's UI.

Consider replacing the native confirm() with a custom dialog component (e.g., an AlertDialog from shadcn/ui) for better UX consistency:

// Add state for dialog
const [showDisconnectDialog, setShowDisconnectDialog] = useState(false);

// Replace confirm with dialog trigger
const handleDisconnect = async () => {
  setShowDisconnectDialog(true);
};

// Add confirmation handler
const confirmDisconnect = async () => {
  if (!connectionId) return;
  setDisconnecting(true);
  // ... rest of disconnect logic
};

// Render AlertDialog in JSX
<AlertDialog open={showDisconnectDialog} onOpenChange={setShowDisconnectDialog}>
  <AlertDialogContent>
    <AlertDialogTitle>Disconnect Integration?</AlertDialogTitle>
    <AlertDialogDescription>
      This will remove all associated tools.
    </AlertDialogDescription>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancel</AlertDialogCancel>
      <AlertDialogAction onClick={confirmDisconnect}>
        Disconnect
      </AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>
apps/web/utils/mcp/sync-tools.ts (1)

17-20: Remove redundant validation check.

getIntegration(integration) already throws Error if the integration is unknown (see apps/web/utils/mcp/integrations.ts lines 181-183), so the subsequent null check at lines 18-20 is unreachable and can be removed.

Apply this diff:

   const integrationConfig = getIntegration(integration);
-  if (!integrationConfig) {
-    throw new Error(`Unknown integration: ${integration}`);
-  }
apps/web/utils/mcp/oauth.ts (1)

440-442: Document fallback expiry behavior.

When expires_in is absent in the refresh response, the code falls back to the old connection.expiresAt. This could retain a stale expiry if the original token was expired. However, this is a reasonable defensive fallback that maintains the existing expiry rather than setting null or a default.

Consider logging a warning when the fallback is used:

   const expiresAt = tokens.expires_in
     ? new Date(Date.now() + tokens.expires_in * 1000)
-    : connection.expiresAt;
+    : (() => {
+        logger.warn("Refresh response missing expires_in, using existing expiry", {
+          integration,
+          emailAccountId,
+        });
+        return connection.expiresAt;
+      })();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09eab48 and ab8c80c.

📒 Files selected for processing (6)
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx (1 hunks)
  • apps/web/utils/ai/mcp/mcp-tools.ts (1 hunks)
  • apps/web/utils/mcp/list-tools.ts (1 hunks)
  • apps/web/utils/mcp/oauth.ts (1 hunks)
  • apps/web/utils/mcp/sync-tools.ts (1 hunks)
  • apps/web/utils/mcp/transport.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (19)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
  • apps/web/utils/mcp/oauth.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
  • apps/web/utils/mcp/oauth.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/utils/mcp/oauth.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/utils/mcp/oauth.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
  • apps/web/utils/mcp/oauth.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/mcp/sync-tools.ts
  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/transport.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
  • apps/web/utils/mcp/oauth.ts
apps/web/utils/ai/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/app/**

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

NextJS app router structure with (app) directory

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
apps/web/**/*.tsx

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.tsx: Follow tailwindcss patterns with prettier-plugin-tailwindcss
Prefer functional components with hooks
Use shadcn/ui components when available
Ensure responsive design with mobile-first approach
Follow consistent naming conventions (PascalCase for components)
Use LoadingContent component for async data
Use result?.serverError with toastError and toastSuccess
Use LoadingContent component to handle loading and error states consistently
Pass loading, error, and children props to LoadingContent

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.tsx: Use React Hook Form with Zod for validation
Validate form inputs before submission
Show validation errors inline next to form fields

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
apps/web/app/(app)/*/**

📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)

Components for the page are either put in page.tsx, or in the apps/web/app/(app)/PAGE_NAME folder

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
apps/web/app/(app)/*/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)

If you need to use onClick in a component, that component is a client component and file must start with 'use client'

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
apps/web/app/(app)/*/**/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/page-structure.mdc)

If we're in a deeply nested component we will use swr to fetch via API

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
apps/web/app/**/*.tsx

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Components with onClick must be client components with use client directive

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{jsx,tsx}: Don't destructure props inside JSX components in Solid projects.
Don't use both children and dangerouslySetInnerHTML props on the same element.
Don't use Array index in keys.
Don't assign to React component props.
Don't define React components inside other components.
Don't use event handlers on non-interactive elements.
Don't assign JSX properties multiple times.
Don't add extra closing tags for components without children.
Use <>...</> instead of ....
Don't insert comments as text nodes.
Don't use the return value of React.render.
Make sure all dependencies are correctly specified in React hooks.
Make sure all React hooks are called from the top level of component functions.
Don't use unnecessary fragments.
Don't pass children as props.
Use semantic elements instead of role attributes in JSX.

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
**/*.{html,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{html,jsx,tsx}: Don't use or elements.
Don't use accessKey attribute on any HTML element.
Don't set aria-hidden="true" on focusable elements.
Don't add ARIA roles, states, and properties to elements that don't support them.
Only use the scope prop on elements.
Don't assign non-interactive ARIA roles to interactive HTML elements.
Make sure label elements have text content and are associated with an input.
Don't assign interactive ARIA roles to non-interactive HTML elements.
Don't assign tabIndex to non-interactive HTML elements.
Don't use positive integers for tabIndex property.
Don't include "image", "picture", or "photo" in img alt prop.
Don't use explicit role property that's the same as the implicit/default role.
Make static elements with click handlers use a valid role attribute.
Always include a title element for SVG elements.
Give all elements requiring alt text meaningful information for screen readers.
Make sure anchors have content that's accessible to screen readers.
Assign tabIndex to non-interactive HTML elements with aria-activedescendant.
Include all required ARIA attributes for elements with ARIA roles.
Make sure ARIA properties are valid for the element's supported roles.
Always include a type attribute for button elements.
Make elements with interactive roles and handlers focusable.
Give heading elements content that's accessible to screen readers (not hidden with aria-hidden).
Always include a lang attribute on the html element.
Always include a title attribute for iframe elements.
Accompany onClick with at least one of: onKeyUp, onKeyDown, or onKeyPress.
Accompany onMouseOver/onMouseOut with onFocus/onBlur.
Include caption tracks for audio and video elements.
Make sure all anchors are valid and navigable.
Ensure all ARIA properties (aria-*) are valid.
Use valid, non-abstract ARIA roles for elements with ARIA roles.
Use valid ARIA state and property values.
Use valid values for the autocomplete attribute on input eleme...

Files:

  • apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx
🧬 Code graph analysis (5)
apps/web/utils/mcp/sync-tools.ts (3)
apps/web/utils/mcp/integrations.ts (1)
  • getIntegration (179-187)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/list-tools.ts (1)
  • listMcpTools (19-69)
apps/web/utils/mcp/list-tools.ts (4)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (2)
  • IntegrationKey (177-177)
  • getIntegration (179-187)
apps/web/utils/mcp/oauth.ts (1)
  • getValidAccessToken (466-507)
apps/web/utils/mcp/transport.ts (1)
  • createMcpTransport (3-15)
apps/web/utils/ai/mcp/mcp-tools.ts (4)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (1)
  • getIntegration (179-187)
apps/web/utils/mcp/oauth.ts (1)
  • getValidAccessToken (466-507)
apps/web/utils/mcp/transport.ts (1)
  • createMcpTransport (3-15)
apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx (7)
apps/web/app/api/mcp/integrations/route.ts (1)
  • GetIntegrationsResponse (6-6)
apps/web/providers/EmailAccountProvider.tsx (1)
  • useAccount (72-82)
apps/web/utils/fetch.ts (1)
  • fetchWithAccount (7-25)
apps/web/app/api/mcp/[integration]/auth-url/route.ts (1)
  • GetMcpAuthUrlResponse (16-16)
apps/web/utils/actions/mcp.ts (3)
  • toggleMcpConnectionAction (27-40)
  • toggleMcpToolAction (42-52)
  • disconnectMcpConnectionAction (16-25)
apps/web/app/(app)/[emailAccountId]/integrations/RequestAccessDialog.tsx (1)
  • RequestAccessDialog (21-102)
apps/web/utils/string.ts (1)
  • truncate (1-3)
apps/web/utils/mcp/oauth.ts (2)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (3)
  • getIntegration (179-187)
  • IntegrationKey (177-177)
  • getStaticCredentials (193-210)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Secret Detection
  • GitHub Check: Jit Security
🔇 Additional comments (18)
apps/web/app/(app)/[emailAccountId]/integrations/IntegrationRow.tsx (6)

1-28: LGTM! Imports and file structure are well-organized.

The use client directive is correctly placed, and imports follow coding guidelines (type imports use the type keyword, no namespace imports).


29-50: LGTM! Component setup follows React best practices.

Props interface, state management, and derived values are implemented correctly.


85-111: LGTM! Error handling and state management are correct.

The function properly checks for serverError, shows appropriate toasts, and triggers onConnectionChange on success.


113-135: LGTM! Tool toggle logic is consistent and complete.

Error handling mirrors the pattern used in handleToggle with proper serverError checks and toast notifications.


177-275: LGTM! JSX structure and accessibility are well-implemented.

The component correctly handles conditional rendering for different integration states (comingSoon, connected, authType). The aria-label on the MoreVertical button (line 251) properly addresses the previous accessibility concern.


277-333: LGTM! ToolsList component is well-structured.

The component correctly:

  • Sorts tools deterministically by name for consistent rendering
  • Uses the truncate helper to prevent overly long descriptions (line 316)
  • Conditionally renders tool descriptions (lines 314-318)
  • Properly handles tool toggle state

The past review comment about commented-out code has been addressed—tool descriptions are now rendered properly.

apps/web/utils/mcp/sync-tools.ts (1)

62-83: LGTM! Transaction correctly handles zero-tool case.

The conditional spread at lines 66-78 ensures createMany is only included when tools.length > 0, preventing Prisma errors. The delete-then-create pattern within a transaction is correct and avoids partial updates.

apps/web/utils/ai/mcp/mcp-tools.ts (2)

86-110: LGTM! Auth type handling is correct.

The implementation properly handles both oauth and api-token authentication types, retrieves the appropriate token, and logs warnings for missing credentials or unsupported auth types. This addresses the earlier concern about API token integrations being filtered out.


140-153: LGTM! Cleanup function properly closes all clients.

The cleanup function iterates over all clients and closes them with proper error handling, preventing resource leaks. The use of Promise.all ensures all clients are closed concurrently.

apps/web/utils/mcp/transport.ts (1)

3-15: LGTM! Transport creation is correct.

The function correctly constructs an StreamableHTTPClientTransport with Bearer token authentication and appropriate headers. No issues found.

apps/web/utils/mcp/list-tools.ts (1)

19-69: LGTM! Tool listing implementation is correct.

The function properly manages the MCP client lifecycle with try/finally, handles errors with appropriate logging and context, and ensures cleanup of resources. Token management is correctly delegated to getValidAccessToken.

apps/web/utils/mcp/oauth.ts (7)

27-170: LGTM! OAuth metadata discovery is robust.

The function correctly implements OAuth discovery with:

  • Caching to avoid redundant network calls
  • Optional RFC 9728 protected resource metadata
  • Required RFC 8414 authorization server metadata
  • Fallback to static configuration
  • Proper error handling and logging throughout

The cache invalidation based on serverUrl match (lines 44-47) prevents stale metadata issues.


176-260: LGTM! OAuth client credential management is well-structured.

The function follows the correct priority order:

  1. Static credentials (highest priority)
  2. Stored dynamic credentials
  3. Dynamic registration (fallback)

The client metadata at lines 224-231 correctly configures a public client with PKCE (token_endpoint_auth_method: "none"), which is appropriate for MCP integrations.


266-309: LGTM! OAuth URL generation is correct.

The function properly orchestrates the OAuth authorization flow:

  • Validates configuration
  • Obtains client credentials
  • Discovers authorization endpoints
  • Generates PKCE-protected authorization URL
  • Returns both URL and code verifier for secure storage

Logging appropriately excludes sensitive parameters.


315-389: LGTM! OAuth callback handling is comprehensive.

The function correctly:

  • Exchanges authorization code for tokens using PKCE verification
  • Upserts integration and connection records with proper composite key
  • Calculates token expiry from expires_in
  • Stores refresh token when provided
  • Sets connection to active state
  • Logs completion with relevant context

395-460: LGTM overall! Token refresh is correctly implemented.

The function properly:

  • Validates the connection has a refresh token
  • Uses MCP SDK's refreshAuthorization
  • Updates tokens in the database
  • Preserves refresh token if not returned in response
  • Logs success with context

466-507: LGTM! Token validation and refresh logic is correct.

This centralized token management function properly:

  • Validates the connection exists and has a token
  • Checks expiry and refreshes when needed
  • Provides clear error messages for missing credentials
  • Returns a valid access token

This avoids the race condition issues that were present in earlier distributed token management code.


514-526: LGTM! OAuth server URL normalization is correct.

The helper correctly handles the standard MCP pattern where OAuth discovery endpoints are at the base URL and the MCP protocol endpoint is at /mcp. The logic is simple and well-documented.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/utils/mcp/oauth.ts (1)

534-546: Consider validating serverUrl format.

The logic correctly handles the common pattern where OAuth discovery is at the base URL when MCP protocol is at /mcp. However, if serverUrl is exactly "/mcp" or malformed, slice(0, -4) would return an empty or invalid URL that would fail in discovery.

This edge case is unlikely if serverUrl is properly validated at configuration time, but you could add a validation check:

 function getOAuthServerUrl(
   integrationConfig: ReturnType<typeof getIntegration>,
 ): string {
   const serverUrl = integrationConfig.serverUrl || "";
+
+  // Validate serverUrl is not just "/mcp"
+  if (serverUrl === "/mcp") {
+    throw new Error("Invalid server URL: cannot be just '/mcp'");
+  }
 
   // If serverUrl ends with /mcp, OAuth discovery is at the base URL
   // This is the standard pattern: OAuth at https://mcp.example.com, MCP protocol at https://mcp.example.com/mcp
   if (serverUrl.endsWith("/mcp")) {
     return serverUrl.slice(0, -4);
   }
 
   return serverUrl;
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c016c7 and 4023afe.

📒 Files selected for processing (2)
  • apps/web/utils/mcp/oauth.ts (1 hunks)
  • version.txt (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • version.txt
🧰 Additional context used
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/mcp/oauth.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/mcp/oauth.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/mcp/oauth.ts
🧬 Code graph analysis (1)
apps/web/utils/mcp/oauth.ts (2)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (3)
  • IntegrationKey (177-177)
  • getIntegration (179-187)
  • getStaticCredentials (193-210)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: Jit Security
🔇 Additional comments (11)
apps/web/utils/mcp/oauth.ts (11)

1-20: LGTM!

Imports are well-organized and follow project conventions. Logger initialization correctly uses createScopedLogger at the top level.


26-71: LGTM!

OAuth URL generation with PKCE is correctly implemented. The function properly validates required configuration, uses the MCP SDK's startAuthorization, and returns the necessary state for completing the flow.


77-151: LGTM!

OAuth callback handling correctly exchanges the authorization code for tokens and persists them with proper expiration tracking. The upsert pattern ensures idempotent connection updates.


157-198: LGTM!

Token retrieval logic correctly handles expiration and automatic refresh. Error messages clearly guide users on reconnection requirements.


204-268: LGTM!

Token refresh logic is correctly implemented with proper fallback handling for refresh token persistence and expiration calculation.


275-390: LGTM!

OAuth metadata discovery correctly implements RFC 8414/9728 with intelligent caching, optional protected resource metadata, and static fallback. The implementation aligns with MCP SDK 1.18.2 improvements for pathful resource servers.


396-478: LGTM!

OAuth client credential resolution follows a sensible three-tier strategy. Dynamic client registration correctly implements public client with PKCE pattern, and the implementation aligns with MCP SDK 1.18.2 redirect URI handling improvements.


480-495: LGTM!

Helper function correctly implements the upsert pattern for integration records.


497-515: LGTM!

Metadata creation helper correctly constructs AuthorizationServerMetadata with appropriate OAuth 2.0 and PKCE capabilities.


517-524: LGTM!

Token expiration calculation correctly converts seconds to a future Date. The edge case of expiresIn: 0 would fall back to the provided date, but this is acceptable as OAuth servers don't typically issue zero-second tokens.


526-532: LGTM!

Simple wrapper providing a cleaner interface for metadata discovery.

When OAuth providers don't return expires_in, use a conservative 1-hour
default instead of falling back to the old token's expiry date. Add
warning logs for observability.
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (6)
apps/web/utils/ai/mcp/mcp-tools.ts (6)

31-33: Remove redundant emailAccountId selection.

The emailAccountId is already provided as a function parameter (line 16), so selecting it again from the database (line 33) is unnecessary and adds overhead to the query result.

Apply this diff to remove the redundant selection:

       select: {
         id: true,
-        emailAccountId: true,
         accessToken: true,

72-77: Remove unreachable null check.

According to the getIntegration implementation in /apps/web/utils/mcp/integrations.ts (lines 178-186), the function throws an error if the integration is not found. Therefore, the null check on line 72 is unreachable and the warning on lines 73-75 will never execute.

Apply this diff to remove the dead code:

       const integrationConfig = getIntegration(integration.name);
 
-      if (!integrationConfig) {
-        logger.warn("Integration config not found", {
-          integration: integration.name,
-        });
-        continue;
-      }
-
       // Use registered server URL if available, otherwise fall back to config

Or wrap the getIntegration call in a try-catch if you want to handle the error gracefully:

+      let integrationConfig;
+      try {
+        integrationConfig = getIntegration(integration.name);
+      } catch (error) {
+        logger.warn("Integration config not found", {
+          integration: integration.name,
+          error,
+        });
+        continue;
+      }
-      const integrationConfig = getIntegration(integration.name);
-
-      if (!integrationConfig) {
-        logger.warn("Integration config not found", {
-          integration: integration.name,
-        });
-        continue;
-      }

106-110: Consider using warn instead of error for recoverable auth type issues.

Since the code continues processing other integrations after encountering an unknown auth type, using logger.warn would be more appropriate than logger.error. This aligns with the pattern used elsewhere in the function for recoverable issues (e.g., lines 73, 83, 99).

Apply this diff:

         } else {
-          logger.error("Unknown auth type", {
+          logger.warn("Unknown auth type", {
             integration: integration.name,

182-193: Consider using .values() to avoid unused destructured variables.

The use of _ and __ for unused map keys is idiomatic but can be avoided by using .values() iterator, which is more explicit about ignoring the keys.

Apply this diff:

   // Build a map of tool names to their integrations
-  for (const [_, { integrationName, tools }] of toolsByIntegration) {
+  for (const { integrationName, tools } of toolsByIntegration.values()) {
     for (const toolName of Object.keys(tools)) {

And similarly for the second loop:

   // Merge tools, prefixing only when there's a conflict
-  for (const [__, { integrationName, tools }] of toolsByIntegration) {
+  for (const { integrationName, tools } of toolsByIntegration.values()) {
     for (const [toolName, toolDef] of Object.entries(tools)) {

194-194: Remove non-null assertion to align with coding guidelines.

The coding guidelines prohibit non-null assertions. While the assertion is safe here (the key was just added in the first loop), you can use optional chaining with a fallback to follow the guidelines.

As per coding guidelines

Apply this diff:

       const integrationsWithThisTool = toolNameToIntegrations.get(toolName)!;
+      const integrationsWithThisTool = toolNameToIntegrations.get(toolName) ?? [];
+      if (integrationsWithThisTool.length === 0) continue;

Or assert the type without runtime nullability:

-      const integrationsWithThisTool = toolNameToIntegrations.get(toolName)!;
+      const integrationsWithThisTool = toolNameToIntegrations.get(toolName);
+      if (!integrationsWithThisTool) continue; // Should never happen

187-187: Remove non-null assertion to align with coding guidelines.

Similar to line 194, this non-null assertion should be replaced with a safer pattern per coding guidelines.

As per coding guidelines

Apply this diff:

-      toolNameToIntegrations.get(toolName)!.push(integrationName);
+      const integrations = toolNameToIntegrations.get(toolName) ?? [];
+      integrations.push(integrationName);
+      toolNameToIntegrations.set(toolName, integrations);

Or use a single expression:

-      toolNameToIntegrations.get(toolName)!.push(integrationName);
+      const existing = toolNameToIntegrations.get(toolName);
+      if (existing) {
+        existing.push(integrationName);
+      }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 33316ff and c608ffc.

📒 Files selected for processing (1)
  • apps/web/utils/ai/mcp/mcp-tools.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (10)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/ai/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
🧬 Code graph analysis (1)
apps/web/utils/ai/mcp/mcp-tools.ts (4)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (1)
  • getIntegration (179-187)
apps/web/utils/mcp/oauth.ts (1)
  • getValidAccessToken (164-205)
apps/web/utils/mcp/transport.ts (1)
  • createMcpTransport (3-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Static Code Analysis Js
  • GitHub Check: Jit Security
🔇 Additional comments (3)
apps/web/utils/ai/mcp/mcp-tools.ts (3)

1-13: LGTM!

The imports and type definitions are clean and follow project conventions. The use of createScopedLogger aligns with the coding guidelines, and the MCPToolsResult type clearly defines the contract for this module.


113-138: LGTM!

The MCP client creation and tool filtering logic is well-structured. The separation of concerns (transport creation, client management, tool filtering) is clean, and the error handling appropriately continues with other integrations on failure.


141-163: LGTM!

The tool merging and cleanup logic is well-implemented. The cleanup function properly handles client closure with error tolerance, and the outer error handling defensively returns an empty result rather than propagating errors, which is appropriate for this use case.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/web/utils/mcp/oauth.ts (1)

184-195: Add buffer time to token expiration check.

The expiration check at line 185 tests connection.expiresAt < now, which can lead to race conditions where the token expires between the check and actual use. Industry best practice is to refresh tokens a few minutes before actual expiry.

Apply this diff to add a 5-minute buffer:

+  // Refresh 5 minutes before actual expiry to avoid race conditions
+  const REFRESH_BUFFER_MS = 5 * 60 * 1000;
   const now = new Date();
-  const isExpired = connection.expiresAt && connection.expiresAt < now;
+  const isExpired = connection.expiresAt && 
+    connection.expiresAt.getTime() - REFRESH_BUFFER_MS < now.getTime();
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c608ffc and 91814b1.

📒 Files selected for processing (1)
  • apps/web/utils/mcp/oauth.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/mcp/oauth.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/mcp/oauth.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/mcp/oauth.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/mcp/oauth.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/mcp/oauth.ts
🧬 Code graph analysis (1)
apps/web/utils/mcp/oauth.ts (2)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (3)
  • IntegrationKey (177-177)
  • getIntegration (179-187)
  • getStaticCredentials (189-201)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Jit Security
🔇 Additional comments (10)
apps/web/utils/mcp/oauth.ts (10)

1-24: LGTM!

Imports follow project conventions, logger is properly initialized at the top level, and the conservative 1-hour default token expiry is appropriate for proactive refresh.


30-75: LGTM!

The PKCE OAuth flow implementation is correct, with proper error handling for missing configuration. The logging now correctly omits sensitive query parameters, addressing the previous review concern.


210-273: LGTM!

Token refresh logic correctly preserves the existing refresh token (line 262) when the provider doesn't return a new one, which is the right approach for OAuth providers that only return access tokens during refresh.


280-395: LGTM!

OAuth metadata discovery implements RFC 8414/9728 correctly with proper caching, optional protected resource metadata handling, and fallback to static configuration. The cache validation ensures serverUrl consistency.


401-483: LGTM!

OAuth client credential resolution correctly prioritizes static credentials, then stored credentials, then dynamic registration. The PKCE public client configuration is appropriate.


485-500: LGTM!

Helper function correctly implements upsert semantics for MCP integration metadata.


502-520: LGTM!

Helper function correctly constructs authorization server metadata with appropriate OAuth 2.0 PKCE configuration values.


522-541: LGTM!

Token expiration calculation correctly converts OAuth expires_in from seconds to milliseconds and applies a conservative default when the provider omits it.


543-549: LGTM!

Helper function provides a clean abstraction for metadata discovery.


551-563: LGTM!

Helper function correctly strips the /mcp suffix to obtain the OAuth discovery base URL, following the standard MCP server URL pattern.

@socket-security
Copy link

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
safer-buffer@2.1.2 has Obfuscated code.

Confidence: 0.94

Location: Package overview

From: pnpm-lock.yamlnpm/encoding@0.1.13npm/safer-buffer@2.1.2

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/safer-buffer@2.1.2. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/web/utils/mcp/list-tools.ts (1)

44-48: Preserve original error details when rethrowing

Wrapping the caught error in a brand‑new Error drops the stack trace and type info, which makes downstream debugging harder. Either rethrow the original error or attach it as a cause so the full context survives.

-    throw new Error(
-      `Failed to list tools: ${error instanceof Error ? error.message : "Unknown error"}`,
-    );
+    throw new Error("Failed to list tools", {
+      cause: error,
+    });
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 91814b1 and e3ca87f.

📒 Files selected for processing (5)
  • apps/web/utils/ai/digest/summarize-email-for-digest.ts (2 hunks)
  • apps/web/utils/ai/mcp/mcp-tools.ts (1 hunks)
  • apps/web/utils/mcp/list-tools.ts (1 hunks)
  • apps/web/utils/mcp/oauth.ts (1 hunks)
  • apps/web/utils/mcp/sync-tools.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/utils/ai/digest/summarize-email-for-digest.ts
  • apps/web/utils/mcp/sync-tools.ts
🧰 Additional context used
📓 Path-based instructions (10)
apps/web/**/*.{ts,tsx}

📄 CodeRabbit inference engine (apps/web/CLAUDE.md)

apps/web/**/*.{ts,tsx}: Use TypeScript with strict null checks
Path aliases: Use @/ for imports from project root
Use proper error handling with try/catch blocks
Format code with Prettier
Leverage TypeScript inference for better DX

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
!{.cursor/rules/*.mdc}

📄 CodeRabbit inference engine (.cursor/rules/cursor-rules.mdc)

Never place rule files in the project root, in subdirectories outside .cursor/rules, or in any other location

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/form-handling.mdc)

**/*.ts: The same validation should be done in the server action too
Define validation schemas using Zod

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/logging.mdc)

**/*.{ts,tsx}: Use createScopedLogger for logging in backend TypeScript files
Typically add the logger initialization at the top of the file when using createScopedLogger
Only use .with() on a logger instance within a specific function, not for a global logger

Import Prisma in the project using import prisma from "@/utils/prisma";

**/*.{ts,tsx}: Don't use TypeScript enums.
Don't use TypeScript const enum.
Don't use the TypeScript directive @ts-ignore.
Don't use primitive type aliases or misleading types.
Don't use empty type parameters in type aliases and interfaces.
Don't use any or unknown as type constraints.
Don't use implicit any type on variable declarations.
Don't let variables evolve into any type through reassignments.
Don't use non-null assertions with the ! postfix operator.
Don't misuse the non-null assertion operator (!) in TypeScript files.
Don't use user-defined types.
Use as const instead of literal types and type annotations.
Use export type for types.
Use import type for types.
Don't declare empty interfaces.
Don't merge interfaces and classes unsafely.
Don't use overload signatures that aren't next to each other.
Use the namespace keyword instead of the module keyword to declare TypeScript namespaces.
Don't use TypeScript namespaces.
Don't export imported variables.
Don't add type annotations to variables, parameters, and class properties that are initialized with literal expressions.
Don't use parameter properties in class constructors.
Use either T[] or Array consistently.
Initialize each enum member value explicitly.
Make sure all enum members are literal values.

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/**

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

Create utility functions in utils/ folder for reusable logic

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/project-structure.mdc)

apps/web/utils/**/*.ts: Use lodash utilities for common operations (arrays, objects, strings)
Import specific lodash functions to minimize bundle size

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

**/*.{js,jsx,ts,tsx}: Don't use elements in Next.js projects.
Don't use elements in Next.js projects.
Don't use namespace imports.
Don't access namespace imports dynamically.
Don't use global eval().
Don't use console.
Don't use debugger.
Don't use var.
Don't use with statements in non-strict contexts.
Don't use the arguments object.
Don't use consecutive spaces in regular expression literals.
Don't use the comma operator.
Don't use unnecessary boolean casts.
Don't use unnecessary callbacks with flatMap.
Use for...of statements instead of Array.forEach.
Don't create classes that only have static members (like a static namespace).
Don't use this and super in static contexts.
Don't use unnecessary catch clauses.
Don't use unnecessary constructors.
Don't use unnecessary continue statements.
Don't export empty modules that don't change anything.
Don't use unnecessary escape sequences in regular expression literals.
Don't use unnecessary labels.
Don't use unnecessary nested block statements.
Don't rename imports, exports, and destructured assignments to the same name.
Don't use unnecessary string or template literal concatenation.
Don't use String.raw in template literals when there are no escape sequences.
Don't use useless case statements in switch statements.
Don't use ternary operators when simpler alternatives exist.
Don't use useless this aliasing.
Don't initialize variables to undefined.
Don't use the void operators (they're not familiar).
Use arrow functions instead of function expressions.
Use Date.now() to get milliseconds since the Unix Epoch.
Use .flatMap() instead of map().flat() when possible.
Use literal property access instead of computed property access.
Don't use parseInt() or Number.parseInt() when binary, octal, or hexadecimal literals work.
Use concise optional chaining instead of chained logical expressions.
Use regular expression literals instead of the RegExp constructor when possible.
Don't use number literal object member names th...

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
!pages/_document.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ultracite.mdc)

!pages/_document.{js,jsx,ts,tsx}: Don't import next/document outside of pages/_document.jsx in Next.js projects.
Don't import next/document outside of pages/_document.jsx in Next.js projects.

Files:

  • apps/web/utils/mcp/list-tools.ts
  • apps/web/utils/mcp/oauth.ts
  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/ai/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

apps/web/utils/ai/**/*.{ts,tsx}: Place main LLM feature implementations under apps/web/utils/ai/
LLM feature functions should follow the provided TypeScript pattern (separate system/user prompts, use createGenerateObject, Zod schema validation, early validation, return result.object)
Keep system prompts and user prompts separate
System prompt should define the LLM's role and task specifications
User prompt should contain the actual data and context
Always define a Zod schema for response validation
Make Zod schemas as specific as possible to guide LLM output
Use descriptive scoped loggers for each feature
Log inputs and outputs with appropriate log levels and include relevant context
Implement early returns for invalid inputs
Use proper error types and logging for failures
Implement fallbacks for AI failures
Add retry logic for transient failures using withRetry
Use XML-like tags to structure data in prompts
Remove excessive whitespace and truncate long inputs in prompts
Format prompt data consistently across similar functions
Use TypeScript types for all parameters and return values in LLM features
Define clear interfaces for complex input/output structures in LLM features

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
apps/web/utils/{ai,llms}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/llm.mdc)

Keep related AI functions co-located and extract common patterns into utilities; document complex AI logic with clear comments

Files:

  • apps/web/utils/ai/mcp/mcp-tools.ts
🧬 Code graph analysis (3)
apps/web/utils/mcp/list-tools.ts (4)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (2)
  • IntegrationKey (177-177)
  • getIntegration (179-187)
apps/web/utils/mcp/oauth.ts (1)
  • getAuthToken (163-195)
apps/web/utils/mcp/transport.ts (1)
  • createMcpTransport (3-15)
apps/web/utils/mcp/oauth.ts (2)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (3)
  • IntegrationKey (177-177)
  • getIntegration (179-187)
  • getStaticCredentials (189-201)
apps/web/utils/ai/mcp/mcp-tools.ts (4)
apps/web/utils/logger.ts (1)
  • createScopedLogger (17-80)
apps/web/utils/mcp/integrations.ts (1)
  • getIntegration (179-187)
apps/web/utils/mcp/oauth.ts (1)
  • getAuthToken (163-195)
apps/web/utils/mcp/transport.ts (1)
  • createMcpTransport (3-15)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Software Component Analysis Js
  • GitHub Check: Jit Security

@elie222 elie222 merged commit e3a04ec into main Oct 2, 2025
12 of 14 checks passed
@elie222 elie222 deleted the cursor/implement-mcp-integration-system-cc46 branch December 18, 2025 23:00
@coderabbitai coderabbitai bot mentioned this pull request Dec 19, 2025
@coderabbitai coderabbitai bot mentioned this pull request Dec 27, 2025
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

Comments