2727use Mcp \Server \Session \SessionInterface ;
2828use Mcp \Server \Session \SessionManagerInterface ;
2929use Mcp \Server \Transport \TransportInterface ;
30+ use PHPUnit \Framework \Attributes \DataProvider ;
3031use PHPUnit \Framework \Attributes \TestDox ;
3132use PHPUnit \Framework \MockObject \MockObject ;
3233use PHPUnit \Framework \TestCase ;
@@ -384,8 +385,19 @@ public function testInvalidMessageStructureReturnsError(): void
384385 $ this ->assertEquals (Error::INVALID_REQUEST , $ message ['error ' ]['code ' ]);
385386 }
386387
388+ /**
389+ * @return iterable<string, array{string, string|int}>
390+ */
391+ public static function recoverableIdProvider (): iterable
392+ {
393+ yield 'positive int ' => ['{"jsonrpc": "2.0", "id": 42, "params": {}} ' , 42 ];
394+ yield 'zero int (truthiness trap) ' => ['{"jsonrpc": "2.0", "id": 0, "params": {}} ' , 0 ];
395+ yield 'string id ' => ['{"jsonrpc": "2.0", "id": "req-1", "params": {}} ' , 'req-1 ' ];
396+ }
397+
398+ #[DataProvider('recoverableIdProvider ' )]
387399 #[TestDox('Invalid but parseable message preserves its recoverable id ' )]
388- public function testInvalidMessagePreservesRecoverableId (): void
400+ public function testInvalidMessagePreservesRecoverableId (string $ input , string | int $ expectedId ): void
389401 {
390402 $ session = $ this ->createMock (SessionInterface::class);
391403
@@ -416,11 +428,11 @@ public function testInvalidMessagePreservesRecoverableId(): void
416428 );
417429
418430 $ sessionId = Uuid::v4 ();
419- // Valid JSON carrying a real numeric id but missing method/result/error: the message
420- // is structurally invalid, yet its id (42) IS recoverable from the decoded payload.
431+ // Valid JSON carrying a real id but missing method/result/error: the message is
432+ // structurally invalid, yet its id IS recoverable from the decoded payload.
421433 $ protocol ->processInput (
422434 $ this ->transport ,
423- ' {"jsonrpc": "2.0", "id": 42, "params": {}} ' ,
435+ $ input ,
424436 $ sessionId
425437 );
426438
@@ -430,7 +442,7 @@ public function testInvalidMessagePreservesRecoverableId(): void
430442 $ message = json_decode ($ outgoing [0 ]['message ' ], true );
431443 $ this ->assertArrayHasKey ('error ' , $ message );
432444 $ this ->assertEquals (Error::INVALID_REQUEST , $ message ['error ' ]['code ' ]);
433- $ this ->assertSame (42 , $ message ['id ' ], 'Invalid-but-parseable message must preserve its recoverable id, not return "" ' );
445+ $ this ->assertSame ($ expectedId , $ message ['id ' ], 'Invalid-but-parseable message must preserve its recoverable id, not return "" ' );
434446 }
435447
436448 #[TestDox('Request without handler returns method not found error ' )]
0 commit comments