-
Notifications
You must be signed in to change notification settings - Fork 146
Allow pre-built instance handlers in element registration #375
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
cc97489
b5b7544
70eb7fe
7def20b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,11 @@ | |||||
|
|
||||||
| All notable changes to `mcp/sdk` will be documented in this file. | ||||||
|
|
||||||
| 0.6.1 | ||||||
| ----- | ||||||
|
|
||||||
| * Allow registering an element handler as a pre-built object instance (`[$instance, 'methodName']`) via `Builder::addTool()`, `addResource()`, `addResourceTemplate()`, and `addPrompt()`. `HandlerResolver` previously rejected instances with "Invalid array handler format" even though the `Handler` type already permitted them — this unblocks handler objects with constructor dependencies that the container-less fallback cannot build. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| 0.6.0 | ||||||
| ----- | ||||||
|
|
||||||
|
|
||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pre-existing nit surfaced while reviewing this PR: at L78, the error message reads
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,11 +11,14 @@ | |
|
|
||
| namespace Mcp\Capability\Discovery; | ||
|
|
||
| use Mcp\Capability\Registry\ElementReference; | ||
| use Mcp\Exception\InvalidArgumentException; | ||
|
|
||
| /** | ||
| * Utility class to validate and resolve MCP element handlers. | ||
| * | ||
| * @phpstan-import-type Handler from ElementReference | ||
| * | ||
| * @author Kyrian Obikwelu <koshnawaza@gmail.com> | ||
| */ | ||
| class HandlerResolver | ||
|
|
@@ -25,11 +28,12 @@ class HandlerResolver | |
| * | ||
| * A handler can be: | ||
| * - A Closure: function() { ... } | ||
| * - An array: [ClassName::class, 'methodName'] (instance method) | ||
| * - An array: [ClassName::class, 'methodName'] (resolved on a new or container-provided instance) | ||
| * - An array: [$instance, 'methodName'] (method on a pre-built object instance) | ||
| * - An array: [ClassName::class, 'staticMethod'] (static method, if callable) | ||
| * - A string: InvokableClassName::class (which will resolve to its '__invoke' method) | ||
| * | ||
| * @param \Closure|array{0: string, 1: string}|string $handler the handler to resolve | ||
| * @param Handler $handler the handler to resolve | ||
| * | ||
| * @throws InvalidArgumentException If the handler format is invalid, the class/method doesn't exist, | ||
| * or the method is unsuitable (e.g., private, abstract). | ||
|
|
@@ -41,10 +45,11 @@ public static function resolve(\Closure|array|string $handler): \ReflectionMetho | |
| } | ||
|
|
||
| if (\is_array($handler)) { | ||
| if (2 !== \count($handler) || !isset($handler[0]) || !isset($handler[1]) || !\is_string($handler[0]) || !\is_string($handler[1])) { | ||
| throw new InvalidArgumentException('Invalid array handler format. Expected [ClassName::class, \'methodName\'].'); | ||
| if (2 !== \count($handler) || !isset($handler[0]) || !isset($handler[1]) || !(\is_string($handler[0]) || \is_object($handler[0])) || !\is_string($handler[1])) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Two options:
Also: the 4-clause negated condition is hard to scan. Consider extracting
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Went with option A — explicitly rejecting |
||
| throw new InvalidArgumentException('Invalid array handler format. Expected [ClassName::class, \'methodName\'] or [$instance, \'methodName\'].'); | ||
| } | ||
| [$className, $methodName] = $handler; | ||
| [$classOrObject, $methodName] = $handler; | ||
| $className = \is_object($classOrObject) ? $classOrObject::class : $classOrObject; | ||
| if (!class_exists($className)) { | ||
| throw new InvalidArgumentException(\sprintf('Handler class "%s" not found for array handler.', $className)); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's go with
0.7.0here - it's rather a feature to me: