Ability to set custom protocol version (#117)

This commit is contained in:
ineersa 2025-11-07 18:37:01 -05:00 • committed by GitHub
commit 09596c0382
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 124 additions and 4 deletions

View file

@ -0,0 +1,24 @@
<?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\Enum;
/**
* Available protocol versions for MCP.
*/
enum ProtocolVersion: string
{
case V2024_11_05 = '2024-11-05';
case V2025_03_26 = '2025-03-26';
case V2025_06_18 = '2025-06-18';
}

View file

@ -11,6 +11,8 @@
namespace Mcp\Schema\JsonRpc; namespace Mcp\Schema\JsonRpc;
use Mcp\Schema\Enum\ProtocolVersion;
/** /**
* Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent. * Refers to any valid JSON-RPC object that can be decoded off the wire, or encoded to be sent.
* *
@ -19,5 +21,5 @@ namespace Mcp\Schema\JsonRpc;
interface MessageInterface extends \JsonSerializable interface MessageInterface extends \JsonSerializable
{ {
public const JSONRPC_VERSION = '2.0'; public const JSONRPC_VERSION = '2.0';
public const PROTOCOL_VERSION = '2025-06-18'; public const PROTOCOL_VERSION = ProtocolVersion::V2025_06_18;
} }

View file

@ -12,6 +12,7 @@
namespace Mcp\Schema\Result; namespace Mcp\Schema\Result;
use Mcp\Exception\InvalidArgumentException; use Mcp\Exception\InvalidArgumentException;
use Mcp\Schema\Enum\ProtocolVersion;
use Mcp\Schema\Implementation; use Mcp\Schema\Implementation;
use Mcp\Schema\JsonRpc\MessageInterface; use Mcp\Schema\JsonRpc\MessageInterface;
use Mcp\Schema\JsonRpc\Response; use Mcp\Schema\JsonRpc\Response;
@ -38,6 +39,7 @@ class InitializeResult implements ResultInterface
public readonly Implementation $serverInfo, public readonly Implementation $serverInfo,
public readonly ?string $instructions = null, public readonly ?string $instructions = null,
public readonly ?array $_meta = null, public readonly ?array $_meta = null,
public readonly ?ProtocolVersion $protocolVersion = null,
) { ) {
} }
@ -66,7 +68,8 @@ class InitializeResult implements ResultInterface
ServerCapabilities::fromArray($data['capabilities']), ServerCapabilities::fromArray($data['capabilities']),
Implementation::fromArray($data['serverInfo']), Implementation::fromArray($data['serverInfo']),
$data['instructions'] ?? null, $data['instructions'] ?? null,
$data['_meta'] ?? null $data['_meta'] ?? null,
ProtocolVersion::tryFrom($data['protocolVersion']),
); );
} }
@ -81,8 +84,9 @@ class InitializeResult implements ResultInterface
*/ */
public function jsonSerialize(): array public function jsonSerialize(): array
{ {
$protocolVersion = $this->protocolVersion ?? MessageInterface::PROTOCOL_VERSION;
$data = [ $data = [
'protocolVersion' => MessageInterface::PROTOCOL_VERSION, 'protocolVersion' => $protocolVersion->value,
'capabilities' => $this->capabilities, 'capabilities' => $this->capabilities,
'serverInfo' => $this->serverInfo, 'serverInfo' => $this->serverInfo,
]; ];

View file

@ -20,6 +20,7 @@ use Mcp\Capability\Registry\Loader\LoaderInterface;
use Mcp\Capability\Registry\ReferenceHandler; use Mcp\Capability\Registry\ReferenceHandler;
use Mcp\JsonRpc\MessageFactory; use Mcp\JsonRpc\MessageFactory;
use Mcp\Schema\Annotations; use Mcp\Schema\Annotations;
use Mcp\Schema\Enum\ProtocolVersion;
use Mcp\Schema\Implementation; use Mcp\Schema\Implementation;
use Mcp\Schema\ServerCapabilities; use Mcp\Schema\ServerCapabilities;
use Mcp\Schema\ToolAnnotations; use Mcp\Schema\ToolAnnotations;
@ -63,6 +64,8 @@ final class Builder
private ?string $instructions = null; private ?string $instructions = null;
private ?ProtocolVersion $protocolVersion = null;
/** /**
* @var array<int, RequestHandlerInterface<mixed>> * @var array<int, RequestHandlerInterface<mixed>>
*/ */
@ -288,6 +291,13 @@ final class Builder
return $this; return $this;
} }
public function setProtocolVersion(?ProtocolVersion $protocolVersion): self
{
$this->protocolVersion = $protocolVersion;
return $this;
}
/** /**
* Manually registers a tool handler. * Manually registers a tool handler.
* *
@ -404,7 +414,7 @@ final class Builder
$messageFactory = MessageFactory::make(); $messageFactory = MessageFactory::make();
$capabilities = $registry->getCapabilities(); $capabilities = $registry->getCapabilities();
$configuration = new Configuration($this->serverInfo, $capabilities, $this->paginationLimit, $this->instructions); $configuration = new Configuration($this->serverInfo, $capabilities, $this->paginationLimit, $this->instructions, $this->protocolVersion);
$referenceHandler = new ReferenceHandler($container); $referenceHandler = new ReferenceHandler($container);
$requestHandlers = array_merge($this->requestHandlers, [ $requestHandlers = array_merge($this->requestHandlers, [

View file

@ -11,6 +11,7 @@
namespace Mcp\Server; namespace Mcp\Server;
use Mcp\Schema\Enum\ProtocolVersion;
use Mcp\Schema\Implementation; use Mcp\Schema\Implementation;
use Mcp\Schema\ServerCapabilities; use Mcp\Schema\ServerCapabilities;
@ -34,6 +35,7 @@ class Configuration
public readonly ServerCapabilities $capabilities, public readonly ServerCapabilities $capabilities,
public readonly int $paginationLimit = 50, public readonly int $paginationLimit = 50,
public readonly ?string $instructions = null, public readonly ?string $instructions = null,
public readonly ?ProtocolVersion $protocolVersion = null,
) { ) {
} }
} }

View file

@ -52,6 +52,8 @@ final class InitializeHandler implements RequestHandlerInterface
$this->configuration->capabilities ?? new ServerCapabilities(), $this->configuration->capabilities ?? new ServerCapabilities(),
$this->configuration->serverInfo ?? new Implementation(), $this->configuration->serverInfo ?? new Implementation(),
$this->configuration?->instructions, $this->configuration?->instructions,
null,
$this->configuration?->protocolVersion,
), ),
); );
} }

View file

@ -0,0 +1,76 @@
<?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\Tests\Unit\Server\Handler\Request;
use Mcp\Schema\Enum\ProtocolVersion;
use Mcp\Schema\Implementation;
use Mcp\Schema\JsonRpc\MessageInterface;
use Mcp\Schema\Request\InitializeRequest;
use Mcp\Schema\Result\InitializeResult;
use Mcp\Schema\ServerCapabilities;
use Mcp\Server\Configuration;
use Mcp\Server\Handler\Request\InitializeHandler;
use Mcp\Server\Session\SessionInterface;
use PHPUnit\Framework\Attributes\TestDox;
use PHPUnit\Framework\TestCase;
class InitializeHandlerTest extends TestCase
{
#[TestDox('uses configuration protocol version when provided')]
public function testHandleUsesConfigurationProtocolVersion(): void
{
$customProtocolVersion = ProtocolVersion::V2024_11_05;
$configuration = new Configuration(
serverInfo: new Implementation('server', '1.2.3'),
capabilities: new ServerCapabilities(),
protocolVersion: $customProtocolVersion,
);
$handler = new InitializeHandler($configuration);
$session = $this->createMock(SessionInterface::class);
$session->expects($this->once())
->method('set')
->with('client_info', [
'name' => 'client-app',
'version' => '1.0.0',
]);
$request = InitializeRequest::fromArray([
'jsonrpc' => MessageInterface::JSONRPC_VERSION,
'id' => 'request-1',
'method' => InitializeRequest::getMethod(),
'params' => [
'protocolVersion' => ProtocolVersion::V2024_11_05->value,
'capabilities' => [],
'clientInfo' => [
'name' => 'client-app',
'version' => '1.0.0',
],
],
]);
$response = $handler->handle($request, $session);
$this->assertInstanceOf(InitializeResult::class, $response->result);
/** @var InitializeResult $result */
$result = $response->result;
$this->assertSame($customProtocolVersion, $result->protocolVersion);
$this->assertSame(
$customProtocolVersion->value,
$result->jsonSerialize()['protocolVersion']
);
}
}