Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e3bb99c

Browse files
committed
remove the use of enableSessionManagement
1 parent b069719 commit e3bb99c

File tree

2 files changed

+104
-127
lines changed

2 files changed

+104
-127
lines changed

src/server/streamable-http.test.ts

+60-81
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ import { IncomingMessage, ServerResponse } from "node:http";
22
import { StreamableHTTPServerTransport } from "./streamable-http.js";
33
import { JSONRPCMessage } from "../types.js";
44
import { Readable } from "node:stream";
5-
5+
import { randomUUID } from "node:crypto";
66
// Mock IncomingMessage
77
function createMockRequest(options: {
88
method: string;
99
headers: Record<string, string | string[] | undefined>;
1010
body?: string;
1111
}): IncomingMessage {
1212
const readable = new Readable();
13-
readable._read = () => {};
13+
readable._read = () => { };
1414
if (options.body) {
1515
readable.push(options.body);
1616
readable.push(null);
@@ -37,12 +37,13 @@ function createMockResponse(): jest.Mocked<ServerResponse> {
3737
}
3838

3939
describe("StreamableHTTPServerTransport", () => {
40-
const endpoint = "/mcp";
4140
let transport: StreamableHTTPServerTransport;
4241
let mockResponse: jest.Mocked<ServerResponse>;
4342

4443
beforeEach(() => {
45-
transport = new StreamableHTTPServerTransport(endpoint);
44+
transport = new StreamableHTTPServerTransport({
45+
sessionId: randomUUID(),
46+
});
4647
mockResponse = createMockResponse();
4748
});
4849

@@ -61,7 +62,7 @@ describe("StreamableHTTPServerTransport", () => {
6162
const initializeMessage: JSONRPCMessage = {
6263
jsonrpc: "2.0",
6364
method: "initialize",
64-
params: {
65+
params: {
6566
clientInfo: { name: "test-client", version: "1.0" },
6667
protocolVersion: "2025-03-26"
6768
},
@@ -119,49 +120,13 @@ describe("StreamableHTTPServerTransport", () => {
119120
expect(mockResponse.end).toHaveBeenCalledWith(expect.stringContaining('"jsonrpc":"2.0"'));
120121
expect(mockResponse.end).toHaveBeenCalledWith(expect.stringContaining('"message":"Bad Request: Mcp-Session-Id header is required"'));
121122
});
122-
123-
it("should always include session ID in initialization response even in stateless mode", async () => {
124-
// Create a stateless transport for this test
125-
const statelessTransport = new StreamableHTTPServerTransport(endpoint, { enableSessionManagement: false });
126-
127-
// Create an initialization request
128-
const initializeMessage: JSONRPCMessage = {
129-
jsonrpc: "2.0",
130-
method: "initialize",
131-
params: {
132-
clientInfo: { name: "test-client", version: "1.0" },
133-
protocolVersion: "2025-03-26"
134-
},
135-
id: "init-1",
136-
};
137-
138-
const req = createMockRequest({
139-
method: "POST",
140-
headers: {
141-
"content-type": "application/json",
142-
"accept": "application/json",
143-
},
144-
body: JSON.stringify(initializeMessage),
145-
});
146-
147-
await statelessTransport.handleRequest(req, mockResponse);
148-
149-
// In stateless mode, session ID should also be included for initialize responses
150-
expect(mockResponse.writeHead).toHaveBeenCalledWith(
151-
200,
152-
expect.objectContaining({
153-
"mcp-session-id": statelessTransport.sessionId,
154-
})
155-
);
156-
});
157123
});
158-
159124
describe("Stateless Mode", () => {
160125
let statelessTransport: StreamableHTTPServerTransport;
161126
let mockResponse: jest.Mocked<ServerResponse>;
162127

163128
beforeEach(() => {
164-
statelessTransport = new StreamableHTTPServerTransport(endpoint, { enableSessionManagement: false });
129+
statelessTransport = new StreamableHTTPServerTransport({ sessionId: undefined });
165130
mockResponse = createMockResponse();
166131
});
167132

@@ -268,7 +233,7 @@ describe("StreamableHTTPServerTransport", () => {
268233
});
269234

270235
await statelessTransport.handleRequest(req2, mockResponse);
271-
236+
272237
// Should still succeed
273238
expect(mockResponse.writeHead).toHaveBeenCalledWith(
274239
200,
@@ -278,12 +243,12 @@ describe("StreamableHTTPServerTransport", () => {
278243
);
279244
});
280245

281-
it("should handle initialization requests properly in both modes", async () => {
246+
it("should handle initialization requests properly in statefull mode", async () => {
282247
// Initialize message that would typically be sent during initialization
283248
const initializeMessage: JSONRPCMessage = {
284249
jsonrpc: "2.0",
285250
method: "initialize",
286-
params: {
251+
params: {
287252
clientInfo: { name: "test-client", version: "1.0" },
288253
protocolVersion: "2025-03-26"
289254
},
@@ -301,17 +266,27 @@ describe("StreamableHTTPServerTransport", () => {
301266
});
302267

303268
await transport.handleRequest(statefulReq, mockResponse);
304-
269+
305270
// In stateful mode, session ID should be included in the response header
306271
expect(mockResponse.writeHead).toHaveBeenCalledWith(
307272
200,
308273
expect.objectContaining({
309274
"mcp-session-id": transport.sessionId,
310275
})
311276
);
277+
});
312278

313-
// Reset mocks for stateless test
314-
mockResponse.writeHead.mockClear();
279+
it("should handle initialization requests properly in stateless mode", async () => {
280+
// Initialize message that would typically be sent during initialization
281+
const initializeMessage: JSONRPCMessage = {
282+
jsonrpc: "2.0",
283+
method: "initialize",
284+
params: {
285+
clientInfo: { name: "test-client", version: "1.0" },
286+
protocolVersion: "2025-03-26"
287+
},
288+
id: "init-1",
289+
};
315290

316291
// Test stateless transport
317292
const statelessReq = createMockRequest({
@@ -324,10 +299,11 @@ describe("StreamableHTTPServerTransport", () => {
324299
});
325300

326301
await statelessTransport.handleRequest(statelessReq, mockResponse);
327-
302+
328303
// In stateless mode, session ID should also be included for initialize responses
329304
const headers = mockResponse.writeHead.mock.calls[0][1];
330-
expect(headers).toHaveProperty("mcp-session-id", statelessTransport.sessionId);
305+
expect(headers).not.toHaveProperty("mcp-session-id");
306+
331307
});
332308
});
333309

@@ -519,14 +495,14 @@ describe("StreamableHTTPServerTransport", () => {
519495

520496
// Send a message to first connection
521497
const message1: JSONRPCMessage = {
522-
jsonrpc: "2.0",
523-
method: "test1",
524-
params: {},
498+
jsonrpc: "2.0",
499+
method: "test1",
500+
params: {},
525501
id: 1
526502
};
527-
503+
528504
await transport.send(message1);
529-
505+
530506
// Get message ID (captured from write call)
531507
const writeCall = mockResponse.write.mock.calls[0][0] as string;
532508
const idMatch = writeCall.match(/id: ([a-f0-9-]+)/);
@@ -550,12 +526,12 @@ describe("StreamableHTTPServerTransport", () => {
550526

551527
// Send a second message
552528
const message2: JSONRPCMessage = {
553-
jsonrpc: "2.0",
554-
method: "test2",
555-
params: {},
529+
jsonrpc: "2.0",
530+
method: "test2",
531+
params: {},
556532
id: 2
557533
};
558-
534+
559535
await transport.send(message2);
560536

561537
// Verify the second message was received by both connections
@@ -596,7 +572,7 @@ describe("StreamableHTTPServerTransport", () => {
596572
params: {},
597573
id: "test-id",
598574
};
599-
575+
600576
const reqPost = createMockRequest({
601577
method: "POST",
602578
headers: {
@@ -605,28 +581,28 @@ describe("StreamableHTTPServerTransport", () => {
605581
},
606582
body: JSON.stringify(requestMessage),
607583
});
608-
584+
609585
await transport.handleRequest(reqPost, mockResponse1);
610-
586+
611587
// Send a response with matching ID
612588
const responseMessage: JSONRPCMessage = {
613589
jsonrpc: "2.0",
614590
result: { success: true },
615591
id: "test-id",
616592
};
617-
593+
618594
await transport.send(responseMessage);
619-
595+
620596
// Verify response was sent to the right connection
621597
expect(mockResponse1.write).toHaveBeenCalledWith(
622598
expect.stringContaining(JSON.stringify(responseMessage))
623599
);
624-
600+
625601
// Check if write was called with this exact message on the second connection
626-
const writeCallsOnSecondConn = mockResponse2.write.mock.calls.filter(call =>
602+
const writeCallsOnSecondConn = mockResponse2.write.mock.calls.filter(call =>
627603
typeof call[0] === 'string' && call[0].includes(JSON.stringify(responseMessage))
628604
);
629-
605+
630606
// Verify the response wasn't broadcast to all connections
631607
expect(writeCallsOnSecondConn.length).toBe(0);
632608
});
@@ -680,7 +656,7 @@ describe("StreamableHTTPServerTransport", () => {
680656
const message: JSONRPCMessage = {
681657
jsonrpc: "2.0",
682658
method: "initialize",
683-
params: {
659+
params: {
684660
clientInfo: { name: "test-client", version: "1.0" },
685661
protocolVersion: "2025-03-26"
686662
},
@@ -715,17 +691,17 @@ describe("StreamableHTTPServerTransport", () => {
715691

716692
it("should handle pre-parsed batch messages", async () => {
717693
const batchMessages: JSONRPCMessage[] = [
718-
{
719-
jsonrpc: "2.0",
720-
method: "method1",
694+
{
695+
jsonrpc: "2.0",
696+
method: "method1",
721697
params: { data: "test1" },
722-
id: "batch1"
698+
id: "batch1"
723699
},
724-
{
725-
jsonrpc: "2.0",
726-
method: "method2",
700+
{
701+
jsonrpc: "2.0",
702+
method: "method2",
727703
params: { data: "test2" },
728-
id: "batch2"
704+
id: "batch2"
729705
},
730706
];
731707

@@ -800,7 +776,7 @@ describe("StreamableHTTPServerTransport", () => {
800776
let mockResponse: jest.Mocked<ServerResponse>;
801777

802778
beforeEach(() => {
803-
transportWithHeaders = new StreamableHTTPServerTransport(endpoint, { customHeaders });
779+
transportWithHeaders = new StreamableHTTPServerTransport({ sessionId: randomUUID(), customHeaders });
804780
mockResponse = createMockResponse();
805781
});
806782

@@ -875,9 +851,10 @@ describe("StreamableHTTPServerTransport", () => {
875851
});
876852

877853
it("should not override essential headers with custom headers", async () => {
878-
const transportWithConflictingHeaders = new StreamableHTTPServerTransport(endpoint, {
854+
const transportWithConflictingHeaders = new StreamableHTTPServerTransport({
855+
sessionId: randomUUID(),
879856
customHeaders: {
880-
"Content-Type": "text/plain", // 尝试覆盖必要的 Content-Type 头
857+
"Content-Type": "text/plain",
881858
"X-Custom-Header": "custom-value"
882859
}
883860
});
@@ -902,8 +879,10 @@ describe("StreamableHTTPServerTransport", () => {
902879
});
903880

904881
it("should work with empty custom headers", async () => {
905-
const transportWithoutHeaders = new StreamableHTTPServerTransport(endpoint);
906-
882+
const transportWithoutHeaders = new StreamableHTTPServerTransport({
883+
sessionId: randomUUID(),
884+
});
885+
907886
const req = createMockRequest({
908887
method: "GET",
909888
headers: {

0 commit comments

Comments
 (0)