Skip to main content
Glama

CTX: Context as Code (CaC) tool

by context-hub
MIT License
235
  • Apple
  • Linux
DocsSourceFetcher.php5.77 kB
<?php declare(strict_types=1); namespace Butschster\ContextGenerator\Source\Docs; use Butschster\ContextGenerator\Application\Logger\LoggerPrefix; use Butschster\ContextGenerator\Lib\Content\ContentBuilderFactory; use Butschster\ContextGenerator\Lib\HttpClient\HttpClientInterface; use Butschster\ContextGenerator\Lib\Variable\VariableResolver; use Butschster\ContextGenerator\Modifier\ModifiersApplierInterface; use Butschster\ContextGenerator\Source\Fetcher\SourceFetcherInterface; use Butschster\ContextGenerator\Source\SourceInterface; use Psr\Log\LoggerInterface; /** * Fetcher for Context7 documentation sources * @implements SourceFetcherInterface<DocsSource> */ #[LoggerPrefix(prefix: 'docs-source')] final readonly class DocsSourceFetcher implements SourceFetcherInterface { private const string CONTEXT7_BASE_URL = 'https://context7.com'; /** * @param array<string, string> $defaultHeaders Default HTTP headers to use for all requests */ public function __construct( private HttpClientInterface $httpClient, private VariableResolver $variableResolver, private ContentBuilderFactory $builderFactory, private LoggerInterface $logger, private array $defaultHeaders = [ 'User-Agent' => 'CTX Bot', 'Accept' => 'text/plain', 'Accept-Language' => 'en-US,en;q=0.9', ], ) {} public function supports(SourceInterface $source): bool { $isSupported = $source instanceof DocsSource; $this->logger->debug('Checking if source is supported', [ 'sourceType' => $source::class, 'isSupported' => $isSupported, ]); return $isSupported; } public function fetch(SourceInterface $source, ModifiersApplierInterface $modifiersApplier): string { if (!$source instanceof DocsSource) { $errorMessage = 'Source must be an instance of DocsSource'; $this->logger->error($errorMessage, [ 'sourceType' => $source::class, ]); throw new \InvalidArgumentException($errorMessage); } $this->logger->info('Fetching documentation from Context7', [ 'library' => $source->library, 'topic' => $source->topic, 'tokens' => $source->tokens, ]); // Create builder $builder = $this->builderFactory ->create() ->addDescription($this->variableResolver->resolve($source->getDescription())); try { $library = $this->variableResolver->resolve($source->library); $topic = $this->variableResolver->resolve($source->topic); $tokens = $source->tokens; // Build the URL for Context7 API $url = \sprintf( '%s/%s/llms.txt?topic=%s&tokens=%d', self::CONTEXT7_BASE_URL, $library, \rawurlencode($topic), $tokens, ); $this->logger->debug('Sending HTTP request to Context7', [ 'url' => $url, 'headers' => $this->defaultHeaders, ]); // Send the request $requestHeaders = $this->variableResolver->resolve($this->defaultHeaders); $response = $this->httpClient->get($url, $requestHeaders); $statusCode = $response->getStatusCode(); if (!$response->isSuccess()) { $this->logger->warning('Context7 request failed', [ 'url' => $url, 'statusCode' => $statusCode, ]); $builder ->addComment("Library: {$library}") ->addComment("Topic: {$topic}") ->addComment("Error: HTTP status code {$statusCode}") ->addSeparator(); return $builder->build(); } $this->logger->debug('Context7 request successful', [ 'url' => $url, 'statusCode' => $statusCode, ]); // Get the response body $content = $response->getBody(); $contentLength = \strlen($content); $this->logger->debug('Received documentation content', [ 'library' => $library, 'topic' => $topic, 'contentLength' => $contentLength, ]); // Add metadata to the builder $builder ->addComment("Library: {$library}") ->addComment("Topic: {$topic}") ->addComment("Tokens: {$tokens}") ->addSeparator(); // Apply modifiers to the content $processedContent = $modifiersApplier->apply($content, $url); // Add the processed content to the builder $builder->addText($processedContent); } catch (\Throwable $e) { $this->logger->error('Error retrieving documentation from Context7', [ 'library' => $source->library ?? 'unknown', 'topic' => $source->topic ?? 'unknown', 'error' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), ]); $builder ->addComment("Library: {$source->library}") ->addComment("Topic: {$source->topic}") ->addComment("Error: {$e->getMessage()}") ->addSeparator(); } $content = $builder->build(); $this->logger->info('Documentation content fetched successfully', [ 'contentLength' => \strlen($content), ]); // Return built content return $content; } }

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