Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/Server/Transport/Stdio/RunnerControl.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?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\Stdio;

/**
* Default implementation of RunnerControlInterface. This will allow
* anyone to change the state of the runner.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class RunnerControl implements RunnerControlInterface
{
public static RunnerState $state = RunnerState::RUNNING;

public function getState(): RunnerState
{
return self::$state;
}
}
22 changes: 22 additions & 0 deletions src/Server/Transport/Stdio/RunnerControlInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?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\Stdio;

/**
* Used by the transport to control the runner state.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
interface RunnerControlInterface
{
public function getState(): RunnerState;
}
24 changes: 24 additions & 0 deletions src/Server/Transport/Stdio/RunnerState.php
Original file line number Diff line number Diff line change
@@ -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\Server\Transport\Stdio;

/**
* State for the transport.
*
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
enum RunnerState
{
case RUNNING;
case STOP_AND_END_SESSION;
case STOP;
}
14 changes: 12 additions & 2 deletions src/Server/Transport/StdioTransport.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
namespace Mcp\Server\Transport;

use Mcp\Schema\JsonRpc\Error;
use Mcp\Server\Transport\Stdio\RunnerControl;
use Mcp\Server\Transport\Stdio\RunnerControlInterface;
use Mcp\Server\Transport\Stdio\RunnerState;
use Psr\Log\LoggerInterface;

/**
Expand All @@ -21,6 +24,8 @@
*/
class StdioTransport extends BaseTransport
{
private RunnerControlInterface $runnerControl;

/**
* @param resource $input
* @param resource $output
Expand All @@ -29,7 +34,9 @@ public function __construct(
private $input = \STDIN,
private $output = \STDOUT,
?LoggerInterface $logger = null,
?RunnerControlInterface $runnerControl = null,
) {
$this->runnerControl = $runnerControl ?? new RunnerControl();
parent::__construct($logger);
}

Expand All @@ -47,14 +54,17 @@ public function listen(): int
$this->logger->info('StdioTransport is listening for messages on STDIN...');
stream_set_blocking($this->input, false);

while (!feof($this->input)) {
while (!feof($this->input) && RunnerState::RUNNING === $this->runnerControl->getState()) {
$this->processInput();
$this->processFiber();
$this->flushOutgoingMessages();
}

$this->logger->info('StdioTransport finished listening.');
$this->handleSessionEnd($this->sessionId);
if (\in_array($this->runnerControl->getState(), [RunnerState::RUNNING, RunnerState::STOP_AND_END_SESSION], true)) {
$this->logger->info('StdioTransport end session.');
$this->handleSessionEnd($this->sessionId);
}

return 0;
}
Expand Down