[Server] Keep injectable parameters out of the published inputSchema (#482)
This commit is contained in:
parent
ff0b5fadc8
commit
e173367c5f
3 changed files with 156 additions and 18 deletions
|
|
@ -13,9 +13,9 @@ namespace Mcp\Capability\Discovery;
|
|||
|
||||
use Mcp\Capability\Attribute\McpTool;
|
||||
use Mcp\Capability\Attribute\Schema;
|
||||
use Mcp\Capability\Registry\InjectableParameters;
|
||||
use Mcp\Exception\BadMethodCallException;
|
||||
use Mcp\Exception\InvalidArgumentException;
|
||||
use Mcp\Server\RequestContext;
|
||||
use phpDocumentor\Reflection\DocBlock\Tags\Param;
|
||||
|
||||
/**
|
||||
|
|
@ -528,12 +528,10 @@ final class SchemaGenerator implements SchemaGeneratorInterface
|
|||
foreach ($reflection->getParameters() as $rp) {
|
||||
$reflectionType = $rp->getType();
|
||||
|
||||
if ($reflectionType instanceof \ReflectionNamedType && !$reflectionType->isBuiltin()) {
|
||||
$typeName = $reflectionType->getName();
|
||||
|
||||
if (is_a($typeName, RequestContext::class, true)) {
|
||||
continue;
|
||||
}
|
||||
if ($reflectionType instanceof \ReflectionNamedType && !$reflectionType->isBuiltin()
|
||||
&& InjectableParameters::supports($reflectionType->getName())
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$paramName = $rp->getName();
|
||||
|
|
|
|||
63
src/Capability/Registry/InjectableParameters.php
Normal file
63
src/Capability/Registry/InjectableParameters.php
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?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\Capability\Registry;
|
||||
|
||||
use Mcp\Server\ClientGateway;
|
||||
use Mcp\Server\RequestContext;
|
||||
|
||||
/**
|
||||
* Single source of truth for handler parameter types the SDK injects itself.
|
||||
*
|
||||
* Both schema generation (which must exclude these parameters from the
|
||||
* published inputSchema) and argument preparation (which must inject them)
|
||||
* read this list, so the two cannot drift apart.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
final class InjectableParameters
|
||||
{
|
||||
private const TYPES = [
|
||||
RequestContext::class,
|
||||
ClientGateway::class,
|
||||
];
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function supports(string $typeName): bool
|
||||
{
|
||||
foreach (self::TYPES as $type) {
|
||||
if (is_a($typeName, $type, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $arguments the raw argument bag including the internal "_session" and "_request" entries
|
||||
*/
|
||||
public static function resolve(string $typeName, array $arguments): ?object
|
||||
{
|
||||
if (RequestContext::class === $typeName && isset($arguments['_session'], $arguments['_request'])) {
|
||||
return new RequestContext($arguments['_session'], $arguments['_request']);
|
||||
}
|
||||
|
||||
if (ClientGateway::class === $typeName && isset($arguments['_session'])) {
|
||||
return new ClientGateway($arguments['_session']);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -13,8 +13,6 @@ namespace Mcp\Capability\Registry;
|
|||
|
||||
use Mcp\Exception\InvalidArgumentException;
|
||||
use Mcp\Exception\RegistryException;
|
||||
use Mcp\Server\ClientGateway;
|
||||
use Mcp\Server\RequestContext;
|
||||
use Mcp\Server\Session\SessionInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
|
|
@ -106,15 +104,9 @@ final class ReferenceHandler implements ReferenceHandlerInterface
|
|||
// Check if parameter is a special injectable type
|
||||
$type = $parameter->getType();
|
||||
if ($type instanceof \ReflectionNamedType && !$type->isBuiltin()) {
|
||||
$typeName = $type->getName();
|
||||
|
||||
if (RequestContext::class === $typeName && isset($arguments['_session'], $arguments['_request'])) {
|
||||
$finalArgs[$paramPosition] = new RequestContext($arguments['_session'], $arguments['_request']);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ClientGateway::class === $typeName && isset($arguments['_session'])) {
|
||||
$finalArgs[$paramPosition] = new ClientGateway($arguments['_session']);
|
||||
$injected = InjectableParameters::resolve($type->getName(), $arguments);
|
||||
if (null !== $injected) {
|
||||
$finalArgs[$paramPosition] = $injected;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue