Skip to main content
Glama

CTX: Context as Code (CaC) tool

by context-hub
MIT License
235
  • Apple
  • Linux
ListPromptsCommand.php8.32 kB
<?php declare(strict_types=1); namespace Butschster\ContextGenerator\McpServer\Prompt\Console; use Butschster\ContextGenerator\Application\AppScope; use Butschster\ContextGenerator\Config\ConfigurationProvider; use Butschster\ContextGenerator\Config\Exception\ConfigLoaderException; use Butschster\ContextGenerator\Console\BaseCommand; use Butschster\ContextGenerator\Console\Renderer\Style; use Butschster\ContextGenerator\DirectoriesInterface; use Butschster\ContextGenerator\McpServer\Prompt\Extension\PromptDefinition; use Butschster\ContextGenerator\McpServer\Prompt\Filter\FilterStrategy; use Butschster\ContextGenerator\McpServer\Prompt\Filter\PromptFilterFactory; use Butschster\ContextGenerator\McpServer\Prompt\Filter\PromptFilterInterface; use Butschster\ContextGenerator\McpServer\Prompt\PromptProviderInterface; use Butschster\ContextGenerator\McpServer\Prompt\PromptType; use PhpMcp\Schema\Prompt; use Spiral\Console\Attribute\Option; use Spiral\Core\Container; use Spiral\Core\Scope; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Helper\TableCell; use Symfony\Component\Console\Helper\TableCellStyle; use Symfony\Component\Console\Helper\TableSeparator; #[AsCommand( name: 'prompts:list', description: 'List all available prompts with their details', aliases: ['prompts'], )] final class ListPromptsCommand extends BaseCommand { #[Option( name: 'config-file', shortcut: 'c', description: 'Path to configuration file (absolute or relative to current directory).', )] protected ?string $configPath = null; #[Option( name: 'tag', shortcut: 't', description: 'Filter prompts by tag (can be used multiple times)', )] protected array $tags = []; #[Option( name: 'exclude-tag', shortcut: 'x', description: 'Exclude prompts with specific tag (can be used multiple times)', )] protected array $excludeTags = []; #[Option( name: 'id', shortcut: 'p', description: 'Filter prompts by ID (can be used multiple times)', )] protected array $promptIds = []; #[Option( name: 'detailed', shortcut: 'd', description: 'Show detailed information including arguments', )] protected bool $detailed = false; public function __invoke(Container $container, DirectoriesInterface $dirs): int { return $container->runScope( bindings: new Scope( name: AppScope::Compiler, bindings: [ DirectoriesInterface::class => $dirs->determineRootPath($this->configPath), ], ), scope: function ( ConfigurationProvider $configProvider, PromptProviderInterface $promptProvider, PromptFilterFactory $filterFactory, ) { try { // Get the appropriate loader based on options provided if ($this->configPath !== null) { $this->logger->info(\sprintf('Loading configuration from %s...', $this->configPath)); $loader = $configProvider->fromPath($this->configPath); } else { $this->logger->info('Loading configuration from default location...'); $loader = $configProvider->fromDefaultLocation(); } } catch (ConfigLoaderException $e) { $this->logger->error('Failed to load configuration', [ 'error' => $e->getMessage(), ]); $this->output->error(\sprintf('Failed to load configuration: %s', $e->getMessage())); return Command::FAILURE; } // Load configuration to make sure all prompts are properly registered $loader->load(); // Get all prompts $prompts = $promptProvider->all(); // Create filter based on command options $filter = $this->createFilter($filterFactory); // Apply filter if needed if ($filter !== null) { $filteredPrompts = []; foreach ($prompts as $id => $promptDef) { $promptConfig = [ 'id' => $promptDef->id, 'tags' => $promptDef->tags, ]; if ($filter->shouldInclude($promptConfig)) { $filteredPrompts[$id] = $promptDef; } } $prompts = $filteredPrompts; } if (empty($prompts)) { $this->output->warning('No prompts found matching the specified criteria.'); return Command::SUCCESS; } // Display prompts based on the selected format return $this->displayAsTable($prompts); }, ); } /** * Creates a filter based on command options. */ private function createFilter(PromptFilterFactory $filterFactory): ?PromptFilterInterface { $filterConfig = []; // Add ID filter if provided if (!empty($this->promptIds)) { $filterConfig['ids'] = $this->promptIds; } // Add tag filters if provided if (!empty($this->tags) || !empty($this->excludeTags)) { $filterConfig['tags'] = []; if (!empty($this->tags)) { $filterConfig['tags']['include'] = $this->tags; $filterConfig['tags']['match'] = FilterStrategy::ANY->value; } if (!empty($this->excludeTags)) { $filterConfig['tags']['exclude'] = $this->excludeTags; } } return $filterFactory->createFromConfig($filterConfig); } /** * Displays prompts as a table. * @param array<PromptDefinition> $prompts */ private function displayAsTable(array $prompts): int { $title = 'Available Prompts'; $this->output->title($title); $table = new Table($this->output); if ($this->detailed) { $table->setHeaders(['ID', 'Type', 'Description', 'Tags', 'Arguments']); } else { $table->setHeaders(['ID', 'Type', 'Description', 'Tags']); } foreach ($prompts as $promptDef) { $row = [ new TableCell($promptDef->id, ['style' => new TableCellStyle(['fg' => 'cyan'])]), new TableCell( $promptDef->type->value, [ 'style' => new TableCellStyle( ['fg' => $promptDef->type === PromptType::Prompt ? 'green' : 'blue'], ), ], ), $promptDef->prompt->description ?? '-', \implode(', ', $promptDef->tags), ]; if ($this->detailed) { $args = $this->formatArguments($promptDef->prompt); $row[] = $args; } $table->addRow($row); if ($this->detailed) { $table->addRow(new TableSeparator()); } } $table->render(); $this->output->writeln(''); $this->output->writeln(\sprintf('%s: %s', Style::property('Total prompts'), Style::count(\count($prompts)))); return Command::SUCCESS; } /** * Formats arguments for display. */ private function formatArguments(Prompt $prompt): string { if (empty($prompt->arguments)) { return '-'; } $args = []; foreach ($prompt->arguments as $arg) { $name = $arg->name; if ($arg->required) { $name .= '*'; } if ($arg->description) { $name .= \sprintf(' (%s)', $arg->description); } $args[] = $name; } return \implode("\n", $args); } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/context-hub/generator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server