Files
WP-LIT-MCP/tests/Unit/Guides/InstructionsBuilderTest.php
T
janniclas.loosenandClaude Opus 5.5 2f8a9f0c61 feat: configurable exposure policy for direct, indirect and disabled tools
Introduces ExposurePolicy (option lit_mcp_exposure) deciding per ability
whether it is a direct MCP tool, only reachable via mcp-adapter's
execute-ability meta-tool, or disabled entirely (not registered with the
Abilities API at all). Ability::isDirect() remains the default when no
override applies. lit/guide can never be disabled or made indirect;
lit/media-preview and lit/media-download (image/embedded-resource results)
can never be made indirect, only direct or disabled.

AbilityRegistrar and ServerRegistrar take an optional ExposurePolicy and
use it to filter registered abilities / compute the direct tool list.
IntegrationRegistry::directAbilityNames() is removed (superseded by
ExposurePolicy::directNames()). InstructionsBuilder now also takes the
policy and lists the currently direct tools by name (lit-<name>), noting
the rest are reachable via mcp-adapter-execute-ability as lit/<name>.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
2026-09-26 03:04:14 +02:00

86 lines
3.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace LIT\MCP\Tests\Unit\Guides;
use LIT\MCP\Abilities\Ability;
use LIT\MCP\Abilities\ExposurePolicy;
use LIT\MCP\Guides\InstructionsBuilder;
use LIT\MCP\Integrations\Integration;
use LIT\MCP\Integrations\IntegrationRegistry;
use LIT\MCP\Tests\Unit\TestCase;
use Mockery;
final class InstructionsBuilderTest extends TestCase
{
private function ability(string $name, bool $direct): Ability
{
$ability = Mockery::mock(Ability::class);
$ability->allows('name')->andReturn($name);
$ability->allows('isDirect')->andReturn($direct);
return $ability;
}
private function coreWith(Ability ...$abilities): Integration
{
$core = Mockery::mock(Integration::class);
$core->allows('id')->andReturn('core');
$core->allows('isAvailable')->andReturn(true);
$core->allows('abilities')->andReturn(array_values($abilities));
return $core;
}
public function testNamesActiveIntegrationsAndCoreRules(): void
{
$core = $this->coreWith($this->ability('lit/guide', true), $this->ability('lit/menu-list', false));
$text = (new InstructionsBuilder(new IntegrationRegistry($core)))->build();
self::assertStringContainsString('Aktive Integrationen: core', $text);
self::assertStringContainsString('lit-guide', $text);
self::assertStringContainsString('Status', $text);
self::assertLessThan(2000, strlen($text), 'Instructions must stay short – they are loaded in every conversation.');
}
public function testListsPostTypesWhenAProviderIsGiven(): void
{
$core = $this->coreWith($this->ability('lit/guide', true));
$text = (new InstructionsBuilder(new IntegrationRegistry($core), static fn (): array => ['page', 'post']))->build();
self::assertStringContainsString('Inhaltstypen: page, post', $text);
self::assertStringContainsString('lit-content-types', $text);
self::assertStringContainsString('confirm: true', $text);
}
public function testListsTheCurrentlyDirectToolsByToolNameAndNamesTheRestNeutrally(): void
{
$core = $this->coreWith(
$this->ability('lit/guide', true),
$this->ability('lit/menu-list', false)
);
$text = (new InstructionsBuilder(new IntegrationRegistry($core)))->build();
self::assertStringContainsString('Direkt aufrufbare Tools: lit-guide', $text);
self::assertStringContainsString('mcp-adapter-execute-ability', $text);
self::assertStringNotContainsString('lit-menu-list', $text);
}
public function testDirectToolListReflectsExposurePolicyOverrides(): void
{
$core = $this->coreWith(
$this->ability('lit/guide', true),
$this->ability('lit/menu-list', false)
);
$policy = new ExposurePolicy(['lit/menu-list' => 'direct']);
$text = (new InstructionsBuilder(new IntegrationRegistry($core), null, $policy))->build();
self::assertStringContainsString('lit-menu-list', $text);
}
}