-
Notifications
You must be signed in to change notification settings - Fork 487
Description
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:
packages/agents-core/src/shims/mcp-server/node.ts- Ensure both
.jsand.mjsbuilds 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
MCPServerSSEOptionstype already includesfetch?: FetchLike, so the type signature is correct - The underlying
@modelcontextprotocol/sdksupports thefetchparameter - 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.