@@ -1592,12 +1592,13 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
15921592 } ) ;
15931593
15941594 // Test SSE priming events for POST streams
1595- describe ( 'StreamableHTTPServerTransport POST SSE priming events' , ( ) => {
1595+ // NOTE: Priming events are DISABLED in 1.23.1 to fix backwards compatibility issues.
1596+ // Clients in the 1.23.x line cannot handle empty SSE data (they crash on JSON.parse("")).
1597+ describe ( 'StreamableHTTPServerTransport POST SSE priming events (DISABLED in 1.23.1)' , ( ) => {
15961598 let server : Server ;
15971599 let transport : StreamableHTTPServerTransport ;
15981600 let baseUrl : URL ;
15991601 let sessionId : string ;
1600- let mcpServer : McpServer ;
16011602
16021603 // Simple eventStore for priming event tests
16031604 const createEventStore = ( ) : EventStore => {
@@ -1641,7 +1642,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
16411642 }
16421643 } ) ;
16431644
1644- it ( 'should send priming event with retry field on POST SSE stream ' , async ( ) => {
1645+ it ( 'should NOT send priming events (disabled in 1.23.1 for backwards compatibility) ' , async ( ) => {
16451646 const result = await createTestServer ( {
16461647 sessionIdGenerator : ( ) => randomUUID ( ) ,
16471648 eventStore : createEventStore ( ) ,
@@ -1650,7 +1651,6 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
16501651 server = result . server ;
16511652 transport = result . transport ;
16521653 baseUrl = result . baseUrl ;
1653- mcpServer = result . mcpServer ;
16541654
16551655 // Initialize to get session ID
16561656 const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
@@ -1671,136 +1671,23 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
16711671 'Content-Type' : 'application/json' ,
16721672 Accept : 'text/event-stream, application/json' ,
16731673 'mcp-session-id' : sessionId ,
1674- 'mcp-protocol-version' : '2025-03-26 '
1674+ 'mcp-protocol-version' : '2025-06-18 '
16751675 } ,
16761676 body : JSON . stringify ( toolCallRequest )
16771677 } ) ;
16781678
16791679 expect ( postResponse . status ) . toBe ( 200 ) ;
16801680 expect ( postResponse . headers . get ( 'content-type' ) ) . toBe ( 'text/event-stream' ) ;
16811681
1682- // Read the priming event
1682+ // Read the first chunk - should be the actual response, not a priming event
16831683 const reader = postResponse . body ?. getReader ( ) ;
16841684 const { value } = await reader ! . read ( ) ;
16851685 const text = new TextDecoder ( ) . decode ( value ) ;
16861686
1687- // Verify priming event has id and retry field
1688- expect ( text ) . toContain ( 'id: ' ) ;
1689- expect ( text ) . toContain ( 'retry: 5000' ) ;
1690- expect ( text ) . toContain ( 'data: ' ) ;
1691- } ) ;
1692-
1693- it ( 'should send priming event without retry field when retryInterval is not configured' , async ( ) => {
1694- const result = await createTestServer ( {
1695- sessionIdGenerator : ( ) => randomUUID ( ) ,
1696- eventStore : createEventStore ( )
1697- // No retryInterval
1698- } ) ;
1699- server = result . server ;
1700- transport = result . transport ;
1701- baseUrl = result . baseUrl ;
1702- mcpServer = result . mcpServer ;
1703-
1704- // Initialize to get session ID
1705- const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
1706- sessionId = initResponse . headers . get ( 'mcp-session-id' ) as string ;
1707- expect ( sessionId ) . toBeDefined ( ) ;
1708-
1709- // Send a tool call request
1710- const toolCallRequest : JSONRPCMessage = {
1711- jsonrpc : '2.0' ,
1712- id : 100 ,
1713- method : 'tools/call' ,
1714- params : { name : 'greet' , arguments : { name : 'Test' } }
1715- } ;
1716-
1717- const postResponse = await fetch ( baseUrl , {
1718- method : 'POST' ,
1719- headers : {
1720- 'Content-Type' : 'application/json' ,
1721- Accept : 'text/event-stream, application/json' ,
1722- 'mcp-session-id' : sessionId ,
1723- 'mcp-protocol-version' : '2025-03-26'
1724- } ,
1725- body : JSON . stringify ( toolCallRequest )
1726- } ) ;
1727-
1728- expect ( postResponse . status ) . toBe ( 200 ) ;
1729-
1730- // Read the priming event
1731- const reader = postResponse . body ?. getReader ( ) ;
1732- const { value } = await reader ! . read ( ) ;
1733- const text = new TextDecoder ( ) . decode ( value ) ;
1734-
1735- // Priming event should have id field but NOT retry field
1736- expect ( text ) . toContain ( 'id: ' ) ;
1737- expect ( text ) . toContain ( 'data: ' ) ;
1738- expect ( text ) . not . toContain ( 'retry:' ) ;
1739- } ) ;
1740-
1741- it ( 'should close POST SSE stream when closeSseStream is called' , async ( ) => {
1742- const result = await createTestServer ( {
1743- sessionIdGenerator : ( ) => randomUUID ( ) ,
1744- eventStore : createEventStore ( ) ,
1745- retryInterval : 1000
1746- } ) ;
1747- server = result . server ;
1748- transport = result . transport ;
1749- baseUrl = result . baseUrl ;
1750- mcpServer = result . mcpServer ;
1751-
1752- // Track tool execution state
1753- let toolResolve : ( ) => void ;
1754- const toolPromise = new Promise < void > ( resolve => {
1755- toolResolve = resolve ;
1756- } ) ;
1757-
1758- // Register a blocking tool
1759- mcpServer . tool ( 'blocking-tool' , 'A blocking tool' , { } , async ( ) => {
1760- await toolPromise ;
1761- return { content : [ { type : 'text' , text : 'Done' } ] } ;
1762- } ) ;
1763-
1764- // Initialize to get session ID
1765- const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
1766- sessionId = initResponse . headers . get ( 'mcp-session-id' ) as string ;
1767- expect ( sessionId ) . toBeDefined ( ) ;
1768-
1769- // Send a tool call request
1770- const toolCallRequest : JSONRPCMessage = {
1771- jsonrpc : '2.0' ,
1772- id : 100 ,
1773- method : 'tools/call' ,
1774- params : { name : 'blocking-tool' , arguments : { } }
1775- } ;
1776-
1777- const postResponse = await fetch ( baseUrl , {
1778- method : 'POST' ,
1779- headers : {
1780- 'Content-Type' : 'application/json' ,
1781- Accept : 'text/event-stream, application/json' ,
1782- 'mcp-session-id' : sessionId ,
1783- 'mcp-protocol-version' : '2025-03-26'
1784- } ,
1785- body : JSON . stringify ( toolCallRequest )
1786- } ) ;
1787-
1788- expect ( postResponse . status ) . toBe ( 200 ) ;
1789-
1790- const reader = postResponse . body ?. getReader ( ) ;
1791-
1792- // Read the priming event
1793- await reader ! . read ( ) ;
1794-
1795- // Close the SSE stream
1796- transport . closeSSEStream ( 100 ) ;
1797-
1798- // Stream should now be closed
1799- const { done } = await reader ! . read ( ) ;
1800- expect ( done ) . toBe ( true ) ;
1801-
1802- // Clean up - resolve the tool promise
1803- toolResolve ! ( ) ;
1687+ // Should NOT contain a priming event (which would have empty data)
1688+ // The first message should be the actual tool result with event: message
1689+ expect ( text ) . toContain ( 'event: message' ) ;
1690+ expect ( text ) . toContain ( '"result"' ) ;
18041691 } ) ;
18051692 } ) ;
18061693
0 commit comments