@@ -184,6 +184,26 @@ describe("stateless MCP Streamable HTTP", () => {
184184 } ) ;
185185 } ) ;
186186
187+ it ( "negotiates 2025-06-18 and accepts it on a sessionless follow-up" , async ( ) => {
188+ const initialized = await post ( initializeRequest ( 11 , "2025-06-18" ) ) ;
189+
190+ expect ( initialized . status ) . toBe ( 200 ) ;
191+ expect ( initialized . headers . get ( "mcp-session-id" ) ) . toBeNull ( ) ;
192+ await expect ( initialized . json ( ) ) . resolves . toMatchObject ( {
193+ jsonrpc : "2.0" ,
194+ id : 11 ,
195+ result : { protocolVersion : "2025-06-18" } ,
196+ } ) ;
197+
198+ const listed = await post (
199+ { jsonrpc : "2.0" , id : 12 , method : "tools/list" , params : { } } ,
200+ { "mcp-protocol-version" : "2025-06-18" } ,
201+ ) ;
202+
203+ expect ( listed . status ) . toBe ( 200 ) ;
204+ await expect ( listedToolNames ( listed ) ) . resolves . toEqual ( [ ...PUBLISHED ] . sort ( ) ) ;
205+ } ) ;
206+
187207 it ( "creates a fresh server and transport for every POST" , async ( ) => {
188208 const first = await post ( initializeRequest ( 7 ) ) ;
189209 const second = await post ( initializeRequest ( 7 ) ) ;
@@ -261,26 +281,36 @@ describe("stateless MCP Streamable HTTP", () => {
261281 } ) ;
262282 } ) ;
263283
264- it ( "rejects batches and protocol versions other than 2025-11-25 " , async ( ) => {
284+ it ( "rejects batches and unknown initialize protocol versions " , async ( ) => {
265285 const batch = await post ( [ initializeRequest ( 1 ) , initializeRequest ( 2 ) ] ) ;
266- const oldVersion = await post ( {
267- ...initializeRequest ( 5 ) ,
268- params : { ...initializeRequest ( 5 ) . params , protocolVersion : "2025-06-18" } ,
269- } ) ;
286+ const unknownVersion = await post ( initializeRequest ( 5 , "2099-01-01" ) ) ;
270287
271288 expect ( batch . status ) . toBe ( 400 ) ;
272- expect ( oldVersion . status ) . toBe ( 400 ) ;
289+ expect ( unknownVersion . status ) . toBe ( 400 ) ;
273290 await expect ( batch . json ( ) ) . resolves . toMatchObject ( {
274291 error : { data : { code : "VALIDATION_FAILED" } } ,
275292 } ) ;
276- await expect ( oldVersion . json ( ) ) . resolves . toMatchObject ( {
293+ await expect ( unknownVersion . json ( ) ) . resolves . toMatchObject ( {
294+ error : { data : { code : "VALIDATION_FAILED" } } ,
295+ } ) ;
296+ } ) ;
297+
298+ it ( "rejects an unknown initialize header before authentication" , async ( ) => {
299+ const response = await post ( initializeRequest ( 6 ) , {
300+ "mcp-protocol-version" : "2099-01-01" ,
301+ } ) ;
302+
303+ expect ( response . status ) . toBe ( 400 ) ;
304+ expect ( state . requireMcpActor ) . not . toHaveBeenCalled ( ) ;
305+ await expect ( response . json ( ) ) . resolves . toMatchObject ( {
306+ id : 6 ,
277307 error : { data : { code : "VALIDATION_FAILED" } } ,
278308 } ) ;
279309 } ) ;
280310
281311 it . each ( [
282312 [ "missing" , { } ] ,
283- [ "wrong " , { "mcp-protocol-version" : "2025-06-18 " } ] ,
313+ [ "unknown " , { "mcp-protocol-version" : "2099-01-01 " } ] ,
284314 ] ) ( "rejects a tools/list follow-up with a %s protocol version before auth" , async ( _case , headers ) => {
285315 const response = await post (
286316 { jsonrpc : "2.0" , id : 9 , method : "tools/list" , params : { } } ,
@@ -710,13 +740,13 @@ async function toolErrorText(response: Response): Promise<string> {
710740 return body . result ?. content ?. [ 0 ] ?. text ?? "" ;
711741}
712742
713- function initializeRequest ( id : number ) {
743+ function initializeRequest ( id : number , protocolVersion = "2025-11-25" ) {
714744 return {
715745 jsonrpc : "2.0" as const ,
716746 id,
717747 method : "initialize" as const ,
718748 params : {
719- protocolVersion : "2025-11-25" ,
749+ protocolVersion,
720750 capabilities : { } ,
721751 clientInfo : { name : "task-5-test" , version : "1.0.0" } ,
722752 } ,
0 commit comments