Skip to content

Commit e5786e1

Browse files
committed
Add SSE polling Phase 2 and Phase 3 tests (SEP-1699)
Add two new test phases to the SSE polling scenario: Phase 2: Event Replay Test (test_event_replay) - Tests that server properly stores and replays events sent during disconnect - Server sends notification1, closes stream, sends notification2 and notification3 - Client should receive all notifications via event replay Phase 3: Multiple Reconnections Test (test_multiple_reconnections) - Tests that server can close stream multiple times during single tool call - Validates proper event store management across multiple reconnections Also adds corresponding tools to everything-server.ts.
1 parent e4cb55e commit e5786e1

File tree

2 files changed

+691
-1
lines changed

2 files changed

+691
-1
lines changed

examples/servers/typescript/everything-server.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,141 @@ function createMcpServer() {
389389
}
390390
);
391391

392+
// SEP-1699: Event replay test tool - closes stream mid-call, sends more events, tests replay
393+
mcpServer.registerTool(
394+
'test_event_replay',
395+
{
396+
description:
397+
'Tests SSE event replay after disconnection (SEP-1699). Sends notification1, closes stream, sends notification2 and notification3, then returns. Client should receive all notifications via event replay.',
398+
inputSchema: {}
399+
},
400+
async (_args, { sessionId, requestId, sendNotification }) => {
401+
const sleep = (ms: number) =>
402+
new Promise((resolve) => setTimeout(resolve, ms));
403+
404+
console.log(`[${sessionId}] Starting test_event_replay tool...`);
405+
406+
// Send notification1 before closing
407+
await sendNotification({
408+
method: 'notifications/message',
409+
params: {
410+
level: 'info',
411+
data: 'notification1'
412+
}
413+
});
414+
console.log(`[${sessionId}] Sent notification1`);
415+
416+
// Get the transport for this session
417+
const transport = sessionId ? transports[sessionId] : undefined;
418+
if (transport && requestId) {
419+
// Close the SSE stream to trigger client reconnection
420+
console.log(`[${sessionId}] Closing SSE stream...`);
421+
transport.closeSSEStream(requestId);
422+
}
423+
424+
// Wait a bit for stream to close
425+
await sleep(100);
426+
427+
// Send notification2 and notification3 (should be stored in event store)
428+
await sendNotification({
429+
method: 'notifications/message',
430+
params: {
431+
level: 'info',
432+
data: 'notification2'
433+
}
434+
});
435+
console.log(`[${sessionId}] Sent notification2 (stored for replay)`);
436+
437+
await sendNotification({
438+
method: 'notifications/message',
439+
params: {
440+
level: 'info',
441+
data: 'notification3'
442+
}
443+
});
444+
console.log(`[${sessionId}] Sent notification3 (stored for replay)`);
445+
446+
// Wait for client to reconnect
447+
await sleep(200);
448+
449+
console.log(`[${sessionId}] test_event_replay tool complete`);
450+
451+
return {
452+
content: [
453+
{
454+
type: 'text',
455+
text: 'Event replay test completed. You should have received notification1, notification2, and notification3.'
456+
}
457+
]
458+
};
459+
}
460+
);
461+
462+
// SEP-1699: Multiple reconnections test tool - closes stream multiple times
463+
mcpServer.registerTool(
464+
'test_multiple_reconnections',
465+
{
466+
description:
467+
'Tests multiple SSE stream closures during single tool call (SEP-1699). Sends checkpoint notifications and closes stream at each checkpoint.',
468+
inputSchema: {
469+
checkpoints: z
470+
.number()
471+
.min(1)
472+
.max(10)
473+
.default(3)
474+
.describe('Number of checkpoints (stream closures)')
475+
}
476+
},
477+
async (
478+
args: { checkpoints?: number },
479+
{ sessionId, requestId, sendNotification }
480+
) => {
481+
const sleep = (ms: number) =>
482+
new Promise((resolve) => setTimeout(resolve, ms));
483+
484+
const numCheckpoints = args.checkpoints ?? 3;
485+
console.log(
486+
`[${sessionId}] Starting test_multiple_reconnections with ${numCheckpoints} checkpoints...`
487+
);
488+
489+
const transport = sessionId ? transports[sessionId] : undefined;
490+
491+
for (let i = 0; i < numCheckpoints; i++) {
492+
// Send checkpoint notification
493+
await sendNotification({
494+
method: 'notifications/message',
495+
params: {
496+
level: 'info',
497+
data: `checkpoint_${i}`
498+
}
499+
});
500+
console.log(`[${sessionId}] Sent checkpoint_${i}`);
501+
502+
// Close the SSE stream
503+
if (transport && requestId) {
504+
console.log(
505+
`[${sessionId}] Closing SSE stream at checkpoint ${i}...`
506+
);
507+
transport.closeSSEStream(requestId);
508+
}
509+
510+
// Wait for client to reconnect (should respect retry field)
511+
await sleep(200);
512+
}
513+
514+
console.log(`[${sessionId}] test_multiple_reconnections tool complete`);
515+
516+
return {
517+
content: [
518+
{
519+
type: 'text',
520+
text: `Completed ${numCheckpoints} checkpoints with stream closures. You should have received all checkpoint notifications.`
521+
}
522+
]
523+
};
524+
}
525+
);
526+
392527
// Sampling tool - requests LLM completion from client
393528
mcpServer.registerTool(
394529
'test_sampling',

0 commit comments

Comments
 (0)