Skip to content

Conversation

@batmn-dev
Copy link
Owner

@batmn-dev batmn-dev commented Feb 9, 2026

Summary

  • MCP (Model Context Protocol) integration: Full end-to-end implementation including Convex schema & functions (mcpServers, mcpToolApprovals, mcpToolCallLog), server-side tool loading with circuit breaker pattern, SSRF URL validation, result truncation, audit logging, and a settings UI for managing MCP servers and tool approvals
  • Model catalog refresh: Added GPT-5.1, Gemini 3 Pro preview, Codestral, O3/O4-mini; removed deprecated Gemini, Claude, and Llama models; updated defaults and curated the catalog
  • Multi-chat improvements: Fixed message persistence so history survives navigation, deduplicated assistant messages by model in multi-chat groups, stabilized component keys, and fixed OpenRouter model grouping
  • UI/UX polish: Simplified sidebar list with improved collapsible chevron behavior, cleaned up user menu (removed app info dialog, updated settings icon), and centralized file picker accept types
  • Infrastructure: Added vitest config, MCP test suite (circuit breaker, tool loading, URL validation, truncation), and planning docs for cross-conversation memory

Key Changes

MCP Integration

  • convex/schema.ts — New tables for MCP servers, tool approvals, and call logs
  • convex/mcpServers.ts, convex/mcpToolApprovals.ts, convex/mcpToolCallLog.ts — CRUD + auth
  • lib/mcp/load-tools.ts — Server-side tool discovery with caching and circuit breaker
  • lib/mcp/circuit-breaker.ts, lib/mcp/url-validation.ts, lib/mcp/truncation.ts — Safety layers
  • app/api/mcp-servers/ — REST endpoints for server management
  • app/api/chat/route.ts — MCP tool injection into chat stream
  • Settings UI: mcp-server-form.tsx, mcp-servers.tsx, mcp-tool-approvals.tsx

Model Catalog

  • lib/models/data/openai.ts, gemini.ts, claude.ts, mistral.ts, openrouter.ts — Updated
  • lib/models/types.ts — Added reasoningModel flag

Multi-Chat

  • app/components/multi-chat/multi-chat.tsx — Persistence + deduplication
  • lib/chat-store/messages/provider.tsx — Message store fixes

Test Plan

  • Verify MCP server CRUD in settings UI (add, edit, delete, test connection)
  • Verify MCP tools load and execute in chat with approved servers
  • Verify circuit breaker trips after repeated failures and resets
  • Verify multi-chat messages persist across navigation
  • Verify no duplicate assistant messages in multi-chat groups
  • Verify updated model catalog shows correct models in model picker
  • Run bun run lint and bun run typecheck pass
  • Run bun run test for MCP test suite

Made with Cursor


Summary by cubic

Integrates MCP tools into chat with secure server management and approvals, refreshes the model catalog, and stabilizes multi‑chat with lifecycle‑managed submissions, server‑side idempotency, and safer URL validation. Adds a settings UI, tests, and a feature flag; now also clears live messages after persistence to stop duplicate groups and blocks CGNAT ranges in SSRF checks.

  • New Features

    • MCP integration: Convex tables + API routes, settings UI for servers and tool approvals, tool injection in chat, circuit breaker, IPv4/IPv6/CGNAT SSRF + DNS‑rebinding validation, runtime tool shape validation, result truncation, audit logging, client cleanup on timeout, and ENABLE_MCP kill‑switch.
    • Model catalog: added GPT‑5.1, Gemini 3 Pro, Codestral, O3/O4‑mini; removed deprecated Gemini/Claude/Llama entries; default model now gpt‑5‑mini; OpenRouter models grouped in their own settings section.
    • Infra/tests: Vitest setup and suite covering circuit breaker, tool loading, IPv4/IPv6/CGNAT URL validation + rebinding, truncation; pin @ai-sdk/mcp to 1.0.18; transport spike script; disable Turbopack persistent SST cache in dev.
  • Bug Fixes

    • Multi‑chat: lifecycle‑managed submission registry with per‑model tracking, server‑side idempotency to prevent duplicate inserts, clear live useChat messages after persistence, three‑tier group key fallback (registry → persisted reverse lookup → raw text), persist history across navigation, stop active streams on chat switches, handle disconnects, dedupe assistant messages by model, stable keys, merge live and stored messages by group.
    • UI/UX: simpler sidebar chevron behavior, cleaned user menu (removed app info; new settings icon), centralized file picker accept types including WebP.

