Skip to content

Bug: global.EventSource permanently overwritten with ReconnectingEventSource on every SSE connection #11727

@marlonbarreto-git

Description

@marlonbarreto-git

Description

When connecting to an MCP server of type sse, the code at McpHub.ts line 826 overwrites global.EventSource with ReconnectingEventSource. This global mutation happens on every SSE connection (not a one-time init) and is never reverted. It pollutes the global scope for all code in the VS Code extension host.

Root Cause

File: src/services/mcp/McpHub.ts, line 826:

} else if (configInjected.type === "sse") {
    // SSE connection setup...
    const reconnectingEventSourceOptions = {
        max_retry_time: 5000,
        // ...
    }
    global.EventSource = ReconnectingEventSource   // ⚠️ Overwrites global
    transport = new SSEClientTransport(new URL(configInjected.url), {
        ...sseOptions,
        eventSourceInit: reconnectingEventSourceOptions,
    })

The original EventSource is never saved and never restored.

Impact

  • Global scope pollution: Any code in the VS Code extension host process that uses EventSource (other extensions, VS Code internals) will get ReconnectingEventSource instead of the native implementation
  • Behavioral change: ReconnectingEventSource has different semantics (automatic reconnection with exponential backoff) vs native EventSource — this silently changes behavior for unrelated code
  • Runs per-connection, not once: While functionally idempotent (same value assigned each time), the placement inside the per-connection flow indicates it wasn't designed as a global init
  • No cleanup: If the SSE connection is later disconnected, the global remains overwritten

Proposed Fix

Option A — Save and restore (minimal change):

const originalEventSource = global.EventSource
global.EventSource = ReconnectingEventSource
transport = new SSEClientTransport(new URL(configInjected.url), {
    ...sseOptions,
    eventSourceInit: reconnectingEventSourceOptions,
})
global.EventSource = originalEventSource

Option B — Pass via transport options (if SDK supports it):
If SSEClientTransport accepts an EventSource constructor option, pass it directly instead of mutating the global.

Option C — Move to one-time init:
If the global mutation is intentional, move it to a static initializer that runs once, not per-connection:

// At module level or in constructor
if (!McpHub._eventSourcePatched) {
    global.EventSource = ReconnectingEventSource
    McpHub._eventSourcePatched = true
}
Option A Option B Option C
Fixes global pollution Yes Yes No (still pollutes, but once)
Complexity Minimal Depends on SDK Minimal
Breaking changes None None None

Environment

  • Roo-Code: latest
  • File: src/services/mcp/McpHub.ts, line 826
  • Affects: All SSE-type MCP server connections + any code sharing the extension host process

I'm happy to open a PR for this fix if you'd like.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions