. */ declare(strict_types=1); namespace App\Services\InfoProviderSystem\DTOs; use ApiPlatform\Metadata\ApiResource; use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\McpToolCollection; use ApiPlatform\OpenApi\Model\Operation; use App\Mcp\DTO\ListInfoProvidersInput; use App\Services\InfoProviderSystem\Providers\ProviderCapabilities; use App\State\Mcp\ListInfoProvidersProcessor; use Symfony\Component\Serializer\Annotation\Groups; /** * Immutable, structured description of an info provider, returned by InfoProviderInterface::getProviderInfo() * and (via the 'info_provider:read' group) exposed as the REST GET /api/info_providers collection and the * list_info_providers MCP tool. * * disabledHelp, oauthAppName and settingsClass are internal-only (used by the settings UI) and deliberately * not tagged with the 'info_provider:read' group, so they never appear in the API/MCP output. */ #[ApiResource( uriTemplate: '/info_providers', description: 'An info provider which can be used to search for parts and retrieve part details.', operations: [ new GetCollection( security: 'is_granted("@info_providers.create_parts")', provider: ListInfoProvidersProcessor::class, openapi: new Operation(summary: 'List the info providers which are currently active and can be used for searching parts.'), ), ], paginationEnabled: false, normalizationContext: ['groups' => ['info_provider:read']], mcp: [ 'list_info_providers' => new McpToolCollection( title: 'List available info providers', description: 'List the info providers (e.g. distributors like Digikey, Mouser, LCSC) which are currently active and can be used with search_info_providers and get_info_provider_part_details.', annotations: ['readOnlyHint' => true, 'destructiveHint' => false, 'idempotentHint' => true, 'openWorldHint' => false], input: ListInfoProvidersInput::class, security: 'is_granted("@info_providers.create_parts")', processor: ListInfoProvidersProcessor::class, normalizationContext: ['groups' => ['info_provider:read']], ), ], )] readonly class ProviderInfoDTO { public function __construct( /** @var string A unique key for this provider (e.g. "digikey"), which is saved into the database and used to identify the provider */ #[Groups(['info_provider:read'])] public string $key, /** @var string The (user friendly) name of the provider (e.g. "Digikey"), will be translated */ #[Groups(['info_provider:read'])] public string $name, /** @var string|null A short description of the provider (e.g. "Digikey is a ..."), will be translated */ #[Groups(['info_provider:read'])] public ?string $description = null, /** @var string|null The url of the provider (e.g. "https://www.digikey.com") */ #[Groups(['info_provider:read'])] public ?string $url = null, /** @var string|null A help text which is shown when the provider is disabled, explaining how to enable it */ public ?string $disabledHelp = null, /** @var string|null The name of the OAuth app which is used for authentication (e.g. "ip_digikey_oauth"). If this is set a connect button will be shown */ public ?string $oauthAppName = null, /** @var class-string|null The class name of the settings class which contains the settings for this provider (e.g. "App\Settings\InfoProviderSettings\DigikeySettings"). If this is set a link to the settings will be shown */ public ?string $settingsClass = null, /** * A list of capabilities this provider supports (which kind of data it can provide). * Not every part have to contain all of these data, but the provider should be able to provide them in general. * Currently, this list is purely informational and not used in functional checks. * @var ProviderCapabilities[] */ #[Groups(['info_provider:read'])] public array $capabilities = [], ) { } }