Written for commit bd85e09. Summary will update on new commits.

batmn-dev and others added 15 commits February 7, 2026 17:07
Derive ACCEPTED_FILE_PICKER_TYPES from ALLOWED_FILE_TYPES so the
file picker and validation logic stay in sync. Also adds MCP
integration and cross-conversation memory planning documents.

Co-authored-by: Cursor <cursoragent@cursor.com>
Scaffold the MCP (Model Context Protocol) integration layer:
- Add mcpServers, mcpToolApprovals, mcpToolCallLog tables to Convex schema
- Create Convex query/mutation functions for MCP server management
- Add MCP constants to lib/config (limits, timeouts, circuit breaker)
- Add ENABLE_MCP env flag as instant kill-switch
- Pin @ai-sdk/mcp to exact version 1.0.18
- Include transport spike script and updated integration plan

Co-authored-by: Cursor <cursoragent@cursor.com>
…espacing

- Enhanced loadMCPToolsFromURL with dual transport support (HTTP/SSE), optional
  auth headers, and client reference return for lifecycle management
- Added loadUserMcpTools orchestrator that loads enabled servers in parallel,
  namespaces tools, filters by approval status, and enforces per-request limits
- Includes encrypted auth decryption (AES-256-GCM) and connection status tracking

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Wire MCP tools into the chat streaming pipeline with auth gating,
feature flag, and proper client cleanup. Add MCP server CRUD API
routes and settings UI for managing connections and tool approvals.

Co-authored-by: Cursor <cursoragent@cursor.com>
…nd observability

Add circuit breaker to skip MCP servers with consecutive failures, URL
validation to block private/localhost endpoints (SSRF protection), and
tool result truncation to prevent oversized payloads. Wire PostHog events
for mcp_tool_load and mcp_tool_call for production observability.

Includes Vitest setup and tests for all new modules.

Co-authored-by: Cursor <cursoragent@cursor.com>
…pdate defaults

- Add GPT-5.1 Instant and GPT-5.1 Thinking models with provider mappings
- Remove deprecated models: GPT-3.5 Turbo, GPT-4 Turbo, GPT-4.1 Mini/Nano,
  GPT-4o Mini, o1, o3-mini, Claude 3 Haiku, Claude Opus 4
- Update default model from gpt-4.1-nano to gpt-5-mini
- Add turbopackFileSystemCacheForDev comments in next.config.ts
- Clarify SST cache troubleshooting docs (preventive vs active fix)
- Add dev:clean command to AGENTS.md

Co-authored-by: Cursor <cursoragent@cursor.com>
Set ENABLE_MCP=true in .env.example and drop 5 deprecated Gemini 1.5/2.0
models from the catalog, keeping only the latest 2.5 generation.

Co-authored-by: Cursor <cursoragent@cursor.com>
…atalog

MCP improvements:
- Add fire-and-forget audit logging for MCP tool calls to Convex
- Track failedServerCount (connection failures + circuit breaker skips)
- Add proper HTTP 500 status to MCP test endpoint errors
- Add console.error in catch blocks across MCP UI components
- Add explanatory comment for MCPToolSet type cast escape hatch

Model catalog updates:
- Promote Gemini 3 Pro from preview to GA
- Update OpenRouter Gemini 2.5 Pro/Flash to GA model IDs
- Remove "preview" tag from o4-mini
- Remove deprecated GPT-4.5 Preview from OpenRouter

Co-authored-by: Cursor <cursoragent@cursor.com>
…s icon

Remove the AppInfoTrigger component and simplify the user menu dropdown
by showing only email. Switch settings icon from User02Icon to Settings01Icon.

Co-authored-by: Cursor <cursoragent@cursor.com>
…/O4-mini

- Rename gemini-3-pro to gemini-3-pro-preview to match actual API model ID
- Update Codestral from open-mistral-7b to codestral-latest with correct pricing and metadata
- Add missing OpenAI model types (o3, o4-mini variants)
- Add codestral-latest to provider map and MistralModel type

