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

View file

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

View file

@ -11,6 +11,7 @@
namespace Mcp\Server;
use Mcp\Schema\Enum\ProtocolVersion;
use Mcp\Schema\Implementation;
use Mcp\Schema\ServerCapabilities;
@ -34,6 +35,7 @@ class Configuration
public readonly ServerCapabilities $capabilities,
public readonly int $paginationLimit = 50,
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->serverInfo ?? new Implementation(),
$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']
);
}
}