diff --git a/src/Dispatcher.php b/src/Dispatcher.php index 9cc9748..590443a 100644 --- a/src/Dispatcher.php +++ b/src/Dispatcher.php @@ -119,16 +119,14 @@ public function handleNotification(Notification $notification, SessionInterface public function handleInitialize(InitializeRequest $request, SessionInterface $session): InitializeResult { - if (! in_array($request->protocolVersion, Protocol::SUPPORTED_PROTOCOL_VERSIONS)) { - $this->logger->warning("Unsupported protocol version: {$request->protocolVersion}", [ - 'supportedVersions' => Protocol::SUPPORTED_PROTOCOL_VERSIONS, - ]); + if (in_array($request->protocolVersion, Protocol::SUPPORTED_PROTOCOL_VERSIONS)) { + $protocolVersion = $request->protocolVersion; + } else { + $protocolVersion = Protocol::LATEST_PROTOCOL_VERSION; } - $protocolVersion = Protocol::LATEST_PROTOCOL_VERSION; - - $session->set('client_info', $request->clientInfo); - + $session->set('client_info', $request->clientInfo->toArray()); + $session->set('protocol_version', $protocolVersion); $serverInfo = $this->configuration->serverInfo; $capabilities = $this->configuration->capabilities; diff --git a/tests/Unit/DispatcherTest.php b/tests/Unit/DispatcherTest.php index 2c1946c..8d683c6 100644 --- a/tests/Unit/DispatcherTest.php +++ b/tests/Unit/DispatcherTest.php @@ -100,7 +100,8 @@ 'capabilities' => [], ] ); - $this->session->shouldReceive('set')->with('client_info', Mockery::on(fn ($value) => $value->name === 'client' && $value->version === '1.0'))->once(); + $this->session->shouldReceive('set')->with('client_info', Mockery::on(fn($value) => $value['name'] === 'client' && $value['version'] === '1.0'))->once(); + $this->session->shouldReceive('set')->with('protocol_version', Protocol::LATEST_PROTOCOL_VERSION)->once(); $result = $this->dispatcher->handleRequest($request, $this->session); expect($result)->toBeInstanceOf(InitializeResult::class); @@ -135,7 +136,34 @@ it('can handle initialize request', function () { $clientInfo = Implementation::make('TestClient', '0.9.9'); $request = InitializeRequest::make(1, Protocol::LATEST_PROTOCOL_VERSION, ClientCapabilities::make(), $clientInfo, []); - $this->session->shouldReceive('set')->with('client_info', $clientInfo)->once(); + $this->session->shouldReceive('set')->with('client_info', $clientInfo->toArray())->once(); + $this->session->shouldReceive('set')->with('protocol_version', Protocol::LATEST_PROTOCOL_VERSION)->once(); + + $result = $this->dispatcher->handleInitialize($request, $this->session); + expect($result->protocolVersion)->toBe(Protocol::LATEST_PROTOCOL_VERSION); + expect($result->serverInfo->name)->toBe('DispatcherTestServer'); + expect($result->capabilities)->toBeInstanceOf(ServerCapabilities::class); +}); + +it('can handle initialize request with older supported protocol version', function () { + $clientInfo = Implementation::make('TestClient', '0.9.9'); + $clientRequestedVersion = '2024-11-05'; + $request = InitializeRequest::make(1, $clientRequestedVersion, ClientCapabilities::make(), $clientInfo, []); + $this->session->shouldReceive('set')->with('client_info', $clientInfo->toArray())->once(); + $this->session->shouldReceive('set')->with('protocol_version', $clientRequestedVersion)->once(); + + $result = $this->dispatcher->handleInitialize($request, $this->session); + expect($result->protocolVersion)->toBe($clientRequestedVersion); + expect($result->serverInfo->name)->toBe('DispatcherTestServer'); + expect($result->capabilities)->toBeInstanceOf(ServerCapabilities::class); +}); + +it('can handle initialize request with unsupported protocol version', function () { + $clientInfo = Implementation::make('TestClient', '0.9.9'); + $unsupportedVersion = '1999-01-01'; + $request = InitializeRequest::make(1, $unsupportedVersion, ClientCapabilities::make(), $clientInfo, []); + $this->session->shouldReceive('set')->with('client_info', $clientInfo->toArray())->once(); + $this->session->shouldReceive('set')->with('protocol_version', Protocol::LATEST_PROTOCOL_VERSION)->once(); $result = $this->dispatcher->handleInitialize($request, $this->session); expect($result->protocolVersion)->toBe(Protocol::LATEST_PROTOCOL_VERSION); @@ -256,14 +284,14 @@ $requestP1 = ListResourcesRequest::make(1); $resultP1 = $this->dispatcher->handleResourcesList($requestP1); expect($resultP1->resources)->toHaveCount(DISPATCHER_PAGINATION_LIMIT); - expect(array_map(fn ($r) => $r->name, $resultP1->resources))->toEqual(['Resource1', 'Resource2', 'Resource3']); + expect(array_map(fn($r) => $r->name, $resultP1->resources))->toEqual(['Resource1', 'Resource2', 'Resource3']); expect($resultP1->nextCursor)->toBe(base64_encode('offset=3')); // Page 2 $requestP2 = ListResourcesRequest::make(2, $resultP1->nextCursor); $resultP2 = $this->dispatcher->handleResourcesList($requestP2); expect($resultP2->resources)->toHaveCount(2); - expect(array_map(fn ($r) => $r->name, $resultP2->resources))->toEqual(['Resource4', 'Resource5']); + expect(array_map(fn($r) => $r->name, $resultP2->resources))->toEqual(['Resource4', 'Resource5']); expect($resultP2->nextCursor)->toBeNull(); }); @@ -288,14 +316,14 @@ $requestP1 = ListResourceTemplatesRequest::make(1); $resultP1 = $this->dispatcher->handleResourceTemplateList($requestP1); expect($resultP1->resourceTemplates)->toHaveCount(DISPATCHER_PAGINATION_LIMIT); - expect(array_map(fn ($rt) => $rt->name, $resultP1->resourceTemplates))->toEqual(['Template1', 'Template2', 'Template3']); + expect(array_map(fn($rt) => $rt->name, $resultP1->resourceTemplates))->toEqual(['Template1', 'Template2', 'Template3']); expect($resultP1->nextCursor)->toBe(base64_encode('offset=3')); // Page 2 $requestP2 = ListResourceTemplatesRequest::make(2, $resultP1->nextCursor); $resultP2 = $this->dispatcher->handleResourceTemplateList($requestP2); expect($resultP2->resourceTemplates)->toHaveCount(1); - expect(array_map(fn ($rt) => $rt->name, $resultP2->resourceTemplates))->toEqual(['Template4']); + expect(array_map(fn($rt) => $rt->name, $resultP2->resourceTemplates))->toEqual(['Template4']); expect($resultP2->nextCursor)->toBeNull(); }); @@ -345,14 +373,14 @@ $requestP1 = ListPromptsRequest::make(1); $resultP1 = $this->dispatcher->handlePromptsList($requestP1); expect($resultP1->prompts)->toHaveCount(DISPATCHER_PAGINATION_LIMIT); - expect(array_map(fn ($p) => $p->name, $resultP1->prompts))->toEqual(['promptA', 'promptB', 'promptC']); + expect(array_map(fn($p) => $p->name, $resultP1->prompts))->toEqual(['promptA', 'promptB', 'promptC']); expect($resultP1->nextCursor)->toBe(base64_encode('offset=3')); // Page 2 $requestP2 = ListPromptsRequest::make(2, $resultP1->nextCursor); $resultP2 = $this->dispatcher->handlePromptsList($requestP2); expect($resultP2->prompts)->toHaveCount(DISPATCHER_PAGINATION_LIMIT); // 3 more - expect(array_map(fn ($p) => $p->name, $resultP2->prompts))->toEqual(['promptD', 'promptE', 'promptF']); + expect(array_map(fn($p) => $p->name, $resultP2->prompts))->toEqual(['promptD', 'promptE', 'promptF']); expect($resultP2->nextCursor)->toBeNull(); // End of list });