Skip to content

Commit 7a8045a

Browse files
authored
Add a way to stop the stdioTransport in a graceful way (#195)
* Add a way to stop the stdioTransport in a graceful way * fix cs * fix: minors * move around files * add changelog
1 parent a07083a commit 7a8045a

5 files changed

Lines changed: 91 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to `mcp/sdk` will be documented in this file.
44

5+
0.2.1
6+
-----
7+
8+
* Add `RunnerControl` for `StdioTransport` to allow break out from continuously listening for new input.
9+
510
0.2.0
611
-----
712

@@ -13,7 +18,6 @@ All notable changes to `mcp/sdk` will be documented in this file.
1318
* Removed `Protocol::getTransport()`
1419
* Added parameter for `TransportInterface` to `Protocol::processInput()`
1520

16-
1721
0.1.0
1822
-----
1923

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the official PHP MCP SDK.
5+
*
6+
* A collaboration between Symfony and the PHP Foundation.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Mcp\Server\Transport\Stdio;
13+
14+
/**
15+
* Default implementation of RunnerControlInterface. This will allow
16+
* anyone to change the state of the runner.
17+
*
18+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
19+
*/
20+
class RunnerControl implements RunnerControlInterface
21+
{
22+
public static RunnerState $state = RunnerState::RUNNING;
23+
24+
public function getState(): RunnerState
25+
{
26+
return self::$state;
27+
}
28+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the official PHP MCP SDK.
5+
*
6+
* A collaboration between Symfony and the PHP Foundation.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Mcp\Server\Transport\Stdio;
13+
14+
/**
15+
* Used by the transport to control the runner state.
16+
*
17+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
18+
*/
19+
interface RunnerControlInterface
20+
{
21+
public function getState(): RunnerState;
22+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the official PHP MCP SDK.
5+
*
6+
* A collaboration between Symfony and the PHP Foundation.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Mcp\Server\Transport\Stdio;
13+
14+
/**
15+
* State for the transport.
16+
*
17+
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
18+
*/
19+
enum RunnerState
20+
{
21+
case RUNNING;
22+
case STOP_AND_END_SESSION;
23+
case STOP;
24+
}

src/Server/Transport/StdioTransport.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
namespace Mcp\Server\Transport;
1313

1414
use Mcp\Schema\JsonRpc\Error;
15+
use Mcp\Server\Transport\Stdio\RunnerControl;
16+
use Mcp\Server\Transport\Stdio\RunnerControlInterface;
17+
use Mcp\Server\Transport\Stdio\RunnerState;
1518
use Psr\Log\LoggerInterface;
1619

1720
/**
@@ -21,6 +24,8 @@
2124
*/
2225
class StdioTransport extends BaseTransport
2326
{
27+
private RunnerControlInterface $runnerControl;
28+
2429
/**
2530
* @param resource $input
2631
* @param resource $output
@@ -29,7 +34,9 @@ public function __construct(
2934
private $input = \STDIN,
3035
private $output = \STDOUT,
3136
?LoggerInterface $logger = null,
37+
?RunnerControlInterface $runnerControl = null,
3238
) {
39+
$this->runnerControl = $runnerControl ?? new RunnerControl();
3340
parent::__construct($logger);
3441
}
3542

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

50-
while (!feof($this->input)) {
57+
while (!feof($this->input) && RunnerState::RUNNING === $this->runnerControl->getState()) {
5158
$this->processInput();
5259
$this->processFiber();
5360
$this->flushOutgoingMessages();
5461
}
5562

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

5969
return 0;
6070
}

0 commit comments

Comments
 (0)