Skip to content

fix(web): keep a failed connect's reason on the server card (#2783) - #2801

Merged
cliffhall merged 1 commit into
v2/mainfrom
v2/fix/2783-sse-connection-failed
Oct 25, 2026
Merged

cliffhall merged 1 commit into
v2/mainfrom
v2/fix/2783-sse-connection-failed

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #2783

Not reproducible: this PR improves diagnostics only

#2783 could not be reproduced. I tested against a real Python MCP SDK 1.x FastMCP server on the legacy SSE transport. It sends CRLF framing and a relative /messages/?session_id=… endpoint, the shape the report describes. Against it, the web client connected and listed tools, both with and without --header "Authorization: Bearer …", and the CLI did too. The reporter's setup has two differences I couldn't test: HTTPS through a cloud load balancer, and Inspector sending accept-encoding: gzip, deflate and user-agent: node where their curl -N sent neither.

What I did find is why the report contains no error text. One failure path matches all three reported symptoms: only the GET /sse is logged, the stream closes after one event, and the card shows Failed. That path is the SDK rejecting the endpoint event (for example Endpoint origin does not match connection origin) and closing the transport. On that path the backend returns the reason, and the browser shows it, but only in a toast that auto-closes after about 4s. After that the card says only Failed, which is all the reporter had. The reason was already stored in connectErrorMessage, but the only place it was exposed was a data-error-message attribute for automation.

Reporter: once this ships, please retry, and if it still fails, open a new issue with the error text the server card now shows under Failed. That message should name the cause this issue couldn't pin down.

Change

  • ServerCard takes an errorMessage prop and renders it under the header while the card is errored. This includes compact mode, where everything else below the header is hidden.
  • ServerListScreen passes connectErrorMessage only to the erroredServerId card, and InspectorView threads it through.
  • A new connectError Text theme variant: danger-text color, and wrapping, so a long transport error carrying a URL or JSON body stays inside the card.
  • Tests cover the errored, compact, not-errored and no-message cases, plus the screen-level targeting. There is also a new ErroredWithReason story.

Screenshots

Both were taken 6s after toggling Connect, once the toast had closed, against a stub legacy-SSE server that sends a cross-origin endpoint event.

Before: the card shows Failed and nothing else.

before

After: the reason stays on the card.

after

npm run local:gate passed.

🤖 Generated with Claude Code

The connect-failure toast auto-closes after a few seconds, after which the
server card showed only a red "Failed" with no reason. The reason was
already held in connectErrorMessage but only exposed as a data attribute
for automation. Thread it to the errored card and render it under the
header, in compact mode too, so a failure like the legacy SSE endpoint
origin mismatch stays readable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: cliffhall <cliff@futurescale.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The scoped diagnostic display correctly reuses existing error state, has focused test coverage, and has no identified blocking issues.

No open issues 🎉

What changed in this PR

This PR improves web-client diagnostics for #2783 by keeping the failed connection’s reason visible on its server card after the toast disappears. It does not change SSE transport behavior or claim to fix the unreproduced connection failure.

Changes:

  • Passes the existing connection error to the failed server’s card, including in compact mode.
  • Adds themed error text with wrapping for long messages.
  • Adds visibility and server-targeting tests plus a diagnostic Storybook example.
File Description
clients/​web/​src/​theme/​Text.ts Adds error-text styling and wrapping.
clients/​web/​src/​components/​views/​InspectorView/​types.ts Documents the error message’s card display.
clients/​web/​src/​components/​views/​InspectorView/​InspectorView.tsx Passes the error message to the server list.
clients/​web/​src/​components/​screens/​ServerListScreen/​ServerListScreen.tsx Targets the message to the failed server.
clients/​web/​src/​components/​screens/​ServerListScreen/​ServerListScreen.test.tsx Tests failed-card targeting.
clients/​web/​src/​components/​groups/​ServerCard/​ServerCard.tsx Displays the failure reason in normal and compact modes.
clients/​web/​src/​components/​groups/​ServerCard/​ServerCard.test.tsx Tests error-message visibility conditions.
clients/​web/​src/​components/​groups/​ServerCard/​ServerCard.stories.tsx Adds a failed-card example with a long reason.

Review effort: Balanced

@cliffhall

Copy link
Copy Markdown
Member Author

Copilot review closed: round 1 came back clean (no inline comments, no suppressed findings, approval recommended), so no further rounds.

@cliffhall
cliffhall merged commit 9558d0d into v2/main Oct 25, 2026
11 checks passed
@cliffhall
cliffhall deleted the v2/fix/2783-sse-connection-failed branch October 25, 2026 04:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SSE transport: connection succeeds then marked 'Failed' after first event, works fine with raw curl

2 participants