• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 21001095414

14 Jan 2026 04:10PM UTC coverage: 0.0% (-29.1%) from 29.095%
21001095414

Pull #7595

github

web-flow
Merge 620cc601d into 73402fc61
Pull Request #7595: feat: mcp bundle tool integration

0 of 476 new or added lines in 16 files covered. (0.0%)

15042 existing lines in 491 files now uncovered.

0 of 58241 relevant lines covered (0.0%)

0.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Mcp/Server/Handler.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
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
declare(strict_types=1);
13

14
/*
15
 * This file is part of the official PHP MCP SDK.
16
 *
17
 * A collaboration between Symfony and the PHP Foundation.
18
 *
19
 * For the full copyright and license information, please view the LICENSE
20
 * file that was distributed with this source code.
21
 */
22

23
namespace ApiPlatform\Mcp\Server;
24

25
use ApiPlatform\Metadata\HttpOperation;
26
use ApiPlatform\Metadata\Operation\Factory\OperationMetadataFactoryInterface;
27
use ApiPlatform\State\ProcessorInterface;
28
use ApiPlatform\State\ProviderInterface;
29
use Mcp\Schema\JsonRpc\Error;
30
use Mcp\Schema\JsonRpc\Request;
31
use Mcp\Schema\JsonRpc\Response;
32
use Mcp\Schema\Request\CallToolRequest;
33
use Mcp\Schema\Request\ReadResourceRequest;
34
use Mcp\Schema\Result\CallToolResult;
35
use Mcp\Schema\Result\ReadResourceResult;
36
use Mcp\Server\Handler\Request\RequestHandlerInterface;
37
use Mcp\Server\Session\SessionInterface;
38
use Psr\Log\LoggerInterface;
39
use Psr\Log\NullLogger;
40
use Symfony\Component\HttpFoundation\RequestStack;
41

42
/**
43
 * @implements RequestHandlerInterface<CallToolResult|ReadResourceResult>
44
 */
45
final class Handler implements RequestHandlerInterface
46
{
47
    public function __construct(
48
        private readonly OperationMetadataFactoryInterface $operationMetadataFactory,
49
        private readonly ProviderInterface $provider,
50
        private readonly ProcessorInterface $processor,
51
        private readonly RequestStack $requestStack,
52
        private readonly LoggerInterface $logger = new NullLogger(),
53
    ) {
NEW
54
    }
×
55

56
    public function supports(Request $request): bool
57
    {
NEW
58
        return $request instanceof CallToolRequest || $request instanceof ReadResourceRequest;
×
59
    }
60

61
    /**
62
     * @return Response<CallToolResult|ReadResourceResult>|Error
63
     */
64
    public function handle(Request $request, SessionInterface $session): Response|Error
65
    {
NEW
66
        $isResource = $request instanceof ReadResourceRequest;
×
67

NEW
68
        if ($isResource) {
×
NEW
69
            $operationNameOrUri = $request->uri;
×
NEW
70
            $arguments = [];
×
NEW
71
            $this->logger->debug('Reading resource', ['uri' => $operationNameOrUri]);
×
72
        } else {
NEW
73
            \assert($request instanceof CallToolRequest);
×
NEW
74
            $operationNameOrUri = $request->name;
×
NEW
75
            $arguments = $request->arguments ?? [];
×
NEW
76
            $this->logger->debug('Executing tool', ['name' => $operationNameOrUri, 'arguments' => $arguments]);
×
77
        }
78

79
        /** @var HttpOperation $operation */
NEW
80
        $operation = $this->operationMetadataFactory->create($operationNameOrUri);
×
81

NEW
82
        $uriVariables = [];
×
NEW
83
        if (!$isResource) {
×
NEW
84
            foreach ($operation->getUriVariables() ?? [] as $key => $link) {
×
NEW
85
                if (isset($arguments[$key])) {
×
NEW
86
                    $uriVariables[$key] = $arguments[$key];
×
87
                }
88
            }
89
        }
90

NEW
91
        $context = [
×
NEW
92
            'request' => ($httpRequest = $this->requestStack->getCurrentRequest()),
×
NEW
93
            'mcp_request' => $request,
×
NEW
94
            'uri_variables' => $uriVariables,
×
NEW
95
            'resource_class' => $operation->getClass(),
×
NEW
96
        ];
×
97

NEW
98
        if (!$isResource) {
×
NEW
99
            $context['mcp_data'] = $arguments;
×
100
        }
101

NEW
102
        if (null === $operation->canValidate()) {
×
NEW
103
            $operation = $operation->withValidate(false);
×
104
        }
105

NEW
106
        if (null === $operation->canRead()) {
×
NEW
107
            $operation = $operation->withRead(true);
×
108
        }
109

NEW
110
        if (null === $operation->getProvider()) {
×
NEW
111
            $operation = $operation->withProvider('api_platform.mcp.state.tool_provider');
×
112
        }
113

NEW
114
        if (null === $operation->canDeserialize()) {
×
NEW
115
            $operation = $operation->withDeserialize(false);
×
116
        }
117

NEW
118
        $body = $this->provider->provide($operation, $uriVariables, $context);
×
119

NEW
120
        if (!$isResource) {
×
NEW
121
            $context['previous_data'] = $httpRequest->attributes->get('previous_data');
×
NEW
122
            $context['data'] = $httpRequest->attributes->get('data');
×
NEW
123
            $context['read_data'] = $httpRequest->attributes->get('read_data');
×
NEW
124
            $context['mapped_data'] = $httpRequest->attributes->get('mapped_data');
×
125
        }
126

NEW
127
        if (null === $operation->canWrite()) {
×
NEW
128
            $operation = $operation->withWrite(true);
×
129
        }
130

NEW
131
        if (null === $operation->canSerialize()) {
×
NEW
132
            $operation = $operation->withSerialize(false);
×
133
        }
134

NEW
135
        return $this->processor->process($body, $operation, $uriVariables, $context);
×
136
    }
137
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc