Skip to content

Commit 7bc57da

Browse files
committed
move to Headers object
1 parent f82c997 commit 7bc57da

File tree

8 files changed

+46
-16
lines changed

8 files changed

+46
-16
lines changed

packages/core/src/types/types.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,19 +2384,14 @@ type Flatten<T> = T extends Primitive
23842384

23852385
type Infer<Schema extends z.ZodTypeAny> = Flatten<z.infer<Schema>>;
23862386

2387-
/**
2388-
* Headers that are compatible with both Node.js and the browser.
2389-
*/
2390-
export type IsomorphicHeaders = Record<string, string | string[] | undefined>;
2391-
23922387
/**
23932388
* Information about the incoming request.
23942389
*/
23952390
export interface RequestInfo {
23962391
/**
23972392
* The headers of the request.
23982393
*/
2399-
headers: IsomorphicHeaders;
2394+
headers: Headers;
24002395
}
24012396

24022397
/**
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type { IncomingHttpHeaders } from 'node:http';
2+
3+
/**
4+
* Converts a Node.js IncomingHttpHeaders object to a Web Headers object.
5+
* @param h - The Node.js IncomingHttpHeaders object.
6+
* @returns The Web Headers object.
7+
*/
8+
export function nodeHeadersToWebHeaders(h: IncomingHttpHeaders): Headers {
9+
const out = new Headers();
10+
11+
for (const [name, value] of Object.entries(h)) {
12+
if (value === undefined) continue;
13+
14+
// Node may surface set-cookie as string[]
15+
if (name.toLowerCase() === 'set-cookie') {
16+
if (Array.isArray(value)) {
17+
for (const v of value) out.append('set-cookie', v);
18+
} else {
19+
out.append('set-cookie', value);
20+
}
21+
continue;
22+
}
23+
24+
if (Array.isArray(value)) {
25+
// Most headers can be joined; append preserves multiple values too.
26+
for (const v of value) out.append(name, v);
27+
} else {
28+
out.set(name, value);
29+
}
30+
}
31+
32+
return out;
33+
}

packages/server/src/server/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ export class Server<
168168
if (this._capabilities.logging) {
169169
this.setRequestHandler(SetLevelRequestSchema, async (request, extra) => {
170170
const transportSessionId: string | undefined =
171-
extra.sessionId || (extra.requestInfo?.headers['mcp-session-id'] as string) || undefined;
171+
extra.sessionId || (extra.requestInfo?.headers.get('mcp-session-id') as string) || undefined;
172172
const { level } = request.params;
173173
const parseResult = LoggingLevelSchema.safeParse(level);
174174
if (parseResult.success) {

packages/server/src/server/sse.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { JSONRPCMessageSchema } from '@modelcontextprotocol/core';
77
import contentType from 'content-type';
88
import getRawBody from 'raw-body';
99

10+
import { nodeHeadersToWebHeaders } from './helper/headers.js';
11+
1012
const MAXIMUM_MESSAGE_SIZE = '4mb';
1113

1214
/**
@@ -149,7 +151,7 @@ export class SSEServerTransport implements Transport {
149151
}
150152

151153
const authInfo: AuthInfo | undefined = req.auth;
152-
const requestInfo: RequestInfo = { headers: req.headers };
154+
const requestInfo: RequestInfo = { headers: nodeHeadersToWebHeaders(req.headers) };
153155

154156
let body: string | unknown;
155157
try {

packages/server/src/server/webStandardStreamableHttp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,7 +596,7 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
596596

597597
// Build request info from headers
598598
const requestInfo: RequestInfo = {
599-
headers: Object.fromEntries(req.headers.entries())
599+
headers: req.headers
600600
};
601601

602602
let rawMessage;

packages/server/test/server/sse.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
303303
{
304304
type: 'text',
305305
text: JSON.stringify({
306-
headers: {
306+
headers: new Headers({
307307
host: `127.0.0.1:${serverPort}`,
308308
connection: 'keep-alive',
309309
'content-type': 'application/json',
@@ -313,7 +313,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
313313
'user-agent': 'node',
314314
'accept-encoding': 'gzip, deflate',
315315
'content-length': '124'
316-
}
316+
})
317317
})
318318
}
319319
]
@@ -416,9 +416,9 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
416416
token: 'test-token'
417417
},
418418
requestInfo: {
419-
headers: {
419+
headers: new Headers({
420420
'content-type': 'application/json'
421-
}
421+
})
422422
}
423423
}
424424
);

packages/server/test/server/streamableHttp.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
445445

446446
const requestInfo = JSON.parse(eventData.result.content[1].text);
447447
expect(requestInfo).toMatchObject({
448-
headers: {
448+
headers: new Headers({
449449
'content-type': 'application/json',
450450
accept: 'application/json, text/event-stream',
451451
connection: 'keep-alive',
@@ -454,7 +454,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
454454
'user-agent': expect.any(String),
455455
'accept-encoding': expect.any(String),
456456
'content-length': expect.any(String)
457-
}
457+
})
458458
});
459459
});
460460

test/integration/test/taskResumability.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ import { randomUUID } from 'node:crypto';
22
import { createServer, type Server } from 'node:http';
33

44
import { Client, StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
5+
import type { EventStore, JSONRPCMessage } from '@modelcontextprotocol/server';
56
import {
67
CallToolResultSchema,
78
LoggingMessageNotificationSchema,
89
McpServer,
910
StreamableHTTPServerTransport
1011
} from '@modelcontextprotocol/server';
11-
import type { EventStore, JSONRPCMessage } from '@modelcontextprotocol/server';
1212
import type { ZodMatrixEntry } from '@modelcontextprotocol/test-helpers';
1313
import { listenOnRandomPort, zodTestMatrix } from '@modelcontextprotocol/test-helpers';
1414

0 commit comments

Comments
 (0)