Introduce schema component

This commit is contained in:
Christopher Hertel 2025-08-01 16:41:16 +02:00
commit 6025f890f9
No known key found for this signature in database
GPG key ID: 111F6BFF7B6B5AA3

View file

@ -0,0 +1,164 @@
<?php
/*
* This file is part of the official PHP MCP SDK.
*
* A collaboration between Symfony and the PHP Foundation.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Mcp\Schema;
/**
* Capabilities that a server may support. Known capabilities are defined here, in this schema, but this is not a closed
* set: any server can define its own, additional capabilities.
*
* @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/
class ServerCapabilities implements \JsonSerializable
{
/**
* @param ?bool $tools server exposes callable tools
* @param ?bool $toolsListChanged server supports list changed notifications for tools
* @param ?bool $resources server provides readable resources
* @param ?bool $resourcesSubscribe server supports subscribing to changes in the list of resources
* @param ?bool $resourcesListChanged server supports list changed notifications for resources
* @param ?bool $prompts server provides prompts templates
* @param ?bool $promptsListChanged server supports list changed notifications for prompts
* @param ?bool $logging server emits structured log messages
* @param ?bool $completions Server supports argument autocompletion
* @param ?array<string, mixed> $experimental experimental, non-standard features that the server supports
*/
public function __construct(
public readonly ?bool $tools = true,
public readonly ?bool $toolsListChanged = false,
public readonly ?bool $resources = true,
public readonly ?bool $resourcesSubscribe = false,
public readonly ?bool $resourcesListChanged = false,
public readonly ?bool $prompts = true,
public readonly ?bool $promptsListChanged = false,
public readonly ?bool $logging = false,
public readonly ?bool $completions = false,
public readonly ?array $experimental = null,
) {
}
/**
* @param array{
* logging?: mixed,
* completions?: mixed,
* prompts?: array{listChanged?: bool}|object,
* resources?: array{listChanged?: bool, subscribe?: bool}|object,
* tools?: object,
* experimental?: array<string, mixed>,
* } $data
*/
public static function fromArray(array $data): self
{
$loggingEnabled = isset($data['logging']);
$completionsEnabled = isset($data['completions']);
$toolsEnabled = isset($data['tools']);
$promptsEnabled = isset($data['prompts']);
$resourcesEnabled = isset($data['resources']);
$promptsListChanged = null;
if (isset($data['prompts'])) {
if (\is_array($data['prompts']) && \array_key_exists('listChanged', $data['prompts'])) {
$promptsListChanged = (bool) $data['prompts']['listChanged'];
} elseif (\is_object($data['prompts']) && property_exists($data['prompts'], 'listChanged')) {
$promptsListChanged = (bool) $data['prompts']->listChanged;
}
}
$resourcesSubscribe = null;
$resourcesListChanged = null;
if (isset($data['resources'])) {
if (\is_array($data['resources']) && \array_key_exists('subscribe', $data['resources'])) {
$resourcesSubscribe = (bool) $data['resources']['subscribe'];
} elseif (\is_object($data['resources']) && property_exists($data['resources'], 'subscribe')) {
$resourcesSubscribe = (bool) $data['resources']->subscribe;
}
if (\is_array($data['resources']) && \array_key_exists('listChanged', $data['resources'])) {
$resourcesListChanged = (bool) $data['resources']['listChanged'];
} elseif (\is_object($data['resources']) && property_exists($data['resources'], 'listChanged')) {
$resourcesListChanged = (bool) $data['resources']->listChanged;
}
}
$toolsListChanged = null;
if (isset($data['tools'])) {
if (\is_array($data['tools']) && \array_key_exists('listChanged', $data['tools'])) {
$toolsListChanged = (bool) $data['tools']['listChanged'];
} elseif (\is_object($data['tools']) && property_exists($data['tools'], 'listChanged')) {
$toolsListChanged = (bool) $data['tools']->listChanged;
}
}
return new self(
tools: $toolsEnabled,
toolsListChanged: $toolsListChanged,
resources: $resourcesEnabled,
resourcesSubscribe: $resourcesSubscribe,
resourcesListChanged: $resourcesListChanged,
prompts: $promptsEnabled,
promptsListChanged: $promptsListChanged,
logging: $loggingEnabled,
completions: $completionsEnabled,
experimental: $data['experimental'] ?? null
);
}
/**
* @return array{
* logging?: object,
* completions?: object,
* prompts?: object,
* resources?: object,
* tools?: object,
* experimental?: object,
* }
*/
public function jsonSerialize(): array
{
$data = [];
if ($this->logging) {
$data['logging'] = new \stdClass();
}
if ($this->completions) {
$data['completions'] = new \stdClass();
}
if ($this->prompts || $this->promptsListChanged) {
$data['prompts'] = new \stdClass();
if ($this->promptsListChanged) {
$data['prompts']->listChanged = $this->promptsListChanged;
}
}
if ($this->resources || $this->resourcesSubscribe || $this->resourcesListChanged) {
$data['resources'] = new \stdClass();
if ($this->resourcesSubscribe) {
$data['resources']->subscribe = $this->resourcesSubscribe;
}
if ($this->resourcesListChanged) {
$data['resources']->listChanged = $this->resourcesListChanged;
}
}
if ($this->tools || $this->toolsListChanged) {
$data['tools'] = new \stdClass();
if ($this->toolsListChanged) {
$data['tools']->listChanged = $this->toolsListChanged;
}
}
if ($this->experimental) {
$data['experimental'] = (object) $this->experimental;
}
return $data;
}
}