Skip to content

Commit 5b4fb27

Browse files
feat: improve enum handling for unit enums when preparing element arguments
1 parent abfeb2c commit 5b4fb27

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

src/Elements/RegisteredElement.php

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
namespace PhpMcp\Server\Elements;
66

77
use InvalidArgumentException;
8+
use JsonSerializable;
89
use PhpMcp\Server\Exception\McpServerException;
910
use Psr\Container\ContainerInterface;
1011
use ReflectionException;
@@ -14,7 +15,7 @@
1415
use Throwable;
1516
use TypeError;
1617

17-
class RegisteredElement
18+
class RegisteredElement implements JsonSerializable
1819
{
1920
public function __construct(
2021
public readonly string $handlerClass,
@@ -95,16 +96,35 @@ private function castArgumentType(mixed $argument, ReflectionParameter $paramete
9596

9697
$typeName = $type->getName();
9798

98-
if (enum_exists($typeName) && is_subclass_of($typeName, \BackedEnum::class)) {
99-
try {
100-
return $typeName::from($argument);
101-
} catch (\ValueError $e) {
102-
$valueStr = is_scalar($argument) ? strval($argument) : gettype($argument);
103-
throw new InvalidArgumentException(
104-
"Invalid value '{$valueStr}' for enum {$typeName}.",
105-
0,
106-
$e
107-
);
99+
if (enum_exists($typeName)) {
100+
if (is_object($argument) && $argument instanceof $typeName) {
101+
return $argument;
102+
}
103+
104+
if (is_subclass_of($typeName, \BackedEnum::class)) {
105+
$value = $typeName::tryFrom($argument);
106+
if ($value === null) {
107+
throw new InvalidArgumentException(
108+
"Invalid value '{$argument}' for backed enum {$typeName}. Expected one of its backing values.",
109+
);
110+
}
111+
return $value;
112+
} else {
113+
if (is_string($argument)) {
114+
foreach ($typeName::cases() as $case) {
115+
if ($case->name === $argument) {
116+
return $case;
117+
}
118+
}
119+
$validNames = array_map(fn($c) => $c->name, $typeName::cases());
120+
throw new InvalidArgumentException(
121+
"Invalid value '{$argument}' for unit enum {$typeName}. Expected one of: " . implode(', ', $validNames) . "."
122+
);
123+
} else {
124+
throw new InvalidArgumentException(
125+
"Invalid value type '{$argument}' for unit enum {$typeName}. Expected a string matching a case name."
126+
);
127+
}
108128
}
109129
}
110130

@@ -179,4 +199,18 @@ private function castToArray(mixed $argument): array
179199
}
180200
throw new InvalidArgumentException('Cannot cast value to array. Expected array.');
181201
}
202+
203+
public function toArray(): array
204+
{
205+
return [
206+
'handlerClass' => $this->handlerClass,
207+
'handlerMethod' => $this->handlerMethod,
208+
'isManual' => $this->isManual,
209+
];
210+
}
211+
212+
public function jsonSerialize(): array
213+
{
214+
return $this->toArray();
215+
}
182216
}

0 commit comments

Comments
 (0)