Skip to main content
Glama
wrediam

Better Qdrant MCP Server

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
NameRequiredDescriptionDefault
collectionYesName of the collection to search in
embeddingServiceYesEmbedding service to use
limitNoMaximum number of results to return (optional)
queryYesSearch query

Implementation Reference

  • 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'],
      },
    },
  • 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'],
    },
  • 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;
      }
    }
  • 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[];
    }
Install Server

Other Tools

Related 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/wrediam/better-qdrant-mcp-server'

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