php-sdk/src/Server/Transport/BaseTransport.php
Camille Islasse 470237ad0b
Make logger nullable in Transport constructors (#152)
- BaseTransport: Accept ?LoggerInterface parameter and convert null to NullLogger
- StdioTransport: Change logger parameter to nullable
- StreamableHttpTransport: Change logger parameter to nullable
- InMemoryTransport: Fix missing parent::__construct() call and add logging
2025-11-20 19:48:17 +01:00

139 lines
3.5 KiB
PHP

<?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\Server\Transport;
use Mcp\Schema\JsonRpc\Error;
use Mcp\Schema\JsonRpc\Response;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
use Symfony\Component\Uid\Uuid;
/**
* Provides a skeletal implementation of the TransportInterface to minimize
* the effort required to implement this interface.
*
* @phpstan-import-type FiberResume from TransportInterface
* @phpstan-import-type FiberReturn from TransportInterface
* @phpstan-import-type FiberSuspend from TransportInterface
* @phpstan-import-type McpFiber from TransportInterface
*
* @author Kyrian Obikwelu <koshnawaza@gmail.com>
*/
abstract class BaseTransport
{
use ManagesTransportCallbacks;
protected ?Uuid $sessionId = null;
/**
* @var McpFiber|null
*/
protected ?\Fiber $sessionFiber = null;
protected LoggerInterface $logger;
public function __construct(?LoggerInterface $logger = null)
{
$this->logger = $logger ?? new NullLogger();
}
public function initialize(): void
{
}
public function close(): void
{
}
public function setSessionId(?Uuid $sessionId): void
{
$this->sessionId = $sessionId;
}
/**
* @param McpFiber $fiber
*/
public function attachFiberToSession(\Fiber $fiber, Uuid $sessionId): void
{
$this->sessionFiber = $fiber;
$this->sessionId = $sessionId;
}
/**
* @return array<int, array{message: string, context: array<string, mixed>}>
*/
protected function getOutgoingMessages(?Uuid $sessionId): array
{
if ($sessionId && \is_callable($this->outgoingMessagesProvider)) {
return ($this->outgoingMessagesProvider)($sessionId);
}
return [];
}
/**
* @return array<int, array<string, mixed>>
*/
protected function getPendingRequests(?Uuid $sessionId): array
{
if ($sessionId && \is_callable($this->pendingRequestsProvider)) {
return ($this->pendingRequestsProvider)($sessionId);
}
return [];
}
/**
* @phpstan-return FiberResume
*/
protected function checkForResponse(int $requestId, ?Uuid $sessionId): Response|Error|null
{
if ($sessionId && \is_callable($this->responseFinder)) {
return ($this->responseFinder)($requestId, $sessionId);
}
return null;
}
/**
* @param FiberSuspend|null $yielded
*/
protected function handleFiberYield(mixed $yielded, ?Uuid $sessionId): void
{
if (null === $yielded || !\is_callable($this->fiberYieldHandler)) {
return;
}
try {
($this->fiberYieldHandler)($yielded, $sessionId);
} catch (\Throwable $e) {
$this->logger->error('Fiber yield handler failed.', [
'exception' => $e,
'sessionId' => $sessionId?->toRfc4122(),
]);
}
}
protected function handleMessage(string $payload, ?Uuid $sessionId): void
{
if (\is_callable($this->messageListener)) {
($this->messageListener)($payload, $sessionId);
}
}
protected function handleSessionEnd(?Uuid $sessionId): void
{
if ($sessionId && \is_callable($this->sessionEndListener)) {
($this->sessionEndListener)($sessionId);
}
}
}