Skip to content

Web server events stream ignores CRLF-delimited SSE frames #2006

Description

@jstar0

Which version line?

v2 - current (@modelcontextprotocol/inspector@latest)

Which client?

Web

Inspector version

2.0.0; reproduced against the current v2 development branch.

Node version

v26.7.0

Operating system (and browser, for the web client)

macOS 27.0; reproduced at hook/test level, so no browser-specific behavior is required.

Transport

Not applicable / never connected

MCP server under inspection

No MCP server is required. The issue is in the web client's /api/servers/events subscription that keeps the saved server list in sync after mcp.json changes.

Steps to reproduce

  1. Start from the current v2 development branch.
  2. Mount useServers with a fetch implementation whose /api/servers response reads from a test mcp.json.
  3. Have /api/servers/events return a readable stream that emits a valid SSE change frame delimited with CRLF line endings: event: change\r\n\r\n.
  4. Update mcp.json before releasing that frame.
  5. Observe the hook state after the frame is consumed.

Expected behavior

The hook should treat the CRLF-delimited SSE frame as a change notification, call the background refresh path, and update the displayed server list from mcp.json.

SSE permits CRLF line endings, and the hook is already acting as a small custom SSE parser because EventSource cannot send the x-mcp-remote-auth header.

Actual behavior

The hook only searches for \n\n as the frame separator. A CRLF-delimited frame stays buffered, isSseDataFrame() is never reached, and no background refresh is triggered. The server list stays at its previous value until the user manually refreshes or another LF-delimited event arrives.

Logs, errors, or screenshots

Focused regression before the prototype fix:

FAIL clients/web/src/test/core/react/useServers.test.tsx > useServers > parses CRLF-delimited SSE frames as change notifications
AssertionError: expected [ 'seed' ] to deeply equal [ 'aftercrlf' ]

Verification after the prototype fix:

npm run test -- src/test/core/react/useServers.test.tsx
Test Files 1 passed (1)
Tests 33 passed (33)

npm run validate:web
Test Files 263 passed (263)
Tests 3811 passed (3811)

Already prototyped a fix?

Prototype prompt:

Update the web client's useServers SSE reader so `/api/servers/events` treats both LF and CRLF blank lines as SSE frame separators. Keep comment-only priming frames ignored, keep the existing one-background-refresh-per-decode-chunk behavior, and add a hook unit test with a controlled readable stream that emits `event: change\r\n\r\n` after an external `mcp.json` write.

The prototype changes core/react/useServers.ts to find SSE frame separators with a CRLF-aware blank-line matcher and split frame lines with CRLF/LF handling. It adds a focused useServers regression test for a CRLF-delimited event: change frame.

Before you submit

  • I searched existing issues and this is not a duplicate.
  • This is not a security vulnerability report (those go through the private advisory process).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingv2Issues and PRs for v2

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions