Skip to content

Commit be063e4

Browse files
committed
fix: extra Headers when they are a Headers object
1 parent 590d484 commit be063e4

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

src/client/streamableHttp.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,37 @@ describe("StreamableHTTPClientTransport", () => {
476476
expect(global.fetch).toHaveBeenCalledTimes(2);
477477
});
478478

479+
it("should always send specified custom headers (Headers class)", async () => {
480+
const requestInit = {
481+
headers: new Headers({
482+
"X-Custom-Header": "CustomValue"
483+
})
484+
};
485+
transport = new StreamableHTTPClientTransport(new URL("http://localhost:1234/mcp"), {
486+
requestInit: requestInit
487+
});
488+
489+
let actualReqInit: RequestInit = {};
490+
491+
((global.fetch as jest.Mock)).mockImplementation(
492+
async (_url, reqInit) => {
493+
actualReqInit = reqInit;
494+
return new Response(null, { status: 200, headers: { "content-type": "text/event-stream" } });
495+
}
496+
);
497+
498+
await transport.start();
499+
500+
await transport["_startOrAuthSse"]({});
501+
expect((actualReqInit.headers as Headers).get("x-custom-header")).toBe("CustomValue");
502+
503+
(requestInit.headers as Headers).set("X-Custom-Header","SecondCustomValue");
504+
505+
await transport.send({ jsonrpc: "2.0", method: "test", params: {} } as JSONRPCMessage);
506+
expect((actualReqInit.headers as Headers).get("x-custom-header")).toBe("SecondCustomValue");
507+
508+
expect(global.fetch).toHaveBeenCalledTimes(2);
509+
});
479510

480511
it("should have exponential backoff with configurable maxRetries", () => {
481512
// This test verifies the maxRetries and backoff calculation directly

src/client/streamableHttp.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,12 @@ export class StreamableHTTPClientTransport implements Transport {
174174
headers["mcp-session-id"] = this._sessionId;
175175
}
176176

177-
return new Headers(
178-
{ ...headers, ...this._requestInit?.headers }
179-
);
177+
const extraHeaders = this._normalizeHeaders(this._requestInit?.headers);
178+
179+
return new Headers({
180+
...headers,
181+
...extraHeaders,
182+
});
180183
}
181184

182185

@@ -242,6 +245,20 @@ export class StreamableHTTPClientTransport implements Transport {
242245

243246
}
244247

248+
private _normalizeHeaders(headers: HeadersInit | undefined): Record<string, string> {
249+
if (!headers) return {};
250+
251+
if (headers instanceof Headers) {
252+
return Object.fromEntries(headers.entries());
253+
}
254+
255+
if (Array.isArray(headers)) {
256+
return Object.fromEntries(headers);
257+
}
258+
259+
return { ...headers as Record<string, string> };
260+
}
261+
245262
/**
246263
* Schedule a reconnection attempt with exponential backoff
247264
*

0 commit comments

Comments
 (0)