Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/server/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

require_once dirname(__DIR__, 2).'/vendor/autoload.php';

set_exception_handler(function (Throwable $t): never {
set_exception_handler(static function (Throwable $t): never {
logger()->critical('Uncaught exception: '.$t->getMessage(), ['exception' => $t]);

exit(1);
Expand Down
2 changes: 1 addition & 1 deletion examples/server/client-communication/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
->setCapabilities(new ServerCapabilities(logging: true, tools: true))
->setDiscovery(__DIR__)
->addTool(
function (RequestContext $context, string $dataset): array {
static function (RequestContext $context, string $dataset): array {
$client = $context->getClientGateway();
$client->log(LoggingLevel::Info, sprintf('Running quality checks on dataset "%s"', $dataset));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function addTask(string $userId, string $description): array

public function getTasksForUser(string $userId): array
{
return array_values(array_filter($this->tasks, fn ($task) => $task['userId'] === $userId && !$task['completed']));
return array_values(array_filter($this->tasks, static fn ($task) => $task['userId'] === $userId && !$task['completed']));
}

public function getAllTasks(): array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
public function getSystemStats(): array
{
$allTasks = $this->taskRepository->getAllTasks();
$completed = \count(array_filter($allTasks, fn ($task) => $task['completed']));
$completed = \count(array_filter($allTasks, static fn ($task) => $task['completed']));
$pending = \count($allTasks) - $completed;

return [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ final class UserIdCompletionProvider implements ProviderInterface

public function getCompletions(string $currentValue): array
{
return array_filter(self::AVAILABLE_USER_IDS, fn (string $userId) => str_contains($userId, $currentValue));
return array_filter(self::AVAILABLE_USER_IDS, static fn (string $userId) => str_contains($userId, $currentValue));
}
}
4 changes: 2 additions & 2 deletions examples/server/discovery-userprofile/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
->setSession(new FileSessionStore(__DIR__.'/sessions'))
->setDiscovery(__DIR__)
->addTool(
function (float $a, float $b, string $operation = 'add'): array {
static function (float $a, float $b, string $operation = 'add'): array {
$result = match ($operation) {
'add' => $a + $b,
'subtract' => $a - $b,
Expand All @@ -42,7 +42,7 @@ function (float $a, float $b, string $operation = 'add'): array {
description: 'Perform basic math operations (add, subtract, multiply, divide)'
)
->addResource(
function (): array {
static function (): array {
$memoryUsage = memory_get_usage(true);
$memoryPeak = memory_get_peak_usage(true);
$uptime = time() - ($_SERVER['REQUEST_TIME_FLOAT'] ?? time());
Expand Down
12 changes: 6 additions & 6 deletions examples/server/env-variables/EnvToolHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ public function processData(string $input): array
'processed_input_length' => \strlen($input),
'message' => 'Processed in PRODUCTION mode (summary only).',
];
} else {
return [
'mode' => $appMode ?: 'default',
'original_input' => $input,
'message' => 'Processed in default mode (APP_MODE not recognized or not set).',
];
}

return [
'mode' => $appMode ?: 'default',
'original_input' => $input,
'message' => 'Processed in default mode (APP_MODE not recognized or not set).',
];
}
}
4 changes: 2 additions & 2 deletions examples/server/schema-showcase/SchemaShowcaseElements.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,10 @@ enum: ['sort', 'reverse', 'shuffle', 'deduplicate', 'filter_short', 'filter_long
$processed = array_unique($processed);
break;
case 'filter_short':
$processed = array_filter($processed, fn ($item) => \strlen($item) <= 10);
$processed = array_filter($processed, static fn ($item) => \strlen($item) <= 10);
break;
case 'filter_long':
$processed = array_filter($processed, fn ($item) => \strlen($item) > 10);
$processed = array_filter($processed, static fn ($item) => \strlen($item) > 10);
break;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Capability/Completion/EnumCompletionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function __construct(string $enumClass)
}

$this->values = array_map(
fn ($case) => isset($case->value) && \is_string($case->value) ? $case->value : $case->name,
static fn ($case) => isset($case->value) && \is_string($case->value) ? $case->value : $case->name,
$enumClass::cases()
);
}
Expand All @@ -46,7 +46,7 @@ public function getCompletions(string $currentValue): array

return array_values(array_filter(
$this->values,
fn (string $value) => str_starts_with($value, $currentValue)
static fn (string $value) => str_starts_with($value, $currentValue)
));
}
}
2 changes: 1 addition & 1 deletion src/Capability/Completion/ListCompletionProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function getCompletions(string $currentValue): array

return array_values(array_filter(
$this->values,
fn (string $value) => str_starts_with($value, $currentValue)
static fn (string $value) => str_starts_with($value, $currentValue)
));
}
}
6 changes: 3 additions & 3 deletions src/Capability/Discovery/SchemaGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ private function buildVariadicParameterSchema(array $paramInfo): array
// If no items specified by Schema attribute, infer from type
if (!isset($paramSchema['items'])) {
$itemJsonTypes = $this->mapPhpTypeToJsonSchemaType($paramInfo['type_string']);
$nonNullItemTypes = array_filter($itemJsonTypes, fn ($t) => 'null' !== $t);
$nonNullItemTypes = array_filter($itemJsonTypes, static fn ($t) => 'null' !== $t);

if (1 === \count($nonNullItemTypes)) {
$paramSchema['items'] = ['type' => $nonNullItemTypes[0]];
Expand Down Expand Up @@ -574,7 +574,7 @@ private function getTypeStringFromReflection(?\ReflectionType $type, bool $nativ
$types[] = $this->getTypeStringFromReflection($innerType, $innerType->allowsNull());
}
if ($nativeAllowsNull) {
$types = array_filter($types, fn ($t) => 'null' !== strtolower($t));
$types = array_filter($types, static fn ($t) => 'null' !== strtolower($t));
}
$typeString = implode('|', array_unique(array_filter($types)));
} elseif ($type instanceof \ReflectionIntersectionType) {
Expand Down Expand Up @@ -619,7 +619,7 @@ private function getTypeStringFromReflection(?\ReflectionType $type, bool $nativ
// Remove leading backslash from class names, but handle built-ins like 'int' or unions like 'int|string'
if (str_contains($typeString, '\\')) {
$parts = preg_split('/([|&])/', $typeString, -1, \PREG_SPLIT_DELIM_CAPTURE);
$processedParts = array_map(fn ($part) => str_starts_with($part, '\\') ? ltrim($part, '\\') : $part, $parts);
$processedParts = array_map(static fn ($part) => str_starts_with($part, '\\') ? ltrim($part, '\\') : $part, $parts);
$typeString = implode('', $processedParts);
}

Expand Down
16 changes: 8 additions & 8 deletions src/Capability/Discovery/SchemaValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ private function convertDataForValidator(mixed $data): mixed
}

return $obj;
} else {
// It's a list (sequential array), convert items recursively
return array_map([$this, 'convertDataForValidator'], $data);
}

// It's a list (sequential array), convert items recursively
return array_map([$this, 'convertDataForValidator'], $data);
} elseif (\is_object($data) && $data instanceof \stdClass) {
// Deep copy/convert stdClass objects as well
$obj = new \stdClass();
Expand Down Expand Up @@ -194,7 +194,7 @@ private function formatJsonPointerPath(?array $pathComponents): string
if (empty($pathComponents)) {
return '/';
}
$escapedComponents = array_map(function ($component) {
$escapedComponents = array_map(static function ($component) {
$componentStr = (string) $component;

return str_replace(['~', '/'], ['~0', '~1'], $componentStr);
Expand All @@ -215,7 +215,7 @@ private function formatValidationError(ValidationError $error): string
switch (strtolower($keyword)) {
case 'required':
$missing = $args['missing'] ?? [];
$formattedMissing = implode(', ', array_map(fn ($p) => "`{$p}`", $missing));
$formattedMissing = implode(', ', array_map(static fn ($p) => "`{$p}`", $missing));
$message = "Missing required properties: {$formattedMissing}.";
break;
case 'type':
Expand All @@ -236,7 +236,7 @@ private function formatValidationError(ValidationError $error): string
if (empty($allowedValues)) {
$message = 'Value does not match the allowed enumeration.';
} else {
$formattedAllowed = array_map(function ($v) { /* ... formatting logic ... */
$formattedAllowed = array_map(static function ($v) { /* ... formatting logic ... */
if (\is_string($v)) {
return '"'.$v.'"';
}
Expand Down Expand Up @@ -309,7 +309,7 @@ private function formatValidationError(ValidationError $error): string
break;
case 'additionalProperties': // Corrected casing
$unexpected = $args['properties'] ?? [];
$formattedUnexpected = implode(', ', array_map(fn ($p) => "`{$p}`", $unexpected));
$formattedUnexpected = implode(', ', array_map(static fn ($p) => "`{$p}`", $unexpected));
$message = "Object contains unexpected additional properties: {$formattedUnexpected}.";
break;
case 'format':
Expand All @@ -320,7 +320,7 @@ private function formatValidationError(ValidationError $error): string
$builtInMessage = $error->message();
if ($builtInMessage && 'The data must match the schema' !== $builtInMessage) {
$placeholders = $args;
$builtInMessage = preg_replace_callback('/\{(\w+)\}/', function ($match) use ($placeholders) {
$builtInMessage = preg_replace_callback('/\{(\w+)\}/', static function ($match) use ($placeholders) {
$key = $match[1];
$value = $placeholders[$key] ?? '{'.$key.'}';

Expand Down
2 changes: 1 addition & 1 deletion src/Capability/Formatter/ResourceResultFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public function format(mixed $readResult, string $uri, ?string $mimeType = null,
}

if ($allAreEmbeddedResource && $hasEmbeddedResource) {
return array_map(fn ($item) => $item->resource, $readResult);
return array_map(static fn ($item) => $item->resource, $readResult);
}

if ($hasResourceContents || $hasEmbeddedResource) {
Expand Down
8 changes: 4 additions & 4 deletions src/Capability/Registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,10 @@ public function getPrompt(string $name): PromptReference
public function getDiscoveryState(): DiscoveryState
{
return new DiscoveryState(
tools: array_filter($this->tools, fn ($tool) => !$tool->isManual),
resources: array_filter($this->resources, fn ($resource) => !$resource->isManual),
prompts: array_filter($this->prompts, fn ($prompt) => !$prompt->isManual),
resourceTemplates: array_filter($this->resourceTemplates, fn ($template) => !$template->isManual),
tools: array_filter($this->tools, static fn ($tool) => !$tool->isManual),
resources: array_filter($this->resources, static fn ($resource) => !$resource->isManual),
prompts: array_filter($this->prompts, static fn ($prompt) => !$prompt->isManual),
resourceTemplates: array_filter($this->resourceTemplates, static fn ($template) => !$template->isManual),
);
}

Expand Down
18 changes: 8 additions & 10 deletions src/Capability/Registry/ReferenceHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,19 +185,17 @@ private function castArgumentType(mixed $argument, \ReflectionParameter $paramet
}

return $value;
} else {
if (\is_string($argument)) {
foreach ($typeName::cases() as $case) {
if ($case->name === $argument) {
return $case;
}
}
if (\is_string($argument)) {
foreach ($typeName::cases() as $case) {
if ($case->name === $argument) {
return $case;
}
$validNames = array_map(fn ($c) => $c->name, $typeName::cases());
throw new InvalidArgumentException("Invalid value '{$argument}' for unit enum {$typeName}. Expected one of: ".implode(', ', $validNames).'.');
} else {
throw new InvalidArgumentException("Invalid value type '{$argument}' for unit enum {$typeName}. Expected a string matching a case name.");
}
$validNames = array_map(static fn ($c) => $c->name, $typeName::cases());
throw new InvalidArgumentException("Invalid value '{$argument}' for unit enum {$typeName}. Expected one of: ".implode(', ', $validNames).'.');
}
throw new InvalidArgumentException("Invalid value type '{$argument}' for unit enum {$typeName}. Expected a string matching a case name.");
}

try {
Expand Down
6 changes: 3 additions & 3 deletions src/Schema/Annotations.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function __construct(
}
if (null !== $this->audience) {
foreach ($this->audience as $role) {
if (!($role instanceof Role)) {
if (!$role instanceof Role) {
throw new InvalidArgumentException('All audience members must be instances of Role enum.');
}
}
Expand All @@ -60,7 +60,7 @@ public static function fromArray(array $data): self
{
$audience = null;
if (isset($data['audience']) && \is_array($data['audience'])) {
$audience = array_map(fn (string $r) => Role::from($r), $data['audience']);
$audience = array_map(static fn (string $r) => Role::from($r), $data['audience']);
}

return new self(
Expand All @@ -76,7 +76,7 @@ public function jsonSerialize(): array
{
$data = [];
if (null !== $this->audience) {
$data['audience'] = array_map(fn (Role $r) => $r->value, $this->audience);
$data['audience'] = array_map(static fn (Role $r) => $r->value, $this->audience);
}
if (null !== $this->priority) {
$data['priority'] = $this->priority;
Expand Down
4 changes: 2 additions & 2 deletions src/Schema/Prompt.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function __construct(
) {
if (null !== $this->arguments) {
foreach ($this->arguments as $arg) {
if (!($arg instanceof PromptArgument)) {
if (!$arg instanceof PromptArgument) {
throw new InvalidArgumentException('All items in Prompt "arguments" must be PromptArgument instances.');
}
}
Expand All @@ -64,7 +64,7 @@ public static function fromArray(array $data): self
}
$arguments = null;
if (isset($data['arguments']) && \is_array($data['arguments'])) {
$arguments = array_map(fn (array $argData) => PromptArgument::fromArray($argData), $data['arguments']);
$arguments = array_map(static fn (array $argData) => PromptArgument::fromArray($argData), $data['arguments']);
}

if (!empty($data['_meta']) && !\is_array($data['_meta'])) {
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/Result/ListPromptsResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function fromArray(array $data): self
}

return new self(
array_map(fn (array $prompt) => Prompt::fromArray($prompt), $data['prompts']),
array_map(static fn (array $prompt) => Prompt::fromArray($prompt), $data['prompts']),
$data['nextCursor'] ?? null
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/Result/ListResourceTemplatesResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function fromArray(array $data): self
}

return new self(
array_map(fn (array $resourceTemplate) => ResourceTemplate::fromArray($resourceTemplate), $data['resourceTemplates']),
array_map(static fn (array $resourceTemplate) => ResourceTemplate::fromArray($resourceTemplate), $data['resourceTemplates']),
$data['nextCursor'] ?? null
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/Result/ListResourcesResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function fromArray(array $data): self
}

return new self(
array_map(fn (array $resource) => ResourceSchema::fromArray($resource), $data['resources']),
array_map(static fn (array $resource) => ResourceSchema::fromArray($resource), $data['resources']),
$data['nextCursor'] ?? null
);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Schema/Result/ListToolsResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public static function fromArray(array $data): self
}

return new self(
array_map(fn (array $tool) => Tool::fromArray($tool), $data['tools']),
array_map(static fn (array $tool) => Tool::fromArray($tool), $data['tools']),
$data['nextCursor'] ?? null
);
}
Expand Down
11 changes: 5 additions & 6 deletions src/Server/Protocol.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ private function handleRequest(TransportInterface $transport, Request $request,

try {
/** @var McpFiber $fiber */
$fiber = new \Fiber(fn () => $handler->handle($request, $session));
$fiber = new \Fiber(static fn () => $handler->handle($request, $session));

$result = $fiber->start();

Expand All @@ -192,11 +192,10 @@ private function handleRequest(TransportInterface $transport, Request $request,
$transport->attachFiberToSession($fiber, $session->getId());

return;
} else {
$finalResult = $fiber->getReturn();

$this->sendResponse($transport, $finalResult, $session);
}
$finalResult = $fiber->getReturn();

$this->sendResponse($transport, $finalResult, $session);
} catch (\InvalidArgumentException $e) {
$this->logger->warning(\sprintf('Invalid argument: %s', $e->getMessage()), ['exception' => $e]);

Expand Down Expand Up @@ -581,7 +580,7 @@ private function gcSessions(): void
if (!empty($deletedSessions)) {
$this->logger->debug('Garbage collected expired sessions.', [
'count' => \count($deletedSessions),
'session_ids' => array_map(fn (Uuid $id) => $id->toRfc4122(), $deletedSessions),
'session_ids' => array_map(static fn (Uuid $id) => $id->toRfc4122(), $deletedSessions),
]);
}
}
Expand Down
Loading