> $tools */ $tools = (new ReflectionClass(WhisperMoneyServer::class))->getDefaultProperties()['tools']; foreach ($tools as $class) { $tool = new $class; expect(mb_strlen((string) $tool->description())) ->toBeLessThanOrEqual(200, "description for {$tool->name()}"); } }); it('declares all three MCP hints on every tool', function () use ($readOnly, $destructive) { /** @var array> $tools */ $tools = (new ReflectionClass(WhisperMoneyServer::class))->getDefaultProperties()['tools']; expect($tools)->toHaveCount(count($readOnly) + 18); foreach ($tools as $class) { $tool = new $class; $annotations = $tool->annotations(); $name = $tool->name(); expect($annotations)->toHaveKeys(['readOnlyHint', 'destructiveHint', 'openWorldHint']) ->and($annotations['openWorldHint'])->toBeFalse() ->and($annotations['readOnlyHint'])->toBe(in_array($name, $readOnly, true), "readOnlyHint for {$name}") ->and($annotations['destructiveHint'])->toBe(in_array($name, $destructive, true), "destructiveHint for {$name}"); } });