Skip to content

fix(native-chat): replace the Claude init error card with an actionable MCP connect warning - #28857

Closed
airematters wants to merge 2 commits into
stablyai:mainfrom
airematters:fix/claude-init-mcp-failed-not-error
Closed

airematters wants to merge 2 commits into
stablyai:mainfrom
airematters:fix/claude-init-mcp-failed-not-error

Conversation

@airematters

Copy link
Copy Markdown

ELI5

When one of your MCP servers can't connect, a Claude chat used to open with a scary red card full of raw JSON. Now it shows one plain warning: which server failed, that its tools are missing, and how to find out why.

What Changed

Before: any MCP server with status: "failed" in Claude's system:init frame turned the whole init frame into an error-surface fallback row: a red claude · message:system:init card whose disclosure is the raw frame (tool list, MCP servers, plugins…).

After: the init frame never renders as a row. Instead, a status / warning row says e.g.:

MCP server "marimo" failed to connect, so its tools are unavailable in this session. Run claude mcp list in a terminal to see why.

Mechanism:

  • provider-frame-disposition.ts: payload failure inspection (hasProviderError) is skipped for inventory frame kinds — today only Claude message:system:init. Its nested status fields describe sub-resources, not the frame's outcome. Every other kind is still inspected.
  • New claude-mcp-connect-failure-row.ts, wired into the Claude provider fallback next to the informational row: builds the warning from mcp_servers[].status === 'failed'. Init repeats every request cycle, so each server is reported once per session; a server that fails later gets its own row. needs-auth is not reported.

Why

The init frame is session inventory, so an error card for it is wrong, and the raw dump gives the user nothing to act on. Silently dropping it would hide a real problem (missing tools). Naming the server and pointing at claude mcp list (which shows the connect error) makes it actionable. Init frames do not carry the error text itself, so the row cannot show the reason directly.

Linked Issue

Fixes #28856

Visual Proof

Before: the red claude · message:system:init card described in #28856. After: the warning text above, asserted verbatim in claude-mcp-connect-failure-row.test.ts. I have not captured an after-screenshot from a built app.

Testing

  • I manually tested these changes locally

  • Automated tests added/updated, or explained why not below

  • provider-frame-disposition.test.ts: init with a failed server stays status-chrome; the same payload under another kind is still error-surface.

  • claude-mcp-connect-failure-row.test.ts (through createClaudeJournalTranslator): no row for connected / needs-auth; one row per newly failed server across repeated inits; one combined row for several failures in one init.

  • Both new tests fail with their fix reverted.

  • vitest over src/main/native-chat + src/main/claude: 5609 passed. tsc -p config/tsconfig.node.json, oxlint, oxfmt, audit:anti-slop, check:max-lines-ratchet clean. Tested on macOS only; the change is platform-independent.

AI Disclosure

Written with Claude Code (Claude Opus 5.5), reviewed by me.

Agent skill upstream boundary

  • Not applicable, or this change copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

🤖 Generated with Claude Code

airematters and others added 2 commits October 14, 2026 23:21
…ailed to connect

The init frame lists every MCP server with its connect status, so one
`status: 'failed'` entry made hasProviderError promote the whole
session-start frame to an error-surface row. Skip payload failure
inspection for inventory frame kinds (Claude `message:system:init`).

Fixes stablyai#28856

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ls to connect

The init frame no longer renders as an error dump, so report the one
actionable fact it carries instead: a warning row naming each MCP server
whose status is `failed`, pointing at `claude mcp list` for the reason.
Init repeats every request cycle, so each server is reported once.

Refs stablyai#28856

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 1869193b-13cc-45e8-a110-8b5c09a0cf09
📥 Commits

Reviewing files that changed from the base of the PR and between c8f0807 and f40b060.

📒 Files selected for processing: 5
  • src/main/claude/claude-mcp-connect-failure-row.test.ts
  • src/main/claude/claude-mcp-connect-failure-row.ts
  • src/main/claude/claude-structured-provider-fallback.ts
  • src/main/native-chat/agent-session-wire/provider-frame-disposition.test.ts
  • src/main/native-chat/agent-session-wire/provider-frame-disposition.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

Claude init frames are excluded from payload-based error classification. The fallback handler checks init frames for failed MCP servers and appends a warning row for newly reported failures. Connected and needs-auth servers produce no row. Informational frames retain their existing row handling.

Priority: ➖ Normal

Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to f40b0

Claude init frames with failed MCP servers now show a readable warning instead of a raw error card. No concrete merge-blocking risk was identified.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: replacing the Claude init error card with an actionable MCP connection warning.
Description check Passed The description is mostly complete. It explains the user impact, implementation, rationale, linked issue, tests, AI usage, and checklist status. It also identifies that no after-screenshot was capture…
Linked Issues check Passed The changes satisfy issue #28856. classifyProviderFrame skips payload error detection only for Claude message:system:init, so a failed MCP sub-resource does not create a raw error card. The Claude…
Out of Scope Changes check Passed The changes stay within issue #28856. They modify Claude init-frame classification and fallback rendering, add the focused MCP warning generator, and add tests for the required behavior. No unrelated …
  • Fix all pre-merge checks with AI
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@AmethystLiang

Copy link
Copy Markdown
Contributor

thanks for the PR. Will review it soon

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.

Claude chat shows system:init as an error card when an MCP server failed to connect

2 participants