search
Find similar documents in a specified collection using semantic search. Input a query, choose an embedding service, and retrieve relevant results for efficient information discovery.
Instructions
Search for similar documents in a collection
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| collection | Yes | Name of the collection to search in | |
| embeddingService | Yes | Embedding service to use | |
| limit | No | Maximum number of results to return (optional) | |
| query | Yes | Search query |
Implementation Reference
- src/index.ts:320-379 (handler)The primary handler for the 'search' tool. Embeds the query using the specified embedding service, performs vector search in Qdrant via qdrantService.search, formats and returns the top results.private async handleSearch(args: SearchArgs) { try { // Create embedding service const embeddingService = createEmbeddingService({ type: args.embeddingService, apiKey: process.env[`${args.embeddingService.toUpperCase()}_API_KEY`], endpoint: process.env[`${args.embeddingService.toUpperCase()}_ENDPOINT`], }); // Generate query embedding const [queryEmbedding] = await embeddingService.generateEmbeddings([args.query]); // Search collection const results = await this.qdrantService.search( args.collection, queryEmbedding, args.limit ); // Format the results to only include the payload text let responseText = ''; results.forEach((result, index) => { // For documents collection, the text is in result.payload.text // For other collections, it might be in different fields const text = result.payload.text || result.payload.content || JSON.stringify(result.payload); const source = result.payload.source || result.payload.metadata?.source || ''; const score = result.score.toFixed(2); responseText += `Result ${index + 1} (Score: ${score}):\n${text}\n`; if (source) { responseText += `Source: ${source}\n`; } responseText += '\n'; }); if (responseText === '') { responseText = 'No results found.'; } return { content: [ { type: 'text', text: responseText, }, ], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: 'text', text: `Error searching: ${errorMessage}`, }, ], isError: true, }; }
- src/index.ts:148-174 (registration)Registration of the 'search' tool in the ListTools response, including name, description, and input schema.{ name: 'search', description: 'Search for similar documents in a collection', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query', }, collection: { type: 'string', description: 'Name of the collection to search in', }, embeddingService: { type: 'string', enum: ['openai', 'openrouter', 'fastembed', 'ollama'], description: 'Embedding service to use', }, limit: { type: 'number', description: 'Maximum number of results to return (optional)', }, }, required: ['query', 'collection', 'embeddingService'], }, },
- src/index.ts:151-173 (schema)JSON input schema defining the parameters for the 'search' tool: query (string), collection (string), embeddingService (enum), limit (number optional).inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query', }, collection: { type: 'string', description: 'Name of the collection to search in', }, embeddingService: { type: 'string', enum: ['openai', 'openrouter', 'fastembed', 'ollama'], description: 'Embedding service to use', }, limit: { type: 'number', description: 'Maximum number of results to return (optional)', }, }, required: ['query', 'collection', 'embeddingService'], },
- src/services/qdrant.ts:174-239 (helper)QdrantService.search method: Performs POST to /points/search endpoint with vector query, retrieves results with payload and vector, maps to SearchResult objects.async search( collection: string, vector: number[], limit: number = 10 ): Promise<SearchResult[]> { try { console.log('Attempting to search Qdrant collection using direct fetch...'); // Use direct fetch instead of the client const searchUrl = `${this.url}/collections/${collection}/points/search`; console.log(`Fetching from: ${searchUrl}`); const response = await fetch(searchUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', ...(this.apiKey ? { 'api-key': this.apiKey } : {}) }, // @ts-ignore - node-fetch supports timeout timeout: 5000, // 5 second timeout body: JSON.stringify({ vector, limit, with_payload: true, with_vector: true }) }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const data = await response.json() as { result: Array<{ id: string; score: number; payload: Record<string, any>; vector?: number[]; }> }; console.log('Successfully retrieved search results:', data); return data.result.map(result => { const searchResult: SearchResult = { id: result.id, score: result.score, payload: result.payload, }; // Only include vector if it's a number array if (Array.isArray(result.vector) && result.vector.every(v => typeof v === 'number')) { searchResult.vector = result.vector; } return searchResult; }); } catch (error) { console.error('Error in search:', error); if (error instanceof Error) { console.error(`${error.name}: ${error.message}`); console.error('Stack:', error.stack); } throw error; } }
- src/types.ts:28-33 (schema)TypeScript interface defining the structure of search results returned by Qdrant search.export interface SearchResult { id: string; score: number; payload: Record<string, any>; vector?: number[]; }