Skip to main content
Glama

list_sources

Retrieve all indexed documentation sources with URLs, titles, and update times to understand 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 core handler implementation for the 'list_sources' MCP tool. Extends BaseHandler and overrides handle() to query the Qdrant 'documentation' collection, paginate through all points, extract title/url payloads, group by domain/subdomain, format into numbered list, and return as McpToolResponse.
    export class ListSourcesHandler extends BaseHandler { 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; } 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'); } 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, }; } }
  • The setupHandlers() method registers all handlers including 'list_sources' mapped to new ListSourcesHandler(server, apiClient). This Map is used in callToolRequest to dispatch execution.
    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));
  • ToolDefinition for 'list_sources' provided in listTools response, including name, description, and empty inputSchema (no parameters required).
    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,
  • Alternative/internal tool definition with identical schema (empty input) and name in ListSourcesTool.get definition()
    get definition(): ToolDefinition { return { name: 'list_sources', description: 'List all documentation sources currently stored', inputSchema: { type: 'object', properties: {}, required: [], }, }; }
  • Re-export of list-sources handler module for barrel import in handler-registry.ts
    export * from './list-sources.js';

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