Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
91.18% |
31 / 34 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
RemoteMcpController | |
91.18% |
31 / 34 |
|
50.00% |
1 / 2 |
3.01 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__invoke | |
90.91% |
30 / 33 |
|
0.00% |
0 / 1 |
2.00 |
1 | <?php |
2 | namespace Apie\McpServer\Controllers; |
3 | |
4 | use Apie\Core\ApieLib; |
5 | use Apie\McpServer\Tool\ToolFactory; |
6 | use Apie\McpServer\Tool\ToolRunner; |
7 | use Mcp\Server\HttpServerRunner; |
8 | use Mcp\Server\Server; |
9 | use Mcp\Server\Transport\Http\HttpMessage; |
10 | use Mcp\Server\Transport\Http\SessionStoreInterface; |
11 | use Nyholm\Psr7\Response; |
12 | use Nyholm\Psr7\Stream; |
13 | use Psr\Http\Message\ServerRequestInterface; |
14 | use Psr\Log\LoggerInterface; |
15 | |
16 | class RemoteMcpController |
17 | { |
18 | public function __construct( |
19 | private readonly ToolFactory $toolFactory, |
20 | private readonly ToolRunner $toolRunner, |
21 | private readonly LoggerInterface $logger, |
22 | private readonly ?SessionStoreInterface $sessionStore = null |
23 | ) { |
24 | } |
25 | public function __invoke(ServerRequestInterface $request): Response |
26 | { |
27 | $server = new Server('apie-server'); |
28 | $server->registerHandler('tools/list', function ($params) { |
29 | return $this->toolFactory->createList(); |
30 | }); |
31 | $server->registerHandler('tools/call', function ($params) use ($request) { |
32 | $name = $params->name; |
33 | $tool = $this->toolFactory->findByName($name); |
34 | return $this->toolRunner->run($tool, $params, $request); |
35 | }); |
36 | // TODO: configurable options? |
37 | $httpOptions = [ |
38 | 'session_timeout' => 1800, |
39 | 'max_queue_size' => 500, |
40 | 'enable_sse' => false, |
41 | 'shared_hosting' => true, |
42 | 'server_header' => 'Apie-MCP-Server/' . ApieLib::VERSION, |
43 | ]; |
44 | |
45 | $runner = new HttpServerRunner( |
46 | $server, |
47 | $server->createInitializationOptions(), |
48 | $httpOptions, |
49 | $this->logger, |
50 | $this->sessionStore |
51 | ); |
52 | $message = new HttpMessage($request->getBody()->getContents()); |
53 | $message->setMethod($request->getMethod()); |
54 | foreach ($request->getHeaders() as $name => $values) { |
55 | $message->setHeader($name, implode(', ', $values)); |
56 | } |
57 | $result = $runner->handleRequest($message); |
58 | |
59 | return new Response( |
60 | $result->getStatusCode(), |
61 | $result->getHeaders(), |
62 | Stream::create($result->getBody()) |
63 | ); |
64 | } |
65 | } |