Skip to content

Fix/on mcp configuration always called#2356

Open
JonasJesus42 wants to merge 29 commits intomainfrom
fix/on-mcp-configuration-always-called
Open

Fix/on mcp configuration always called#2356
JonasJesus42 wants to merge 29 commits intomainfrom
fix/on-mcp-configuration-always-called

Conversation

@JonasJesus42
Copy link
Contributor

@JonasJesus42 JonasJesus42 commented Jan 29, 2026

Problem

Previously, ON_MCP_CONFIGURATION was only called when:

  1. configuration_state or configuration_scopes were explicitly passed in the update request
  2. AND finalState was truthy
  3. AND finalScopes.length > 0

This caused a bug where MCPs with onChange handlers were never notified because:

  • The UI doesn't always send configuration_state/configuration_scopes on save
  • configuration_scopes were never automatically fetched from the MCP
  • So finalScopes.length was always 0 for new connections

Impact

MCPs that depend on onChange to initialize their state (e.g., caching configs, setting up webhooks, validating credentials) would never receive the callback, leaving them in an uninitialized state.

Solution

  • Fetch scopes from MCP_CONFIGURATION if not already saved in the connection
  • Save fetched scopes to the connection for future updates
  • Initialize empty state ({}) if scopes exist but state is null
  • Always call ON_MCP_CONFIGURATION when state and scopes are available
  • Use single proxy connection for all operations (more efficient)

Changes

Before:
if (
(data.configuration_state !== undefined ||
data.configuration_scopes !== undefined) &&
finalState &&
finalScopes.length > 0
) {
// Call ON_MCP_CONFIGURATION
}After:
// Fetch scopes from MCP if not saved
if (finalScopes.length === 0) {
const mcpConfig = await proxy.callTool({ name: "MCP_CONFIGURATION" });
if (mcpConfig?.scopes?.length > 0) {
finalScopes = mcpConfig.scopes;
await ctx.storage.connections.update(id, { configuration_scopes: finalScopes });
}
}

// Initialize empty state if needed
if (finalScopes.length > 0 && !finalState) {
finalState = {};
}

// Always call if we have state and scopes
if (finalState && finalScopes.length > 0) {
await proxy.callTool({ name: "ON_MCP_CONFIGURATION", arguments: { state, scopes } });
}### Testing

  1. Create a new MCP connection with an onChange handler
  2. Click "Save" without changing any configuration fields
  3. Verify that ON_MCP_CONFIGURATION is called and onChange is triggered
  4. Verify that configuration_scopes is saved to the connection

Related

This fix is essential for MCPs like Slack Bot that need to cache configurations for webhook handlers that run outside the MCP context.

Screenshots/Demonstration

Add screenshots or a Loom video if your changes affect the UI.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • Documentation is updated (if needed)
  • No breaking changes

Summary by cubic

Always calls ON_MCP_CONFIGURATION on connection updates by fetching missing scopes and initializing state. Improves Decopilot API with detailed validation logs and support for agent mode.

  • Bug Fixes

    • Fetch and persist scopes from MCP_CONFIGURATION when none are saved.
    • Initialize configuration_state to {} if scopes exist but state is null.
    • Always call ON_MCP_CONFIGURATION when state and scopes are available.
    • Use a single MCP proxy for the entire update flow.
  • New Features

    • Add agent.mode to Decopilot stream schema (passthrough, smart_tool_selection, code_execution).
    • Provide default, uniform server capabilities and instructions for virtual MCPs.

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

…ections

Previously, ON_MCP_CONFIGURATION was only called when:
1. configuration_state or configuration_scopes were explicitly passed in the update
2. AND finalState was truthy
3. AND finalScopes.length > 0

This caused a bug where MCPs with onChange handlers were never notified because:
- The UI doesn't always send configuration_state/scopes on save
- configuration_scopes were never automatically fetched from the MCP
- So finalScopes.length was always 0 for new connections