Co-authored-by: Cursor <cursoragent@cursor.com>
Remove unused icon/collapsible props from SidebarList, always delegate
to CollapsibleSection. Update chevron visibility so collapsed sections
show the arrow at full opacity and expanded sections reveal it on hover.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add messageGroupId-based grouping and cacheAndAddMessage calls for both
user and assistant messages in multi-chat. Use refs to avoid stale
closures in onFinish callbacks, and extend ExtendedUIMessage with model
and messageGroupId fields to remove unsafe type assertions.

Co-authored-by: Cursor <cursoragent@cursor.com>
…atalog update

- Group OpenRouter models in their own settings section with underlying
  provider icons and "via" labels instead of mixing with direct providers
- Fix multi-chat message grouping so live useChat messages merge with
  persisted messages using text→groupId mapping
- Fix React key uniqueness in multi-conversation response cards
- Remove standalone Llama/Groq model definitions (available via OpenRouter)
- Expand OpenRouter types: Claude Sonnet 4, Gemini 2.5, Perplexity Sonar
  family, GPT-4.1 variants, Llama 3.3 free

Co-authored-by: Cursor <cursoragent@cursor.com>
Prevent the same model's response from being added multiple times to a
message group, both in the primary messageGroupId path and the fallback
scan-backward path.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel
Copy link

vercel bot commented Feb 9, 2026

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

Project Deployment Actions Updated (UTC)
not-a-wrapper Ready Ready Preview, Comment Feb 9, 2026 4:27am

@greptile-apps
Copy link

greptile-apps bot commented Feb 9, 2026

Greptile Overview

Greptile Summary

This PR delivers a comprehensive MCP integration, model catalog refresh, and critical multi-chat fixes. The implementation follows solid patterns with defense-in-depth security layers (SSRF validation, circuit breaker, result truncation), proper encryption for auth credentials, and extensive test coverage.

Key changes:

  • MCP Integration: Full end-to-end implementation with Convex schema, server-side tool loading, circuit breaker pattern, URL validation, audit logging, and settings UI
  • Multi-chat persistence: Messages now persist across navigation using UUID-based grouping and model-based deduplication to prevent duplicate assistant responses
  • Model catalog refresh: Added GPT-5.1 variants, Gemini 3 Pro preview, Codestral, O3/O4-mini; removed deprecated models
  • Default model change: Updated from gpt-4.1-nano to gpt-5-mini

Notable strengths:

  • Circuit breaker prevents repeated failures from blocking all requests
  • SSRF validation blocks private IPs and localhost at both API and database layers
  • Tool result truncation with proper multi-byte character handling
  • Comprehensive test suite for security-critical components
  • MCP client cleanup handlers in both success and error paths

Areas for attention:

  • MCP client cleanup in app/api/chat/route.ts uses after() which may not complete if serverless function terminates early
  • Multi-chat textToGroupIdRef map grows unbounded (potential memory leak in long sessions)
  • DNS rebinding attacks not prevented by current SSRF validation
  • PostHog analytics only capture successful tool calls, not failures

Confidence Score: 4/5

  • Safe to merge with minor cleanup considerations for production scale
  • Score reflects well-architected MCP integration with strong security layers, comprehensive tests, and proper error handling. Deducted one point for potential resource cleanup issues in serverless edge cases (MCP client lifecycle with after()) and unbounded memory growth in multi-chat sessions. These are optimization concerns rather than critical bugs, but should be addressed before heavy production use.
  • Pay close attention to app/api/chat/route.ts for MCP client cleanup logic and app/components/multi-chat/multi-chat.tsx for memory management in the textToGroupIdRef map

Important Files Changed

Filename Overview
lib/mcp/load-tools.ts Implements server-side MCP tool loading with circuit breaker, timeout handling, and approval filtering. Well-structured with comprehensive error handling and observability updates.
lib/mcp/circuit-breaker.ts Clean circuit breaker implementation for tracking MCP server failures. Simple in-memory state management appropriate for serverless environment.
lib/mcp/url-validation.ts SSRF protection validation function. Blocks private IPs and localhost. Validation logic duplicated in convex/mcpServers.ts (documented).
convex/schema.ts Added three MCP tables with proper indexes and auth field encryption support. Schema design follows existing patterns.
convex/mcpServers.ts CRUD operations for MCP servers with SSRF validation, auth enforcement, and ownership checks. Follows Convex auth patterns correctly.
app/api/chat/route.ts Integrated MCP tool loading into chat route with cleanup handlers, PostHog analytics, and audit logging. Complex but properly gated. Found potential memory leak issue.
app/components/multi-chat/multi-chat.tsx Implemented message persistence with UUID-based grouping to survive navigation. Deduplication logic prevents duplicate assistant messages by model ID.
lib/config.ts Added MCP configuration constants. Changed default model from gpt-4.1-nano to gpt-5-mini.

