@@ -1671,7 +1671,7 @@ 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-11-25 '
16751675 } ,
16761676 body : JSON . stringify ( toolCallRequest )
16771677 } ) ;
@@ -1690,6 +1690,57 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
16901690 expect ( text ) . toContain ( 'data: ' ) ;
16911691 } ) ;
16921692
1693+ it ( 'should NOT send priming event for old protocol versions (backwards compatibility)' , async ( ) => {
1694+ const result = await createTestServer ( {
1695+ sessionIdGenerator : ( ) => randomUUID ( ) ,
1696+ eventStore : createEventStore ( ) ,
1697+ retryInterval : 5000
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 with OLD protocol version
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+ expect ( postResponse . headers . get ( 'content-type' ) ) . toBe ( 'text/event-stream' ) ;
1730+
1731+ // Read the first chunk - should be the actual response, not a priming event
1732+ const reader = postResponse . body ?. getReader ( ) ;
1733+ const { value } = await reader ! . read ( ) ;
1734+ const text = new TextDecoder ( ) . decode ( value ) ;
1735+
1736+ // Should NOT contain a priming event (empty data line before the response)
1737+ // The first message should be the actual tool result
1738+ expect ( text ) . toContain ( 'event: message' ) ;
1739+ expect ( text ) . toContain ( '"result"' ) ;
1740+ // Should NOT have a separate priming event line with empty data
1741+ expect ( text ) . not . toMatch ( / ^ i d : .* \n d a t a : \s * \n \n / ) ;
1742+ } ) ;
1743+
16931744 it ( 'should send priming event without retry field when retryInterval is not configured' , async ( ) => {
16941745 const result = await createTestServer ( {
16951746 sessionIdGenerator : ( ) => randomUUID ( ) ,
@@ -1720,7 +1771,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
17201771 'Content-Type' : 'application/json' ,
17211772 Accept : 'text/event-stream, application/json' ,
17221773 'mcp-session-id' : sessionId ,
1723- 'mcp-protocol-version' : '2025-03-26 '
1774+ 'mcp-protocol-version' : '2025-11-25 '
17241775 } ,
17251776 body : JSON . stringify ( toolCallRequest )
17261777 } ) ;
@@ -1786,7 +1837,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
17861837 'Content-Type' : 'application/json' ,
17871838 Accept : 'text/event-stream, application/json' ,
17881839 'mcp-session-id' : sessionId ,
1789- 'mcp-protocol-version' : '2025-03-26 '
1840+ 'mcp-protocol-version' : '2025-11-25 '
17901841 } ,
17911842 body : JSON . stringify ( toolCallRequest )
17921843 } ) ;
@@ -1849,7 +1900,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
18491900 'Content-Type' : 'application/json' ,
18501901 Accept : 'text/event-stream, application/json' ,
18511902 'mcp-session-id' : sessionId ,
1852- 'mcp-protocol-version' : '2025-03-26 '
1903+ 'mcp-protocol-version' : '2025-11-25 '
18531904 } ,
18541905 body : JSON . stringify ( toolCallRequest )
18551906 } ) ;
@@ -1868,6 +1919,67 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
18681919 expect ( typeof receivedCloseSSEStream ) . toBe ( 'function' ) ;
18691920 } ) ;
18701921
1922+ it ( 'should NOT provide closeSSEStream callback for old protocol versions (backwards compatibility)' , async ( ) => {
1923+ const result = await createTestServer ( {
1924+ sessionIdGenerator : ( ) => randomUUID ( ) ,
1925+ eventStore : createEventStore ( ) ,
1926+ retryInterval : 1000
1927+ } ) ;
1928+ server = result . server ;
1929+ transport = result . transport ;
1930+ baseUrl = result . baseUrl ;
1931+ mcpServer = result . mcpServer ;
1932+
1933+ // Track whether closeSSEStream callback was provided
1934+ let receivedCloseSSEStream : ( ( ) => void ) | undefined ;
1935+ let receivedCloseStandaloneSSEStream : ( ( ) => void ) | undefined ;
1936+
1937+ // Register a tool that captures the extra.closeSSEStream callback
1938+ mcpServer . tool ( 'test-old-version-tool' , 'Test tool' , { } , async ( _args , extra ) => {
1939+ receivedCloseSSEStream = extra . closeSSEStream ;
1940+ receivedCloseStandaloneSSEStream = extra . closeStandaloneSSEStream ;
1941+ return { content : [ { type : 'text' , text : 'Done' } ] } ;
1942+ } ) ;
1943+
1944+ // Initialize to get session ID
1945+ const initResponse = await sendPostRequest ( baseUrl , TEST_MESSAGES . initialize ) ;
1946+ sessionId = initResponse . headers . get ( 'mcp-session-id' ) as string ;
1947+ expect ( sessionId ) . toBeDefined ( ) ;
1948+
1949+ // Call the tool with OLD protocol version
1950+ const toolCallRequest : JSONRPCMessage = {
1951+ jsonrpc : '2.0' ,
1952+ id : 200 ,
1953+ method : 'tools/call' ,
1954+ params : { name : 'test-old-version-tool' , arguments : { } }
1955+ } ;
1956+
1957+ const postResponse = await fetch ( baseUrl , {
1958+ method : 'POST' ,
1959+ headers : {
1960+ 'Content-Type' : 'application/json' ,
1961+ Accept : 'text/event-stream, application/json' ,
1962+ 'mcp-session-id' : sessionId ,
1963+ 'mcp-protocol-version' : '2025-03-26'
1964+ } ,
1965+ body : JSON . stringify ( toolCallRequest )
1966+ } ) ;
1967+
1968+ expect ( postResponse . status ) . toBe ( 200 ) ;
1969+
1970+ // Read all events to completion
1971+ const reader = postResponse . body ?. getReader ( ) ;
1972+ while ( true ) {
1973+ const { done } = await reader ! . read ( ) ;
1974+ if ( done ) break ;
1975+ }
1976+
1977+ // Verify closeSSEStream callbacks were NOT provided for old protocol version
1978+ // even though eventStore is configured
1979+ expect ( receivedCloseSSEStream ) . toBeUndefined ( ) ;
1980+ expect ( receivedCloseStandaloneSSEStream ) . toBeUndefined ( ) ;
1981+ } ) ;
1982+
18711983 it ( 'should NOT provide closeSSEStream callback when eventStore is NOT configured' , async ( ) => {
18721984 const result = await createTestServer ( {
18731985 sessionIdGenerator : ( ) => randomUUID ( )
@@ -1963,7 +2075,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
19632075 'Content-Type' : 'application/json' ,
19642076 Accept : 'text/event-stream, application/json' ,
19652077 'mcp-session-id' : sessionId ,
1966- 'mcp-protocol-version' : '2025-03-26 '
2078+ 'mcp-protocol-version' : '2025-11-25 '
19672079 } ,
19682080 body : JSON . stringify ( toolCallRequest )
19692081 } ) ;
@@ -2010,7 +2122,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
20102122 headers : {
20112123 Accept : 'text/event-stream' ,
20122124 'mcp-session-id' : sessionId ,
2013- 'mcp-protocol-version' : '2025-03-26 '
2125+ 'mcp-protocol-version' : '2025-11-25 '
20142126 }
20152127 } ) ;
20162128 expect ( sseResponse . status ) . toBe ( 200 ) ;
@@ -2040,7 +2152,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
20402152 'Content-Type' : 'application/json' ,
20412153 Accept : 'text/event-stream, application/json' ,
20422154 'mcp-session-id' : sessionId ,
2043- 'mcp-protocol-version' : '2025-03-26 '
2155+ 'mcp-protocol-version' : '2025-11-25 '
20442156 } ,
20452157 body : JSON . stringify ( toolCallRequest )
20462158 } ) ;
@@ -2091,7 +2203,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
20912203 headers : {
20922204 Accept : 'text/event-stream' ,
20932205 'mcp-session-id' : sessionId ,
2094- 'mcp-protocol-version' : '2025-03-26 '
2206+ 'mcp-protocol-version' : '2025-11-25 '
20952207 }
20962208 } ) ;
20972209 expect ( sseResponse . status ) . toBe ( 200 ) ;
@@ -2122,7 +2234,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
21222234 'Content-Type' : 'application/json' ,
21232235 Accept : 'text/event-stream, application/json' ,
21242236 'mcp-session-id' : sessionId ,
2125- 'mcp-protocol-version' : '2025-03-26 '
2237+ 'mcp-protocol-version' : '2025-11-25 '
21262238 } ,
21272239 body : JSON . stringify ( toolCallRequest )
21282240 } ) ;
@@ -2152,7 +2264,7 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
21522264 headers : {
21532265 Accept : 'text/event-stream' ,
21542266 'mcp-session-id' : sessionId ,
2155- 'mcp-protocol-version' : '2025-03-26 ' ,
2267+ 'mcp-protocol-version' : '2025-11-25 ' ,
21562268 'last-event-id' : lastEventId
21572269 }
21582270 } ) ;
0 commit comments