From ad4b2f9cac22d57f8840f8bf01364db65c469f31 Mon Sep 17 00:00:00 2001 From: bhosmer-ant Date: Mon, 9 Mar 2026 14:05:30 -0400 Subject: [PATCH] Include requestInit options in GET SSE stream request (#1592) Co-authored-by: De Wildt van Reenen Co-authored-by: Matt <77928207+mattzcarey@users.noreply.github.com> Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com> --- packages/client/src/client/streamableHttp.ts | 1 + .../client/test/client/streamableHttp.test.ts | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/packages/client/src/client/streamableHttp.ts b/packages/client/src/client/streamableHttp.ts index 79a20adf..dab9b37a 100644 --- a/packages/client/src/client/streamableHttp.ts +++ b/packages/client/src/client/streamableHttp.ts @@ -222,6 +222,7 @@ export class StreamableHTTPClientTransport implements Transport { } const response = await (this._fetch ?? fetch)(this._url, { + ...this._requestInit, method: 'GET', headers, signal: this._abortController?.signal diff --git a/packages/client/test/client/streamableHttp.test.ts b/packages/client/test/client/streamableHttp.test.ts index 8a550fea..0398964d 100644 --- a/packages/client/test/client/streamableHttp.test.ts +++ b/packages/client/test/client/streamableHttp.test.ts @@ -425,6 +425,34 @@ describe('StreamableHTTPClientTransport', () => { expect(headers.get('last-event-id')).toBe('test-event-id'); }); + it('should include requestInit options (credentials, mode, etc.) in GET SSE request', async () => { + // Regression test for #895: POST and DELETE requests spread _requestInit but the + // GET SSE request did not, so non-header options like credentials were dropped. + vi.clearAllMocks(); + + transport = new StreamableHTTPClientTransport(new URL('http://localhost:1234/mcp'), { + requestInit: { credentials: 'include', mode: 'cors' } + }); + + const fetchSpy = globalThis.fetch as Mock; + fetchSpy.mockReset(); + fetchSpy.mockResolvedValue({ + ok: true, + status: 200, + headers: new Headers({ 'content-type': 'text/event-stream' }), + body: new ReadableStream() + }); + + await transport.start(); + await (transport as unknown as { _startOrAuthSse: (opts: StartSSEOptions) => Promise })._startOrAuthSse({}); + + expect(fetchSpy).toHaveBeenCalled(); + const init = fetchSpy.mock.calls[0]![1]; + expect(init.method).toBe('GET'); + expect(init.credentials).toBe('include'); + expect(init.mode).toBe('cors'); + }); + it('should throw error when invalid content-type is received', async () => { // Clear any previous state from other tests vi.clearAllMocks();