Sequence Diagram

sequenceDiagram
    participant User
    participant ChatRoute as /api/chat
    participant LoadTools as loadUserMcpTools()
    participant Convex
    participant MCPServer as MCP Server
    participant CircuitBreaker
    participant StreamText as streamText()
    
    User->>ChatRoute: POST chat request
    ChatRoute->>Convex: Fetch enabled MCP servers + approvals
    Convex-->>ChatRoute: Server configs
    
    ChatRoute->>LoadTools: Load MCP tools
    LoadTools->>CircuitBreaker: Check circuit status
    CircuitBreaker-->>LoadTools: Circuit closed (healthy)
    
    par Connect to MCP Servers
        LoadTools->>MCPServer: createMCPClient() with timeout
        MCPServer-->>LoadTools: Client + tools
        LoadTools->>CircuitBreaker: recordSuccess()
    end
    
    LoadTools->>LoadTools: Filter by approvals, namespace tools
    LoadTools-->>ChatRoute: Merged tools + clients
    
    ChatRoute->>StreamText: streamText(model, tools)
    
    par Streaming Response
        StreamText->>MCPServer: Execute tool calls
        MCPServer-->>StreamText: Tool results
        StreamText-->>User: Stream AI response
    end
    
    StreamText->>ChatRoute: onFinish callback
    ChatRoute->>Convex: Log tool calls to mcpToolCallLog
    ChatRoute->>ChatRoute: after() cleanup
    ChatRoute->>LoadTools: Close MCP clients
    LoadTools->>MCPServer: client.close()
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

8 files reviewed, 9 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +44 to +45
// MCP state — declared outside try for cleanup in both after() and catch
let mcpClients: LoadToolsResult["clients"] = []
Copy link

Choose a reason for hiding this comment

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

MCP state declared outside try block but mcpClients may contain open connections if an error occurs after loadUserMcpTools but before streaming starts. The catch block closes them, but if error occurs before catch (e.g., during model creation), connections remain open.

