Skip to content

MCPServerSSE doesn't forward fetch parameter to SSEClientTransport #699

@aasullivan

Description

@aasullivan

Bug Report: MCPServerSSE doesn't forward fetch parameter to SSEClientTransport

Summary

The MCPServerSSE class in @openai/agents-core accepts a fetch parameter in its constructor options but fails to forward it to the underlying SSEClientTransport. This prevents custom fetch implementations from being used with SSE-based MCP servers, breaking authentication and request customization use cases.

Affected Versions

  • @openai/agents: 0.3.0 - 0.3.3 (latest as of 2025-11-25)
  • @openai/agents-core: 0.3.0 - 0.3.3

Impact

Severity: High

This bug makes it impossible to:

  • Add authentication headers to SSE MCP server requests
  • Customize request behavior (timeouts, retries, logging)
  • Use corporate proxies or custom network configurations
  • Implement any per-request customization for SSE-based MCP servers

Meanwhile, MCPServerStreamableHttp correctly forwards the fetch parameter and works as expected.

Bug Location

File: node_modules/@openai/agents-core/dist/shims/mcp-server/node.js (and .mjs)

Current Code (Line ~180):

this.transport = new SSEClientTransport(new URL(this.params.url), {
    authProvider: this.params.authProvider,
    requestInit: this.params.requestInit,
    eventSourceInit: this.params.eventSourceInit,
    // ❌ BUG: fetch parameter is missing!
});

Expected Code:

this.transport = new SSEClientTransport(new URL(this.params.url), {
    authProvider: this.params.authProvider,
    requestInit: this.params.requestInit,
    eventSourceInit: this.params.eventSourceInit,
    fetch: this.params.fetch,  // ✅ This line is missing
});

How to Reproduce

Step 1: Create a custom fetch function

const customFetch: typeof fetch = async (input, init) => {
  console.log('[CUSTOM-FETCH] Request:', input);

  // Add custom headers
  const customHeaders = {
    'x-custom-auth': 'my-token',
  };

  return fetch(input, {
    ...init,
    headers: {
      ...(init?.headers || {}),
      ...customHeaders,
    },
  });
};

Step 2: Create an MCP server with SSE transport

import { MCPServerSSE } from '@openai/agents';

const mcpServer = new MCPServerSSE({
  url: 'https://my-mcp-server.com/sse',
  fetch: customFetch,  // This parameter is accepted but never used!
});

await mcpServer.connect();

Step 3: Observe the issue

Expected: Custom fetch function is called for all SSE requests, custom headers are added

Actual: Custom fetch function is NEVER called. SSE requests use the default global fetch without any customization.

Proof of Bug

You can verify this by adding logging to the custom fetch function:

const customFetch: typeof fetch = async (input, init) => {
  console.log('🔍 CUSTOM FETCH CALLED'); // This NEVER appears in logs
  return fetch(input, init);
};

When using MCPServerSSE, the log message never appears. When using MCPServerStreamableHttp with the same custom fetch, it works correctly.

Root Cause

The MCPServerSSE class (in NodeMCPServerSSE) accepts fetch in its params but the connect() method doesn't pass it to SSEClientTransport:

// In node_modules/@openai/agents-core/dist/shims/mcp-server/node.js
export class NodeMCPServerSSE {
  async connect() {
    const { SSEClientTransport } = await import('@modelcontextprotocol/sdk/client/sse.js');

    // BUG: this.params.fetch exists but is never passed to SSEClientTransport
    this.transport = new SSEClientTransport(new URL(this.params.url), {
      authProvider: this.params.authProvider,
      requestInit: this.params.requestInit,
      eventSourceInit: this.params.eventSourceInit,
      // fetch: this.params.fetch,  ← MISSING!
    });
  }
}

The underlying @modelcontextprotocol/sdk does support the fetch parameter in SSEClientTransport - the OpenAI SDK just isn't forwarding it.

Comparison with MCPServerStreamableHttp

The StreamableHttp transport correctly forwards the fetch parameter:

// This works correctly in NodeMCPServerStreamableHttp
this.transport = new StreamableHttpClientTransport({
  url: this.params.url,
  fetch: this.params.fetch,  // ✅ Correctly forwarded
});

Workaround

Until this is fixed, users must manually patch the SDK files:

node.js file patch:

// In node_modules/@openai/agents-core/dist/shims/mcp-server/node.js
this.transport = new SSEClientTransport(new URL(this.params.url), {
    authProvider: this.params.authProvider,
    requestInit: this.params.requestInit,
    eventSourceInit: this.params.eventSourceInit,
    fetch: this.params.fetch,  // Add this line
});

node.mjs file patch:

// In node_modules/@openai/agents-core/dist/shims/mcp-server/node.mjs
this.transport = new SSEClientTransport(new URL(this.params.url), {
    authProvider: this.params.authProvider,
    requestInit: this.params.requestInit,
    eventSourceInit: this.params.eventSourceInit,
    fetch: this.params.fetch,  // Add this line
});

Proposed Fix

Add fetch: this.params.fetch to both SSEClientTransport initialization calls:

Files to modify:

  1. packages/agents-core/src/shims/mcp-server/node.ts
  2. Ensure both .js and .mjs builds include the fix

Change:

  this.transport = new SSEClientTransport(new URL(this.params.url), {
      authProvider: this.params.authProvider,
      requestInit: this.params.requestInit,
      eventSourceInit: this.params.eventSourceInit,
+     fetch: this.params.fetch,
  });

Use Case Context

We discovered this bug while implementing authentication header propagation for internal MCP servers. Our use case:

  • Frontend sends authentication headers with conversation requests
  • Backend needs to forward these headers to MCP tool invocations
  • SSE-based MCP servers require these headers for authorization
  • Custom fetch function should inject headers into all MCP requests

Without this fix, SSE-based MCP servers cannot receive authentication headers, making them unusable in authenticated environments.

Testing

After applying the fix, this test should pass:

let fetchCallCount = 0;

const customFetch: typeof fetch = async (input, init) => {
  fetchCallCount++;
  return fetch(input, init);
};

const mcpServer = new MCPServerSSE({
  url: 'https://example.com/sse',
  fetch: customFetch,
});

await mcpServer.connect();
// Make a tool call that triggers an SSE request...

assert(fetchCallCount > 0, 'Custom fetch should be called for SSE requests');

Additional Notes

  • The bug exists in both CommonJS (.js) and ESM (.mjs) builds
  • The MCPServerSSEOptions type already includes fetch?: FetchLike, so the type signature is correct
  • The underlying @modelcontextprotocol/sdk supports the fetch parameter
  • This appears to be a simple oversight in forwarding constructor parameters

Environment

  • Node.js: 22.17.0
  • @openai/agents: 0.3.3
  • @openai/agents-core: 0.3.3
  • @modelcontextprotocol/sdk: 1.20.2

Expected Timeline: This is a one-line fix that would greatly improve the usability of SSE-based MCP servers in production environments requiring authentication.

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