Changes:
- Fetch scopes from MCP_CONFIGURATION if not already saved
- Save fetched scopes to the connection for future updates
- Initialize empty state ({}) if scopes exist but state is null
- Always call ON_MCP_CONFIGURATION when state and scopes are available
- Use single proxy connection for all operations (more efficient)

This ensures that MCP onChange handlers are always triggered when
a connection is updated, allowing MCPs to properly initialize their
state (e.g., caching configs, setting up webhooks, etc.).
@github-actions
Copy link
Contributor

🧪 Benchmark

Should we run the Virtual MCP strategy benchmark for this PR?

React with 👍 to run the benchmark.

Reaction Action
👍 Run quick benchmark (10 & 128 tools)

Benchmark will run on the next push after you react.

@github-actions
Copy link
Contributor

github-actions bot commented Jan 29, 2026

Release Options

Should a new version be published when this PR is merged?

React with an emoji to vote on the release type:

Reaction Type Next Version
👍 Prerelease 2.64.2-alpha.1
🎉 Patch 2.64.2
❤️ Minor 2.65.0
🚀 Major 3.0.0

Current version: 2.64.1

Deployment

  • Deploy to production (triggers ArgoCD sync after Docker image is published)

Copy link
Contributor

@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.

No issues found across 2 files

- Loga parseResult.error.format() do Zod quando validação falha
- Loga rawPayload que causou erro de validação
- Facilita debug de erros 400 'Invalid request body'
- Inclui cause no HTTPException para rastreamento
Copy link
Contributor

@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.

1 issue found across 1 file (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="apps/mesh/src/api/routes/decopilot/routes.ts">

<violation number="1" location="apps/mesh/src/api/routes/decopilot/routes.ts:47">
P2: Avoid logging the full raw payload on validation errors because it can expose sensitive data in logs. Log only validation errors or redact the payload.</violation>
</file>

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

"Validation errors:",
JSON.stringify(parseResult.error.format(), null, 2),
);
console.error("Raw payload:", JSON.stringify(rawPayload, null, 2));
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P2: Avoid logging the full raw payload on validation errors because it can expose sensitive data in logs. Log only validation errors or redact the payload.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/api/routes/decopilot/routes.ts, line 47:

<comment>Avoid logging the full raw payload on validation errors because it can expose sensitive data in logs. Log only validation errors or redact the payload.</comment>

