diff --git a/src/Schema/ClientCapabilities.php b/src/Schema/ClientCapabilities.php index bc71cfc..75d50ff 100644 --- a/src/Schema/ClientCapabilities.php +++ b/src/Schema/ClientCapabilities.php @@ -188,7 +188,10 @@ class ClientCapabilities implements \JsonSerializable } if ($this->extensions) { - $data['extensions'] = (object) $this->extensions; + $data['extensions'] = (object) array_map( + static fn (mixed $settings): mixed => \is_array($settings) ? (object) $settings : $settings, + $this->extensions, + ); } return $data ?: new \stdClass(); diff --git a/src/Schema/ServerCapabilities.php b/src/Schema/ServerCapabilities.php index 0e47c61..33cc1ee 100644 --- a/src/Schema/ServerCapabilities.php +++ b/src/Schema/ServerCapabilities.php @@ -189,7 +189,12 @@ class ServerCapabilities implements \JsonSerializable } if ($this->extensions) { - $data['extensions'] = (object) $this->extensions; + // Each entry is a settings *object*; an extension with no settings + // declares `{}`, and an empty PHP array would serialize as `[]`. + $data['extensions'] = (object) array_map( + static fn (mixed $settings): mixed => \is_array($settings) ? (object) $settings : $settings, + $this->extensions, + ); } return $data; diff --git a/tests/Unit/Schema/Extension/CapabilitiesExtensionsTest.php b/tests/Unit/Schema/Extension/CapabilitiesExtensionsTest.php index 7ef916e..dbb7e7e 100644 --- a/tests/Unit/Schema/Extension/CapabilitiesExtensionsTest.php +++ b/tests/Unit/Schema/Extension/CapabilitiesExtensionsTest.php @@ -57,6 +57,24 @@ class CapabilitiesExtensionsTest extends TestCase $this->assertObjectHasProperty(McpApps::EXTENSION_ID, $json['extensions']); } + public function testServerCapabilitiesSerializeSettinglessExtensionAsObject(): void + { + $caps = new ServerCapabilities(tools: true, extensions: ['acme/thing' => []]); + + $json = json_encode($caps->jsonSerialize(), \JSON_UNESCAPED_SLASHES); + + $this->assertStringContainsString('"acme/thing":{}', (string) $json); + } + + public function testClientCapabilitiesSerializeSettinglessExtensionAsObject(): void + { + $caps = new ClientCapabilities(elicitation: true, extensions: ['acme/thing' => []]); + + $json = json_encode($caps->jsonSerialize(), \JSON_UNESCAPED_SLASHES); + + $this->assertStringContainsString('"acme/thing":{}', (string) $json); + } + public function testServerCapabilitiesJsonSerializeWithoutExtensions(): void { $caps = new ServerCapabilities(tools: true);