diff --git a/src/Protocol.php b/src/Protocol.php index 918885e..7870a49 100644 --- a/src/Protocol.php +++ b/src/Protocol.php @@ -120,7 +120,12 @@ public function processMessage(Request|Notification|BatchRequest $message, strin $session = $this->sessionManager->getSession($sessionId); if ($session === null) { - $error = Error::forInvalidRequest('Invalid or expired session. Please re-initialize the session.', $message->id); + if ($message instanceof Notification) { + $this->logger->warning('Notification received for invalid or expired session. Ignoring.', ['sessionId' => $sessionId, 'method' => $message->method]); + return; + } + + $error = Error::forInvalidRequest('Invalid or expired session. Please re-initialize the session.', $message->getId()); $messageContext['status_code'] = 404; $this->transport->sendMessage($error, $sessionId, $messageContext) diff --git a/tests/Unit/ProtocolTest.php b/tests/Unit/ProtocolTest.php index 4bc0b15..0975930 100644 --- a/tests/Unit/ProtocolTest.php +++ b/tests/Unit/ProtocolTest.php @@ -271,6 +271,31 @@ function expectSuccessResponse(mixed $response, mixed $expectedResult, string|in $this->session->shouldNotHaveReceived('save'); }); +it('ignores notification if session is not found', function () { + $notification = createNotification('notifications/initialized'); + $this->sessionManager->shouldReceive('getSession')->with('unknown-client')->andReturn(null); + + $this->transport->shouldNotReceive('sendMessage'); + $this->dispatcher->shouldNotReceive('handleNotification'); + + $this->protocol->processMessage($notification, 'unknown-client', ['is_initialize_request' => false]); + $this->session->shouldNotHaveReceived('save'); +}); + +it('sends error response with first request id if session is not found for batch', function () { + $batchRequest = new BatchRequest([createNotification('notifications/initialized'), createRequest('tools/list', [], 'batch-req-1')]); + $this->sessionManager->shouldReceive('getSession')->with('unknown-client')->andReturn(null); + + $this->transport->shouldReceive('sendMessage')->once() + ->with(Mockery::on(function (Error $error) { + expectErrorResponse($error, \PhpMcp\Schema\Constants::INVALID_REQUEST, 'batch-req-1'); + return true; + }), 'unknown-client', Mockery::any()) + ->andReturn(resolve(null)); + + $this->protocol->processMessage($batchRequest, 'unknown-client'); +}); + it('sends error response if session is not initialized for non-initialize request', function () { $request = createRequest('tools/list'); $this->session->shouldReceive('get')->with('initialized', false)->andReturn(false);