Skip to content

Commit 2dbd411

Browse files
[Server] Simplify server entrypoint with run-based transport lifecycle (#103)
* feat: replace connect/listen flow with run lifecycle * feat(transport): add phpstan generics for typed transport returns * refactor: standardize variable naming for MCP server instances in transport handling * test: remove unnecessary phpstan-ignore annotation in DocBlockTestFixture
1 parent e2243bc commit 2dbd411

File tree

19 files changed

+82
-74
lines changed

19 files changed

+82
-74
lines changed

README.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ $server = Server::builder()
108108
->build();
109109

110110
$transport = new StdioTransport();
111-
$server->connect($transport);
112-
$transport->listen();
111+
112+
$server->run($transport);
113113
```
114114

115115
### 3. Configure Your MCP Client
@@ -175,15 +175,13 @@ $server = Server::builder()
175175
**STDIO Transport** (Command-line integration):
176176
```php
177177
$transport = new StdioTransport();
178-
$server->connect($transport);
179-
$transport->listen();
178+
$server->run($transport);
180179
```
181180

182181
**HTTP Transport** (Web-based communication):
183182
```php
184183
$transport = new StreamableHttpTransport($request, $responseFactory, $streamFactory);
185-
$server->connect($transport);
186-
$response = $transport->listen();
184+
$response = $server->run($transport);
187185
// Handle $response in your web application
188186
```
189187

docs/transports.md

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,7 @@ $server = Server::builder()
2222

2323
$transport = new SomeTransport();
2424

25-
$server->connect($transport);
26-
27-
$transport->listen(); // For STDIO, or handle response for HTTP
25+
$result = $server->run($transport); // Blocks for STDIO, returns a response for HTTP
2826
```
2927

3028
## STDIO Transport
@@ -70,9 +68,9 @@ $server = Server::builder()
7068

7169
$transport = new StdioTransport();
7270

73-
$server->connect($transport);
71+
$status = $server->run($transport);
7472

75-
$transport->listen();
73+
exit($status); // 0 on clean shutdown, non-zero if STDIN errored
7674
```
7775

7876
### Client Configuration
@@ -138,24 +136,20 @@ use Nyholm\Psr7\Factory\Psr17Factory;
138136
use Nyholm\Psr7Server\ServerRequestCreator;
139137
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
140138

141-
// Create PSR-7 request from globals
142139
$psr17Factory = new Psr17Factory();
143140
$creator = new ServerRequestCreator($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
144141
$request = $creator->fromGlobals();
145142

146-
// Build server
147143
$server = Server::builder()
148144
->setServerInfo('HTTP Server', '1.0.0')
149145
->setDiscovery(__DIR__, ['.'])
150146
->setSession(new FileSessionStore(__DIR__ . '/sessions')) // HTTP needs persistent sessions
151147
->build();
152148

153-
// Process request and get response
154149
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
155-
$server->connect($transport);
156-
$response = $transport->listen();
157150

158-
// Emit response
151+
$response = $server->run($transport);
152+
159153
(new SapiEmitter())->emit($response);
160154
```
161155

@@ -187,7 +181,7 @@ use Mcp\Server\Transport\StreamableHttpTransport;
187181
class McpController
188182
{
189183
#[Route('/mcp', name: 'mcp_endpoint']
190-
public function handle(Request $request, Server $mcpServer): Response
184+
public function handle(Request $request, Server $server): Response
191185
{
192186
// Create PSR-7 factories
193187
$psr17Factory = new Psr17Factory();
@@ -199,8 +193,7 @@ class McpController
199193

200194
// Process with MCP
201195
$transport = new StreamableHttpTransport($psrRequest, $psr17Factory, $psr17Factory);
202-
$mcpServer->connect($transport);
203-
$psrResponse = $transport->listen();
196+
$psrResponse = $server->run($transport);
204197

205198
// Convert PSR-7 response back to Symfony
206199
return $httpFoundationFactory->createResponse($psrResponse);
@@ -230,17 +223,16 @@ use Nyholm\Psr7\Factory\Psr17Factory;
230223

231224
class McpController
232225
{
233-
public function handle(ServerRequestInterface $request, Server $mcpServer): ResponseInterface
226+
public function handle(ServerRequestInterface $request, Server $server): ResponseInterface
234227
{
235228
$psr17Factory = new Psr17Factory();
236229

237-
// Create and connect the MCP HTTP transport
230+
// Create the MCP HTTP transport
238231
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
239-
$mcpServer->connect($transport);
240232

241233
// Process MCP request and return PSR-7 response
242234
// Laravel automatically handles PSR-7 responses
243-
return $transport->listen();
235+
return $server->run($transport);
244236
}
245237
}
246238

@@ -255,33 +247,26 @@ Slim Framework works natively with PSR-7.
255247
Create a route handler using Slim's built-in factories and container:
256248

257249
```php
258-
use Psr\Container\ContainerInterface;
259250
use Slim\Factory\AppFactory;
260251
use Slim\Psr7\Factory\ResponseFactory;
261252
use Slim\Psr7\Factory\StreamFactory;
262253
use Mcp\Server;
263254
use Mcp\Server\Transport\StreamableHttpTransport;
264255

265256
$app = AppFactory::create();
266-
$container = $app->getContainer();
267257

268-
$container->set('mcpServer', function (ContainerInterface $container) {
269-
return Server::builder()
258+
$app->any('/mcp', function ($request, $response) {
259+
$server = Server::builder()
270260
->setServerInfo('My MCP Server', '1.0.0')
271261
->setDiscovery(__DIR__, ['.'])
272262
->build();
273-
});
274-
275-
$app->any('/mcp', function ($request, $response) {
276-
$mcpServer = $this->get('mcpServer');
277263

278264
$responseFactory = new ResponseFactory();
279265
$streamFactory = new StreamFactory();
280266

281267
$transport = new StreamableHttpTransport($request, $responseFactory, $streamFactory);
282-
$mcpServer->connect($transport);
283268

284-
return $transport->listen();
269+
return $server->run($transport);
285270
});
286271
```
287272

examples/custom-method-handlers/server.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ public function handle(CallToolRequest|HasMethodInterface $message, SessionInter
137137

138138
$transport = new StdioTransport(logger: logger());
139139

140-
$server->connect($transport);
140+
$result = $server->run($transport);
141141

142-
$transport->listen();
142+
logger()->info('Server listener stopped gracefully.', ['result' => $result]);
143143

144-
logger()->info('Server listener stopped gracefully.');
144+
exit($result);

examples/http-combined-registration/server.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@
4242

4343
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
4444

45-
$server->connect($transport);
46-
47-
$response = $transport->listen();
45+
$response = $server->run($transport);
4846

4947
(new SapiEmitter())->emit($response);

examples/http-complex-tool-schema/server.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535

3636
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
3737

38-
$server->connect($transport);
39-
40-
$response = $transport->listen();
38+
$response = $server->run($transport);
4139

4240
(new SapiEmitter())->emit($response);

examples/http-discovery-userprofile/server.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ function (): array {
7777

7878
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
7979

80-
$server->connect($transport);
81-
82-
$response = $transport->listen();
80+
$response = $server->run($transport);
8381

8482
(new SapiEmitter())->emit($response);

examples/http-schema-showcase/server.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@
3535

3636
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
3737

38-
$server->connect($transport);
39-
40-
$response = $transport->listen();
38+
$response = $server->run($transport);
4139

4240
(new SapiEmitter())->emit($response);

examples/stdio-cached-discovery/server.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131

3232
$transport = new StdioTransport(logger: logger());
3333

34-
$server->connect($transport);
34+
$result = $server->run($transport);
3535

36-
$transport->listen();
36+
logger()->info('Server listener stopped gracefully.', ['result' => $result]);
3737

38-
logger()->info('Server listener stopped gracefully.');
38+
exit($result);

examples/stdio-custom-dependencies/server.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@
3939

4040
$transport = new StdioTransport(logger: logger());
4141

42-
$server->connect($transport);
42+
$result = $server->run($transport);
4343

44-
$transport->listen();
44+
logger()->info('Server listener stopped gracefully.', ['result' => $result]);
4545

46-
logger()->info('Server listener stopped gracefully.');
46+
exit($result);

examples/stdio-discovery-calculator/server.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828

2929
$transport = new StdioTransport(logger: logger());
3030

31-
$server->connect($transport);
31+
$result = $server->run($transport);
3232

33-
$transport->listen();
33+
logger()->info('Server listener stopped gracefully.', ['result' => $result]);
3434

35-
logger()->info('Server listener stopped gracefully.');
35+
exit($result);

0 commit comments

Comments
 (0)