Suggested change
// MCP state — declared outside try for cleanup in both after() and catch
let mcpClients: LoadToolsResult["clients"] = []
try {
// MCP state — cleanup handled in both after() and catch
let mcpClients: LoadToolsResult["clients"] = []
let mcpToolServerMap: LoadToolsResult["toolServerMap"] = new Map()
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/api/chat/route.ts
Line: 44:45

Comment:
MCP state declared outside try block but mcpClients may contain open connections if an error occurs after `loadUserMcpTools` but before streaming starts. The catch block closes them, but if error occurs before catch (e.g., during model creation), connections remain open.

```suggestion
  try {
    // MCP state — cleanup handled in both after() and catch
    let mcpClients: LoadToolsResult["clients"] = []
    let mcpToolServerMap: LoadToolsResult["toolServerMap"] = new Map()
```

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +237 to +242
// -------------------------------------------------------------------------
// 4. Collect tools from successful clients
// -------------------------------------------------------------------------
const clients: MCPClient[] = []
// MCPToolSet is an opaque mapped type from @ai-sdk/mcp that does not expose a
// mutable builder interface. We accumulate tools as Record<string, unknown> and
Copy link

Choose a reason for hiding this comment

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

Type safety issue: mergedTools is built as Record<string, unknown> then cast to MCPToolSet. While this works, consider using type guards or asserting tool descriptor shape before insertion to catch SDK type changes at runtime.

The comment explains why this pattern is necessary (opaque mapped type), but runtime validation would add safety.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/mcp/load-tools.ts
Line: 237:242

Comment:
Type safety issue: `mergedTools` is built as `Record<string, unknown>` then cast to `MCPToolSet`. While this works, consider using type guards or asserting tool descriptor shape before insertion to catch SDK type changes at runtime.

The comment explains why this pattern is necessary (opaque mapped type), but runtime validation would add safety.

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

export const DAILY_LIMIT_PRO_MODELS = 500

export const NON_AUTH_ALLOWED_MODELS = ["gpt-4.1-nano"]
export const NON_AUTH_ALLOWED_MODELS = ["gpt-5-mini"]
Copy link

Choose a reason for hiding this comment

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

Changed default from gpt-4.1-nano to gpt-5-mini. Verify the new model ID exists in your OpenAI provider configuration and is available to all users.

Prompt To Fix With AI
This is a comment left during a code review.
Path: lib/config.ts
Line: 26:26

Comment:
Changed default from `gpt-4.1-nano` to `gpt-5-mini`. Verify the new model ID exists in your OpenAI provider configuration and is available to all users.

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +124 to +126
name: v.string(),
url: v.string(),
transport: v.union(v.literal("http"), v.literal("sse")),
Copy link

Choose a reason for hiding this comment

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

Auth fields use optional encryption. Validation logic in mcpServers.create/update enforces that when authType is "bearer" or "header", these fields are required (verified at convex/mcpServers.ts:167-178).

Prompt To Fix With AI
This is a comment left during a code review.
Path: convex/schema.ts
Line: 124:126

Comment:
Auth fields use optional encryption. Validation logic in `mcpServers.create/update` enforces that when `authType` is "bearer" or "header", these fields are required (verified at convex/mcpServers.ts:167-178).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines 264 to 287
// PostHog: MCP tool call events — one event per tool invocation
// Iterates through all steps to find tool calls that map to MCP tools.
// durationMs per tool call requires wrapping tool.execute (future enhancement).
if (steps && mcpToolServerMap.size > 0) {
for (const step of steps) {
if (step.toolCalls) {
for (const toolCall of step.toolCalls) {
const serverInfo = mcpToolServerMap.get(toolCall.toolName)
if (serverInfo) {
phClient.capture({
distinctId: userId,
event: "mcp_tool_call",
properties: {
toolName: serverInfo.displayName,
serverName: serverInfo.serverName,
serverId: serverInfo.serverId,
namespacedToolName: toolCall.toolName,
success: true,
chatId,
},
})
}
}
}
Copy link

Choose a reason for hiding this comment

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

PostHog MCP tool call events only capture successful executions. Failed tool calls won't appear in PostHog analytics (only in Convex audit log). Consider capturing both success and failure events.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/api/chat/route.ts
Line: 264:287

Comment:
PostHog MCP tool call events only capture successful executions. Failed tool calls won't appear in PostHog analytics (only in Convex audit log). Consider capturing both success and failure events.

<sub>Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!</sub>

How can I resolve this? If you propose a fix, please make it concise.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

9 issues found across 58 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="lib/mcp/truncation.ts">

<violation number="1" location="lib/mcp/truncation.ts:43">
P2: When maxSize is smaller than the truncation suffix, this returns a string larger than maxSize, breaking the size limit guarantee. Consider truncating the suffix to fit maxSize bytes instead of returning it unmodified.</violation>
</file>

<file name="app/components/multi-chat/multi-conversation.tsx">

<violation number="1" location="app/components/multi-chat/multi-conversation.tsx:199">
P2: `response.message` is optional in rendering (loading/placeholder branch), but the key now unconditionally dereferences `response.message.id`, which will throw when message is undefined. Use a safe fallback for the key when the response is loading.</violation>
</file>

<file name="lib/mcp/url-validation.ts">

<violation number="1" location="lib/mcp/url-validation.ts:28">
P1: SSRF bypass via IPv6 addresses: The validation only blocks `[::1]` but misses other IPv6 private/local addresses. Attackers can use `http://[::]`, `http://[::ffff:127.0.0.1]` (IPv4-mapped localhost), `http://[fe80::1]` (link-local), or `http://[fd00::1]` (unique local) to access internal services.</violation>
</file>

<file name="app/api/chat/route.ts">

<violation number="1" location="app/api/chat/route.ts:281">
P2: The `success: true` is hardcoded for PostHog analytics, which will produce inaccurate metrics. Tool executions can fail, and the result status should be checked. Consider deriving success from the presence and content of the corresponding `toolResult`.</violation>
</file>

<file name="lib/file-handling.ts">

<violation number="1" location="lib/file-handling.ts:49">
P2: The accept list includes image/webp/.webp but validation only allows ALLOWED_FILE_TYPES, so users can pick .webp files and then hit a validation error. Either add image/webp to ALLOWED_FILE_TYPES (and MIME_TO_EXTENSIONS) or remove it from the accept list to keep them in sync.</violation>
</file>

<file name="lib/mcp/load-tools.ts">

<violation number="1" location="lib/mcp/load-tools.ts:219">
P2: Resource leak when MCP connection times out. When `Promise.race` rejects due to timeout, the underlying `createMCPClient` promise continues running. If it eventually resolves, the client is never closed. Track the promise and clean up orphaned clients.</violation>
</file>

<file name="app/api/mcp-servers/route.ts">

<violation number="1" location="app/api/mcp-servers/route.ts:146">
P2: PATCH handler allows empty strings after trimming. Unlike POST which validates `!name?.trim()`, the PATCH handler accepts whitespace-only values that trim to empty strings. Add validation to reject empty trimmed values for required fields.</violation>
</file>

<file name="convex/mcpServers.ts">

<violation number="1" location="convex/mcpServers.ts:33">
P1: Incomplete IPv6 SSRF protection allows bypass via IPv4-mapped IPv6 addresses (e.g., `[::ffff:127.0.0.1]`), link-local (`fe80::*`), or unique local (`fc00::/fd00::`) ranges. Consider adding checks for these IPv6 private ranges.</violation>
</file>

<file name="app/components/multi-chat/use-multi-chat.ts">

<violation number="1" location="app/components/multi-chat/use-multi-chat.ts:38">
P2: Handle `isDisconnect` in the onFinish guard; otherwise a disconnect can trigger the success callback with a partial message.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…hat navigation

- Add IPv6 private range detection (loopback, link-local, unique-local,
  IPv4-mapped) to both lib/mcp/url-validation.ts and convex/mcpServers.ts
- Add DNS rebinding protection via validateResolvedUrl at connection time
- Add runtime tool shape validation and orphaned client cleanup on timeout
- Stop active streams on chat-to-chat navigation (single + multi-chat)
- Handle isDisconnect callback, improve multi-chat duplicate detection
- Move MCP client cleanup before potential throws, fix success tracking
- Add image/webp to allowed file types, fix truncation edge cases
- Add comprehensive test coverage for all changes

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 15 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="lib/mcp/url-validation.ts">

<violation number="1" location="lib/mcp/url-validation.ts:19">
P2: Missing CGNAT range (100.64.0.0/10) in SSRF protection. This RFC 6598 range is used by cloud providers for internal networking and should be blocked to prevent SSRF attacks in cloud environments.</violation>
</file>

<file name="convex/mcpServers.ts">

<violation number="1" location="convex/mcpServers.ts:102">
P3: Error message is inconsistent with `lib/mcp/url-validation.ts`. When blocking private IPv6 ranges like `fe80::/10` (link-local) or `fc00::/7` (unique-local), this returns "Localhost and local network URLs are not allowed" which is misleading. The lib version correctly returns "Private IPv6 addresses are not allowed". Since the comment says to keep both in sync, consider using the same error message.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

…y for multi-chat

Replace single shared messageGroupIdRef with per-model groupId tracking and a
lifecycle-managed submission registry. Entries are only cleaned up when ALL models
complete streaming, preventing premature bridge removal that caused duplicate
message groups. Add server-side idempotency guard in convex/messages.ts to reject
duplicate inserts from concurrent race conditions.

Co-authored-by: Cursor <cursoragent@cursor.com>
…GNAT detection

Clear useChat hook messages after persistence to prevent stale live messages
from producing duplicate groups alongside persisted ones. Add three-tier
group key fallback (submission registry → persisted reverse lookup → raw text).

Also block CGNAT range (100.64.0.0/10, RFC 6598) in both server and client
URL validation for MCP SSRF protection.

Co-authored-by: Cursor <cursoragent@cursor.com>
@batmn-dev batmn-dev merged commit 0664ffd into main Feb 9, 2026
6 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.

1 participant