Skip to main content
Glama
jumasheff

RAG Documentation MCP Server

by jumasheff

list_sources

Retrieve all indexed documentation sources with URLs, titles, and update times to verify available content for searching.

Instructions

List all documentation sources currently stored in the system. Returns a comprehensive list of all indexed documentation including source URLs, titles, and last update times. Use this to understand what documentation is available for searching or to verify if specific sources have been indexed.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The handle() method implementing the core logic of the list_sources tool: paginates Qdrant scroll on 'documentation' collection, filters payloads for title/url, groups sources by domain/subdomain using helper methods, formats into structured text list, handles auth/connection errors specifically.
    async handle(): Promise<McpToolResponse> {
      try {
        await this.apiClient.initCollection(COLLECTION_NAME);
        
        const pageSize = 100;
        let offset = null;
        const sources: Source[] = [];
        
        while (true) {
          const scroll = await this.apiClient.qdrantClient.scroll(COLLECTION_NAME, {
            with_payload: true,
            with_vector: false,
            limit: pageSize,
            offset,
          });
    
          if (scroll.points.length === 0) break;
          
          for (const point of scroll.points) {
            if (point.payload && typeof point.payload === 'object' && 'url' in point.payload && 'title' in point.payload) {
              const payload = point.payload as any;
              sources.push({
                title: payload.title,
                url: payload.url
              });
            }
          }
    
          if (scroll.points.length < pageSize) break;
          offset = scroll.points[scroll.points.length - 1].id;
        }
    
        if (sources.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: 'No documentation sources found.',
              },
            ],
          };
        }
    
        const grouped = this.groupSourcesByDomainAndSubdomain(sources);
        const formattedOutput = this.formatGroupedSources(grouped);
    
        return {
          content: [
            {
              type: 'text',
              text: formattedOutput,
            },
          ],
        };
      } catch (error) {
        if (error instanceof Error) {
          if (error.message.includes('unauthorized')) {
            throw new McpError(
              ErrorCode.InvalidRequest,
              'Failed to authenticate with Qdrant cloud while listing sources'
            );
          } else if (error.message.includes('ECONNREFUSED') || error.message.includes('ETIMEDOUT')) {
            throw new McpError(
              ErrorCode.InternalError,
              'Connection to Qdrant cloud failed while listing sources'
            );
          }
        }
        return {
          content: [
            {
              type: 'text',
              text: `Failed to list sources: ${error}`,
            },
          ],
          isError: true,
        };
      }
    }
  • Hardcoded ToolDefinition schema for the list_sources tool in the ListToolsRequestHandler response, including name, description, and empty input schema.
      name: 'list_sources',
      description: 'List all documentation sources currently stored in the system. Returns a comprehensive list of all indexed documentation including source URLs, titles, and last update times. Use this to understand what documentation is available for searching or to verify if specific sources have been indexed.',
      inputSchema: {
        type: 'object',
        properties: {},
      },
    } as ToolDefinition,
  • setupHandlers() method registers all tool handlers in a Map, including 'list_sources' -> new ListSourcesHandler(server, apiClient).
    private setupHandlers() {
      this.handlers.set('add_documentation', new AddDocumentationHandler(this.server, this.apiClient));
      this.handlers.set('search_documentation', new SearchDocumentationHandler(this.server, this.apiClient));
      this.handlers.set('list_sources', new ListSourcesHandler(this.server, this.apiClient));
      this.handlers.set('remove_documentation', new RemoveDocumentationHandler(this.server, this.apiClient));
      this.handlers.set('extract_urls', new ExtractUrlsHandler(this.server, this.apiClient));
      this.handlers.set('list_queue', new ListQueueHandler(this.server, this.apiClient));
      this.handlers.set('run_queue', new RunQueueHandler(this.server, this.apiClient));
      this.handlers.set('clear_queue', new ClearQueueHandler(this.server, this.apiClient));
    }
  • Helper method to group sources by domain and first path segment (subdomain).
    private groupSourcesByDomainAndSubdomain(sources: Source[]): GroupedSources {
      const grouped: GroupedSources = {};
    
      for (const source of sources) {
        try {
          const url = new URL(source.url);
          const domain = url.hostname;
          const pathParts = url.pathname.split('/').filter(p => p);
          const subdomain = pathParts[0] || '/';
    
          if (!grouped[domain]) {
            grouped[domain] = {};
          }
          if (!grouped[domain][subdomain]) {
            grouped[domain][subdomain] = [];
          }
          grouped[domain][subdomain].push(source);
        } catch (error) {
          console.error(`Invalid URL: ${source.url}`);
        }
      }
    
      return grouped;
    }
  • Helper method to format grouped sources into a numbered list: domains numbered, sources under each as domain.N. title (url), deduplicated by url, sorted by title.
    private formatGroupedSources(grouped: GroupedSources): string {
      const output: string[] = [];
      let domainCounter = 1;
    
      for (const [domain, subdomains] of Object.entries(grouped)) {
        output.push(`${domainCounter}. ${domain}`);
        
        // Create a Set of unique URL+title combinations
        const uniqueSources = new Map<string, Source>();
        for (const sources of Object.values(subdomains)) {
          for (const source of sources) {
            uniqueSources.set(source.url, source);
          }
        }
    
        // Convert to array and sort
        const sortedSources = Array.from(uniqueSources.values())
          .sort((a, b) => a.title.localeCompare(b.title));
    
        // Use letters for subdomain entries
        sortedSources.forEach((source, index) => {
          output.push(`${domainCounter}.${index + 1}. ${source.title} (${source.url})`);
        });
    
        output.push(''); // Add blank line between domains
        domainCounter++;
      }
    
      return output.join('\n');
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes the return format (list with URLs, titles, update times) and implies a read-only operation, but lacks details on potential limitations like pagination, rate limits, or error conditions. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in two sentences: the first states the action and return value, the second provides usage context. Every sentence adds value without redundancy, and it is appropriately sized for a simple listing tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (0 parameters, no annotations, no output schema), the description is reasonably complete—it explains what the tool does, what it returns, and when to use it. However, it could be more comprehensive by addressing potential behavioral aspects like performance or data freshness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has 0 parameters with 100% schema description coverage, so the schema already fully documents the inputs. The description appropriately does not add parameter details, maintaining focus on the tool's purpose and output. Baseline for 0 parameters is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific verb ('List') and resource ('all documentation sources currently stored in the system'), distinguishing it from siblings like 'search_documentation' (searching) and 'remove_documentation' (deleting). It explicitly mentions what information is returned (source URLs, titles, last update times).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context on when to use this tool ('to understand what documentation is available for searching or to verify if specific sources have been indexed'), but does not explicitly state when not to use it or name specific alternatives among siblings (e.g., 'search_documentation' for querying content).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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/jumasheff/mcp-ragdoc-fork'

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