<file context>
@@ -38,7 +38,18 @@ async function validateRequest(
+      "Validation errors:",
+      JSON.stringify(parseResult.error.format(), null, 2),
+    );
+    console.error("Raw payload:", JSON.stringify(rawPayload, null, 2));
+
+    throw new HTTPException(400, {
</file context>
Suggested change
console.error("Raw payload:", JSON.stringify(rawPayload, null, 2));
console.error("Raw payload:", "[redacted]");
Fix with Cubic

rafavalls and others added 23 commits February 2, 2026 12:06
* Enhance virtual MCP functionality and improve error handling

- Introduced DEFAULT_SERVER_CAPABILITIES to standardize server capabilities across MCPs.
- Updated getServerCapabilities to return the new default capabilities.
- Refactored error handling in virtual MCP request processing to ensure proper responses when IDs are missing.
- Simplified connection handling in the connection storage by resolving organization IDs more efficiently.
- Added new utility functions for managing selections in virtual MCPs, improving the user experience in selection dialogs.
- Implemented a new share modal for virtual MCPs, allowing users to easily share agent configurations and integrate with IDEs.
- Removed deprecated item selector component to streamline the codebase.

* fmt

* Refactor ChatPanels component to simplify chat visibility logic

- Updated the logic for displaying the chat panel by directly using the `chatOpen` state instead of a derived `shouldShowChat` variable.
- Enhanced readability by wrapping the chat-related components in a fragment for better structure.

* fix ts

---------

Co-authored-by: gimenes <tlgimenes@gmail.com>
* Refactor virtual MCP schemas and improve metadata handling

- Updated `PassthroughClient` to ensure consistent return of instructions metadata.
- Enhanced `VirtualMCPStorage` to normalize instructions in metadata, defaulting to null when not provided.
- Re-exported schemas from `@decocms/mesh-sdk` in `schema.ts` and `virtual/schema.ts` to maintain a single source of truth.
- Adjusted `DependencySelectionDialog` to enforce required metadata structure.
- Updated constants and types to reflect changes in metadata handling across the application.

* wip

* Refactor Virtual MCP components to use updated types

- Replaced `UseFormReturn` with `VirtualMcpFormReturn` in `DependencySelectionDialogProps`.
- Updated connection handling to utilize `VirtualMCPConnection` type across components.
- Introduced a new `types.ts` file to define shared types and validation schema for Virtual MCP forms.
- Deprecated the old `ConnectionSelection` type in favor of the new SDK type for better consistency.
* fix error boundary reset on select other

* fmt
* feat(ui): add SVG assets for sidebar components

* refactor(sidebar): reorganize sidebar components into structured layout

- Move mesh-sidebar.tsx to sidebar/index.tsx
- Move sidebar-items-section.tsx to sidebar/items/item.tsx
- Move navigation-sidebar.tsx from packages/ui to apps/mesh
- Add sidebar/types.ts for shared types
- Add sidebar/items/index.tsx and layout.tsx for better organization

* feat(sidebar): add account switcher component

- Add MeshAccountSwitcher with user and org panels
- Implement organization switching functionality
- Add user panel with settings navigation
- Add org panel with organization selection and settings
- Support collapsed sidebar state

* feat(sidebar): add inbox component for organization invitations

- Add SidebarInboxFooter component with invitation management
- Implement InvitationItem for displaying and handling invitations
- Support accepting/rejecting invitations
- Show pending invitation indicator
- Filter expired invitations automatically

* feat(sidebar): integrate account switcher and inbox into sidebar

- Update shell-layout to use new sidebar structure
- Integrate account switcher in sidebar header
- Add inbox footer component
- Update sidebar items hook for new structure
- Update home page to use new sidebar components

* feat(chat): add transition when creating new thread using useTransition

* feat(sidebar): enhance sidebar header with chat toggle and refactor styles

- Add chat toggle functionality using useDecoChatOpen hook
- Update sidebar header to include chat icon and tooltip
- Refactor class names for better readability and maintainability
- Remove unnecessary SidebarSeparator from navigation

* refactor(inbox): remove InboxButton component and related invitation handling

- Delete InboxButton component which managed user invitations
- Remove associated InvitationItem and invitation handling logic
- Update useDecoChatOpen hook to default to true for chat open state

* remove svgs

* fix(user-panel): improve clipboard copy functionality with error handling

- Update handleCopyUserInfo to be asynchronous for clipboard operations
- Add error handling to notify users if copying fails
- Maintain success notification for successful copy actions

* wip

---------

Co-authored-by: rafavalls <valls@deco.cx>
* refactor(web): unify page headers with Page component system

- Create unified Page component with slot-based composition (Page.Header, Page.Header.Left/Right, Page.Content)
- Migrate all collection pages (agents, connections, members, settings, monitoring, store, workflow) to use Page component
- Replace Chat.Header with Page.Header directly for consistency
- Remove deprecated CollectionHeader and CollectionPage components
- Add comprehensive documentation in Page component README

Benefits:
- Consistent header styling (48px height, borders, spacing) across all pages
- Reduced bundle size by eliminating duplicate header implementations
- Better type safety with slot-based composition
- Easier to maintain and extend

* fmt&lint

* feat(ui): update breadcrumb separator and remove back buttons from detail pages

- Change breadcrumb separator from SlashDivider to ChevronRight
- Remove flex-wrap from breadcrumb list to prevent wrapping
- Add truncate classes to breadcrumb links and pages
- Add overflow-x-auto to Page.Header for horizontal scrolling
- Add border-l to Page.Header.Right
- Remove back buttons from ViewLayout and MCPServerDetailHeader
- Remove onBack props from all detail page components
- Clean up unused imports (useRouter, ArrowLeft)

* feat(ui): convert page titles to breadcrumb components

- Replace h1 titles with Breadcrumb components in list pages
- Update agents, connections, members, settings, plugins, and store pages
- Update binding-collection-view to use breadcrumb component
- Maintain consistent breadcrumb styling across all pages

* feat(ui): add breadcrumb to monitoring page

- Replace h1 title with Breadcrumb component in monitoring page
- Refactor monitoring logs table to use Table components

* fix(ui): make table headers opaque and refactor monitoring table to use Table components

- Fix transparent table headers in CollectionTable and monitoring table by changing bg-muted/30 to bg-muted
- Refactor monitoring table to use base Table components (TableHeader, TableBody, TableRow, TableCell) for better semantic HTML and consistency
- Preserve all existing functionality including expandable rows, infinite scroll, and responsive layouts

* refactor(chat): remove unused IntegrationIcon from ChatPanelContent

- Eliminate IntegrationIcon component from ChatPanelContent in both header sections to streamline the UI and improve performance.
- Maintain existing functionality and layout integrity.

* fix(ui): make all table headers sticky by default and fix scrolling containers

- Make TableHeader sticky by default (sticky top-0 z-10 bg-muted) in base table component
- Remove sticky classes from CollectionTable and monitoring table callers (simplified)
- Remove relative positioning from Table wrapper that was interfering with sticky
- Remove extra wrapper div from CollectionTable that broke sticky positioning
- Add bg-background to Table wrapper for consistent styling
- Fix CollectionTableWrapper scrolling structure to work with Page.Content
- Wrap CollectionTableWrapper in connections and agents routes to prevent Page.Content scrolling conflicts

All tables now have sticky headers by default, and the scrolling container hierarchy is properly structured to support sticky positioning.

* fix(ui): remove unused isFirst prop from LogRow component

* fix: address cubic code review issues

- Conditionally render Page.Header.Right in monitoring.tsx only when tab === 'logs' to avoid stray divider
- Implement OAuth authentication handler in tool.tsx for 'Go back to authenticate' button
- Add navigation handler for 'Go back' button in collection-detail.tsx

* fix: use centralized KEYS constant for query key invalidation

* revert: rollback OAuth authentication handler changes in tool.tsx

* restore: bring tool.tsx back to main branch state

* restore: bring collection-detail.tsx back to main branch state

* apply fix

* feat: add breadcrumbs to tool detail view

- Add breadcrumb navigation: Connections > Tools > Tool.Name
- Connections links to /:org/mcps
- Tools links to /:org/mcps/:connectionId?tab=tools
- Tool name displayed as final breadcrumb item

* feat: add breadcrumbs to collection detail view

- Add breadcrumb navigation: Connections > Connection Name > Collection Name
- Connections links to /:org/mcps
- Connection Name links to /:org/mcps/:connectionId?tab=collectionName
- Collection Name displayed as final breadcrumb item
- Only show Connection Name breadcrumb if connection exists
- Wrap EmptyState in ViewLayout with breadcrumbs

* fix: update tool detail breadcrumb to show MCP name instead of Tools

- Change breadcrumb from Connections > Tools > ToolName to Connections > MCP Name > ToolName
- MCP Name links to connection detail page with tools tab selected
- Matches the pattern used in connection detail view

* Update packages/ui/src/components/breadcrumb.tsx

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
* feat(ui): unify save button UX across detail pages

- Create shared SaveActions component with unified save/undo pattern
- Save button: primary variant with 'Save' label and diskette icon
- Undo button: outline variant with 'Undo' label and flip icon
- Both buttons always render, disabled when form is not dirty
- Add undo functionality to Connection Settings (previously missing)
- Replace icon-only buttons with text buttons in Agents, Prompts, and Workflows
- Standardize button order: Pin → Save → Undo → Other buttons (right to left)
- Fix Settings > Plugins to always render Cancel button

Pages updated:
- Connection Settings (added undo)
- Virtual MCP/Agents (icon → text buttons)
- Prompt Details (icon → text buttons)
- Workflow Details (icon → text buttons)
- Settings > Plugins (always render Cancel)

* refactor(ui): move save/undo buttons to leftmost and hide when not dirty

- Move SaveActions to first position (leftmost) in all pages
- Hide SaveActions when form is not dirty (instead of disabling)
- Remove isDirty check from disabled state (only check isSaving)
- Button order: SaveActions (left, hidden when clean) → Other buttons → Pin (right)
* feat(ui): add gray sidebar and chat panel styles

- Update sidebar and muted color tokens to use subtle gray tones
- Change side panel chat background from white to gray (bg-muted)
- Keep home page chat white background via className override
- Make chat skeleton background configurable via className prop

* fix(ui): ensure home page header uses white background

* fix(ui): keep topbar white on org list route

Change AppTopbar from bg-sidebar to bg-background so the topbar
on the / route (organizations list) remains white instead of gray.

* chore: remove redundant bg-background from Page.Header

Page.Header doesn't need bg-background since the parent Chat component
already has it.

* fix(chat): make sticky overlay background adapt to chat surface color

Use CSS custom property to dynamically set the sticky overlay background color based on the parent Chat component's surface. This ensures the overlay properly masks scrolling content in both contexts (bg-muted in sidebar, bg-background on home page).

* feat(chat): add agent mode selector with hover-to-expand UI

- Add mode selector for choosing agent execution modes (Direct access, Smart discovery, Smart execution)
- Mode selector uses business-friendly labels consistent with share modal
- Implement hover-to-expand behavior for both Mode and Model selectors
  - Shows only icon by default
  - Expands to show label and chevron on hover
  - Stays expanded when popover is open
- Store mode preference in localStorage per project
- Pass mode through metadata to decopilot API
- Make mode field required in API schema
- Update file upload button icon from Plus to Upload01
- Reorganize chat input layout:
  - Left: Agent selector, Usage stats
  - Right: Model selector, Mode selector, File upload, Submit button
- Fix unused imports in select-virtual-mcp component

* fix: remove unused ModeSelector export
… dialog unmounting (#2369)

- Remove Profile and Security & Access menu items from sidebar header
- Keep Preferences menu item to open settings dialog
- Fix dialog closing immediately by lifting state out of PopoverContent
- Move UserSettingsDialog rendering to parent component to prevent unmounting
…gradient (#2368)

* feat(chat): enhance ThoughtSummary streaming UX with auto-scroll and gradient

- Always render ThoughtSummary expanded with fixed 100px height while streaming
- Add smooth auto-scroll to bottom as new reasoning parts arrive (typewriter effect)
- Add gradient fade-out at top only while streaming
- Collapse summary when streaming stops, allow manual expand/collapse
- Refactor hover state to CSS-only approach using Tailwind group utilities
- Use scrollIntoView with smooth behavior instead of direct scrollTop manipulation

* refactor(chat): remove unused scrollRef from ThoughtSummary

- Remove unused scrollRef that was left over from refactoring
- Only lastPartRef is needed for scrollIntoView functionality

* fix(chat): increase minHeightOffset for Chat.Messages component

- Update minHeightOffset from 230 to 240 in Chat.Messages for better layout consistency in both chat panel and home page.

* refactor(chat): implement smart auto-scroll with visibility detection

- Refactor auto-scroll from Chat-level hook to Assistant-level component
- Use IntersectionObserver to detect when user scrolls away
- Auto-scroll only when component is visible in viewport
- Remove scrollIntoView in favor of direct scrollTop manipulation
- Move ThoughtSummary internal scrolling to scrollTop approach
- Simplify SmartAutoScroll to accept parts directly
- Only render SmartAutoScroll for last message during streaming

* fix(chat): initialize isVisible to false in SmartAutoScroll

Initialize isVisible to false so auto-scroll only starts after the IntersectionObserver confirms the sentinel is visible; the current default true can force an unwanted scroll when the user is already scrolled away.

* refactor(chat): hardcode minHeightOffset and extract ref callback

- Remove minHeightOffset parameter from ChatMessages component
- Hardcode 240px value in MessagePair component
- Extract ref callback into handlePairRef function
- Remove minHeightOffset prop from all usage sites

* refactor(chat): make isLast prop required in MessageAssistant
…simultaneously (#2370)

When the sidebar is collapsed and hovering over the organization button area, both the account switcher button and the expand chevron were visible at the same time. Added proper visibility classes to ensure only one is shown at a time.
github-actions bot and others added 3 commits February 2, 2026 12:06
* Virtual tools

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>

* Fixes cubic issues

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>

* Rebase things

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>

---------

Signed-off-by: Marcos Candeia <marrcooos@gmail.com>
Copy link
Contributor

@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.

5 issues found across 90 files (changes from recent commits).

Note: This PR contains a large number of files. cubic only reviews up to 75 files per PR, so some files may not have been reviewed.

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="apps/mesh/src/storage/virtual.ts">

<violation number="1" location="apps/mesh/src/storage/virtual.ts:400">
P2: Spreading `metadata` can throw when parseJson returns null. Guard the spread with a fallback object to avoid runtime errors when metadata is null.</violation>
</file>

<file name="apps/mesh/src/api/routes/proxy.ts">

<violation number="1" location="apps/mesh/src/api/routes/proxy.ts:667">
P2: The transport is no longer closed after handling the request, which can leave open streams and leak resources. Reintroduce the try/finally cleanup around `handleRequest` so the transport is always closed.</violation>
</file>

<file name="apps/mesh/src/web/components/details/prompt/index.tsx">

<violation number="1" location="apps/mesh/src/web/components/details/prompt/index.tsx:250">
P3: Align the exported `PromptDetailsViewProps` type with the component’s actual props. Right now `onUpdate` is still required in the interface even though the component omits it, which is a confusing public API mismatch.</violation>
</file>

<file name="packages/mesh-plugin-user-sandbox/server/tools/get.ts">

<violation number="1" location="packages/mesh-plugin-user-sandbox/server/tools/get.ts:14">
P2: The handler can return null when a template ID is not found, but the output schema is now non-nullable. This will cause schema validation failures for valid “not found” responses. Keep the output schema nullable or throw a not-found error instead.</violation>
</file>

<file name="apps/mesh/src/web/components/details/virtual-mcp/index.tsx">

<violation number="1" location="apps/mesh/src/web/components/details/virtual-mcp/index.tsx:254">
P3: The eslint-disable comment uses a misspelled rule name (`react-hooks/exhaustive-depsbun`), which triggers an ESLint error and doesn’t suppress the hook dependency warning. Correct the rule name or remove the comment.</violation>
</file>

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

updated_by: undefined, // connections table doesn't have updated_by
metadata: this.parseJson<{ instructions?: string }>(row.metadata),
metadata: {
...metadata,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P2: Spreading metadata can throw when parseJson returns null. Guard the spread with a fallback object to avoid runtime errors when metadata is null.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/storage/virtual.ts, line 400:

<comment>Spreading `metadata` can throw when parseJson returns null. Guard the spread with a fallback object to avoid runtime errors when metadata is null.</comment>

<file context>
@@ -433,7 +396,10 @@ export class VirtualMCPStorage implements VirtualMCPStoragePort {
       updated_by: undefined, // connections table doesn't have updated_by
-      metadata: this.parseJson<{ instructions?: string }>(row.metadata),
+      metadata: {
+        ...metadata,
+        instructions: metadata?.instructions ?? null,
+      },
</file context>
Suggested change
...metadata,
...(metadata ?? {}),
Fix with Cubic

// Ignore close errors - transport may already be closed
}
}
return await transport.handleRequest(c.req.raw);
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P2: The transport is no longer closed after handling the request, which can leave open streams and leak resources. Reintroduce the try/finally cleanup around handleRequest so the transport is always closed.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/api/routes/proxy.ts, line 667:

<comment>The transport is no longer closed after handling the request, which can leave open streams and leak resources. Reintroduce the try/finally cleanup around `handleRequest` so the transport is always closed.</comment>

<file context>
@@ -653,16 +664,7 @@ app.all("/:connectionId", async (c) => {
-          // Ignore close errors - transport may already be closed
-        }
-      }
+      return await transport.handleRequest(c.req.raw);
     } catch (error) {
       // Check if this is an auth error - if so, return appropriate 401
</file context>
Suggested change
return await transport.handleRequest(c.req.raw);
try {
return await transport.handleRequest(c.req.raw);
} finally {
try {
await transport.close?.();
} catch {
// Ignore close errors - transport may already be closed
}
}
Fix with Cubic

description: "Get a user sandbox by ID",
inputSchema: UserSandboxGetInputSchema,
outputSchema: UserSandboxEntitySchema.nullable(),
outputSchema: UserSandboxEntitySchema,
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P2: The handler can return null when a template ID is not found, but the output schema is now non-nullable. This will cause schema validation failures for valid “not found” responses. Keep the output schema nullable or throw a not-found error instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/mesh-plugin-user-sandbox/server/tools/get.ts, line 14:

<comment>The handler can return null when a template ID is not found, but the output schema is now non-nullable. This will cause schema validation failures for valid “not found” responses. Keep the output schema nullable or throw a not-found error instead.</comment>

<file context>
@@ -11,7 +11,7 @@ export const USER_SANDBOX_GET: ServerPluginToolDefinition = {
   description: "Get a user sandbox by ID",
   inputSchema: UserSandboxGetInputSchema,
-  outputSchema: UserSandboxEntitySchema.nullable(),
+  outputSchema: UserSandboxEntitySchema,
 
   handler: async (input, ctx) => {
</file context>
Suggested change
outputSchema: UserSandboxEntitySchema,
outputSchema: UserSandboxEntitySchema.nullable(),
Fix with Cubic

export function PromptDetailsView({ itemId, onBack }: PromptDetailsViewProps) {
export function PromptDetailsView({
itemId,
}: Omit<PromptDetailsViewProps, "onUpdate">) {
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P3: Align the exported PromptDetailsViewProps type with the component’s actual props. Right now onUpdate is still required in the interface even though the component omits it, which is a confusing public API mismatch.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/components/details/prompt/index.tsx, line 250:

<comment>Align the exported `PromptDetailsViewProps` type with the component’s actual props. Right now `onUpdate` is still required in the interface even though the component omits it, which is a confusing public API mismatch.</comment>

<file context>
@@ -284,11 +242,12 @@ function PromptDetailContent({
-export function PromptDetailsView({ itemId, onBack }: PromptDetailsViewProps) {
+export function PromptDetailsView({
+  itemId,
+}: Omit<PromptDetailsViewProps, "onUpdate">) {
   const connectionId = getConnectionIdFromPathname();
 
</file context>
Fix with Cubic

useEffect(() => {
setChatOpen(true);
setVirtualMcpId(virtualMcp.id);
// eslint-disable-next-line react-hooks/exhaustive-depsbun
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 2, 2026

Choose a reason for hiding this comment

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

P3: The eslint-disable comment uses a misspelled rule name (react-hooks/exhaustive-depsbun), which triggers an ESLint error and doesn’t suppress the hook dependency warning. Correct the rule name or remove the comment.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mesh/src/web/components/details/virtual-mcp/index.tsx, line 254:

<comment>The eslint-disable comment uses a misspelled rule name (`react-hooks/exhaustive-depsbun`), which triggers an ESLint error and doesn’t suppress the hook dependency warning. Correct the rule name or remove the comment.</comment>

<file context>
@@ -1,998 +1,356 @@
+  useEffect(() => {
+    setChatOpen(true);
+    setVirtualMcpId(virtualMcp.id);
+    // eslint-disable-next-line react-hooks/exhaustive-depsbun
+  }, [virtualMcp.id]);
+
</file context>
Suggested change
// eslint-disable-next-line react-hooks/exhaustive-depsbun
// eslint-disable-next-line react-hooks/exhaustive-deps
Fix with Cubic

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.

5 participants