@@ -1802,6 +1802,120 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
18021802 // Clean up - resolve the tool promise
18031803 toolResolve ! ( ) ;
18041804 } ) ;
1805+
1806+ it ( 'should provide closeSSEStream callback in extra when eventStore is configured' , async ( ) => {
1807+ const result = await createTestServer ( {
1808+ sessionIdGenerator : ( ) => randomUUID ( ) ,
1809+ eventStore : createEventStore ( ) ,
1810+ retryInterval : 1000
1811+ } ) ;
1812+ server = result . server ;
1813+ transport = result . transport ;
1814+ baseUrl = result . baseUrl ;
1815+ mcpServer = result . mcpServer ;
1816+
1817+ // Track whether closeSSEStream callback was provided
1818+ let receivedCloseSSEStream : ( ( ) => void ) | undefined ;
1819+
1820+ // Register a tool that captures the extra.closeSSEStream callback
1821+ mcpServer . tool ( 'test-callback-tool' , 'Test tool' , { } , async ( _args , extra ) => {
1822+ receivedCloseSSEStream = extra . closeSSEStream ;
1823+ return { content : [ { type : 'text' , text : 'Done' } ] } ;
1824+ } ) ;
1825+
1826+ // Initialize to get session ID
1827+ const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
1828+ sessionId = initResponse . headers . get ( 'mcp-session-id' ) as string ;
1829+ expect ( sessionId ) . toBeDefined ( ) ;
1830+
1831+ // Call the tool
1832+ const toolCallRequest : JSONRPCMessage = {
1833+ jsonrpc : '2.0' ,
1834+ id : 200 ,
1835+ method : 'tools/call' ,
1836+ params : { name : 'test-callback-tool' , arguments : { } }
1837+ } ;
1838+
1839+ const postResponse = await fetch ( baseUrl , {
1840+ method : 'POST' ,
1841+ headers : {
1842+ 'Content-Type' : 'application/json' ,
1843+ Accept : 'text/event-stream, application/json' ,
1844+ 'mcp-session-id' : sessionId ,
1845+ 'mcp-protocol-version' : '2025-03-26'
1846+ } ,
1847+ body : JSON . stringify ( toolCallRequest )
1848+ } ) ;
1849+
1850+ expect ( postResponse . status ) . toBe ( 200 ) ;
1851+
1852+ // Read all events to completion
1853+ const reader = postResponse . body ?. getReader ( ) ;
1854+ while ( true ) {
1855+ const { done } = await reader ! . read ( ) ;
1856+ if ( done ) break ;
1857+ }
1858+
1859+ // Verify closeSSEStream callback was provided
1860+ expect ( receivedCloseSSEStream ) . toBeDefined ( ) ;
1861+ expect ( typeof receivedCloseSSEStream ) . toBe ( 'function' ) ;
1862+ } ) ;
1863+
1864+ it ( 'should NOT provide closeSSEStream callback when eventStore is NOT configured' , async ( ) => {
1865+ const result = await createTestServer ( {
1866+ sessionIdGenerator : ( ) => randomUUID ( )
1867+ // No eventStore
1868+ } ) ;
1869+ server = result . server ;
1870+ transport = result . transport ;
1871+ baseUrl = result . baseUrl ;
1872+ mcpServer = result . mcpServer ;
1873+
1874+ // Track whether closeSSEStream callback was provided
1875+ let receivedCloseSSEStream : ( ( ) => void ) | undefined ;
1876+
1877+ // Register a tool that captures the extra.closeSSEStream callback
1878+ mcpServer . tool ( 'test-no-callback-tool' , 'Test tool' , { } , async ( _args , extra ) => {
1879+ receivedCloseSSEStream = extra . closeSSEStream ;
1880+ return { content : [ { type : 'text' , text : 'Done' } ] } ;
1881+ } ) ;
1882+
1883+ // Initialize to get session ID
1884+ const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
1885+ sessionId = initResponse . headers . get ( 'mcp-session-id' ) as string ;
1886+ expect ( sessionId ) . toBeDefined ( ) ;
1887+
1888+ // Call the tool
1889+ const toolCallRequest : JSONRPCMessage = {
1890+ jsonrpc : '2.0' ,
1891+ id : 201 ,
1892+ method : 'tools/call' ,
1893+ params : { name : 'test-no-callback-tool' , arguments : { } }
1894+ } ;
1895+
1896+ const postResponse = await fetch ( baseUrl , {
1897+ method : 'POST' ,
1898+ headers : {
1899+ 'Content-Type' : 'application/json' ,
1900+ Accept : 'text/event-stream, application/json' ,
1901+ 'mcp-session-id' : sessionId ,
1902+ 'mcp-protocol-version' : '2025-03-26'
1903+ } ,
1904+ body : JSON . stringify ( toolCallRequest )
1905+ } ) ;
1906+
1907+ expect ( postResponse . status ) . toBe ( 200 ) ;
1908+
1909+ // Read all events to completion
1910+ const reader = postResponse . body ?. getReader ( ) ;
1911+ while ( true ) {
1912+ const { done } = await reader ! . read ( ) ;
1913+ if ( done ) break ;
1914+ }
1915+
1916+ // Verify closeSSEStream callback was NOT provided
1917+ expect ( receivedCloseSSEStream ) . toBeUndefined ( ) ;
1918+ } ) ;
18051919 } ) ;
18061920
18071921 // Test onsessionclosed callback
0 commit comments