diff --git a/src/Capability/Discovery/Discoverer.php b/src/Capability/Discovery/Discoverer.php index dab6590c..5b7e4765 100644 --- a/src/Capability/Discovery/Discoverer.php +++ b/src/Capability/Discovery/Discoverer.php @@ -217,7 +217,6 @@ private function processFile(SplFileInfo $file, array &$discoveredCount, array & private function processMethod(\ReflectionMethod $method, array &$discoveredCount, \ReflectionAttribute $attribute, array &$tools, array &$resources, array &$prompts, array &$resourceTemplates): void { $className = $method->getDeclaringClass()->getName(); - $classShortName = $method->getDeclaringClass()->getShortName(); $methodName = $method->getName(); $attributeClassName = $attribute->getName(); @@ -226,9 +225,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun switch ($attributeClassName) { case McpTool::class: - $docBlock = $this->docBlockParser->parseDocBlock($method->getDocComment() ?? null); - $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $instance->description ?? $this->docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($method, $instance->name); + $description = ElementMetadataResolver::resolveDescription($method, $instance->description, $this->docBlockParser); $inputSchema = $this->schemaGenerator->generate($method); $outputSchema = $this->schemaGenerator->generateOutputSchema($method); $tool = new Tool( @@ -246,9 +244,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun break; case McpResource::class: - $docBlock = $this->docBlockParser->parseDocBlock($method->getDocComment() ?? null); - $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $instance->description ?? $this->docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($method, $instance->name); + $description = ElementMetadataResolver::resolveDescription($method, $instance->description, $this->docBlockParser); $resource = new ResourceDefinition( $instance->uri, $name, @@ -267,8 +264,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun case McpPrompt::class: $docBlock = $this->docBlockParser->parseDocBlock($method->getDocComment() ?? null); - $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $instance->description ?? $this->docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($method, $instance->name); + $description = ElementMetadataResolver::resolveDescription($method, $instance->description, $this->docBlockParser); $arguments = []; $paramTags = $this->docBlockParser->getParamTags($docBlock); foreach ($method->getParameters() as $param) { @@ -286,9 +283,8 @@ private function processMethod(\ReflectionMethod $method, array &$discoveredCoun break; case McpResourceTemplate::class: - $docBlock = $this->docBlockParser->parseDocBlock($method->getDocComment() ?? null); - $name = $instance->name ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $instance->description ?? $this->docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($method, $instance->name); + $description = ElementMetadataResolver::resolveDescription($method, $instance->description, $this->docBlockParser); $mimeType = $instance->mimeType; $annotations = $instance->annotations; $meta = $instance->meta ?? null; diff --git a/src/Capability/Discovery/ElementMetadataResolver.php b/src/Capability/Discovery/ElementMetadataResolver.php new file mode 100644 index 00000000..3c755ddd --- /dev/null +++ b/src/Capability/Discovery/ElementMetadataResolver.php @@ -0,0 +1,44 @@ + + */ +final class ElementMetadataResolver +{ + private function __construct() + { + } + + /** + * Explicit names win; otherwise invokable classes are named after the class, + * regular handlers after the method. + */ + public static function resolveName(\ReflectionMethod $method, ?string $name): string + { + $methodName = $method->getName(); + + return $name ?? ('__invoke' === $methodName ? $method->getDeclaringClass()->getShortName() : $methodName); + } + + /** + * Explicit descriptions win; otherwise the summary of the method's doc block is used. + */ + public static function resolveDescription(\ReflectionMethod $method, ?string $description, DocBlockParser $docBlockParser): ?string + { + return $description ?? $docBlockParser->getDescription($docBlockParser->parseDocBlock($method->getDocComment() ?? null)); + } +} diff --git a/src/Capability/Registry/Loader/ReflectedElementLoader.php b/src/Capability/Registry/Loader/ReflectedElementLoader.php index a87dd58b..d1e849da 100644 --- a/src/Capability/Registry/Loader/ReflectedElementLoader.php +++ b/src/Capability/Registry/Loader/ReflectedElementLoader.php @@ -16,6 +16,7 @@ use Mcp\Capability\Completion\ListCompletionProvider; use Mcp\Capability\Completion\ProviderInterface; use Mcp\Capability\Discovery\DocBlockParser; +use Mcp\Capability\Discovery\ElementMetadataResolver; use Mcp\Capability\Discovery\HandlerResolver; use Mcp\Capability\Discovery\SchemaGenerator; use Mcp\Capability\Discovery\SchemaGeneratorInterface; @@ -106,12 +107,8 @@ public function load(RegistryInterface $registry): void $name = $data['name'] ?? 'closure_tool_'.spl_object_id($data['handler']); $description = $data['description'] ?? null; } else { - $classShortName = $reflection->getDeclaringClass()->getShortName(); - $methodName = $reflection->getName(); - $docBlock = $docBlockParser->parseDocBlock($reflection->getDocComment() ?? null); - - $name = $data['name'] ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $data['description'] ?? $docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($reflection, $data['name'] ?? null); + $description = ElementMetadataResolver::resolveDescription($reflection, $data['description'] ?? null, $docBlockParser); } $inputSchema = $data['inputSchema'] ?? $schemaGenerator->generate($reflection); @@ -148,12 +145,8 @@ public function load(RegistryInterface $registry): void $name = $data['name'] ?? 'closure_resource_'.spl_object_id($data['handler']); $description = $data['description'] ?? null; } else { - $classShortName = $reflection->getDeclaringClass()->getShortName(); - $methodName = $reflection->getName(); - $docBlock = $docBlockParser->parseDocBlock($reflection->getDocComment() ?? null); - - $name = $data['name'] ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $data['description'] ?? $docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($reflection, $data['name'] ?? null); + $description = ElementMetadataResolver::resolveDescription($reflection, $data['description'] ?? null, $docBlockParser); } $resource = new ResourceDefinition( @@ -189,12 +182,8 @@ public function load(RegistryInterface $registry): void $name = $data['name'] ?? 'closure_template_'.spl_object_id($data['handler']); $description = $data['description'] ?? null; } else { - $classShortName = $reflection->getDeclaringClass()->getShortName(); - $methodName = $reflection->getName(); - $docBlock = $docBlockParser->parseDocBlock($reflection->getDocComment() ?? null); - - $name = $data['name'] ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $data['description'] ?? $docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($reflection, $data['name'] ?? null); + $description = ElementMetadataResolver::resolveDescription($reflection, $data['description'] ?? null, $docBlockParser); } $template = new ResourceTemplate( @@ -229,12 +218,8 @@ public function load(RegistryInterface $registry): void $name = $data['name'] ?? 'closure_prompt_'.spl_object_id($data['handler']); $description = $data['description'] ?? null; } else { - $classShortName = $reflection->getDeclaringClass()->getShortName(); - $methodName = $reflection->getName(); - $docBlock = $docBlockParser->parseDocBlock($reflection->getDocComment() ?? null); - - $name = $data['name'] ?? ('__invoke' === $methodName ? $classShortName : $methodName); - $description = $data['description'] ?? $docBlockParser->getDescription($docBlock) ?? null; + $name = ElementMetadataResolver::resolveName($reflection, $data['name'] ?? null); + $description = ElementMetadataResolver::resolveDescription($reflection, $data['description'] ?? null, $docBlockParser); } $arguments = [];