semantic_search
Search your knowledge graph memory using semantic vector embeddings to find entities similar to your query, with options for hybrid search, similarity thresholds, and entity type filtering.
Instructions
Search for entities semantically using vector embeddings and similarity in your Memento MCP knowledge graph memory
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| entity_types | No | Filter results by entity types | |
| hybrid_search | No | Whether to combine keyword and semantic search (default: true) | |
| limit | No | Maximum number of results to return (default: 10) | |
| min_similarity | No | Minimum similarity threshold from 0.0 to 1.0 (default: 0.6) | |
| query | Yes | The text query to search for semantically | |
| semantic_weight | No | Weight of semantic results in hybrid search from 0.0 to 1.0 (default: 0.6) |
Implementation Reference
- Defines the input schema, description, and parameters for the semantic_search MCP tool.{ name: 'semantic_search', description: 'Search for entities semantically using vector embeddings and similarity in your Memento MCP knowledge graph memory', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'The text query to search for semantically', }, limit: { type: 'number', description: 'Maximum number of results to return (default: 10)', }, min_similarity: { type: 'number', description: 'Minimum similarity threshold from 0.0 to 1.0 (default: 0.6)', }, entity_types: { type: 'array', items: { type: 'string' }, description: 'Filter results by entity types', }, hybrid_search: { type: 'boolean', description: 'Whether to combine keyword and semantic search (default: true)', }, semantic_weight: { type: 'number', description: 'Weight of semantic results in hybrid search from 0.0 to 1.0 (default: 0.6)', }, }, required: ['query'], }, },
- The switch case handler that executes the semantic_search tool, parsing arguments and delegating to KnowledgeGraphManager.search() with semantic options.case 'semantic_search': try { // Extract search options from args const searchOptions = { limit: args.limit || 10, minSimilarity: args.min_similarity || 0.6, entityTypes: args.entity_types || [], hybridSearch: args.hybrid_search !== undefined ? args.hybrid_search : true, semanticWeight: args.semantic_weight || 0.6, semanticSearch: true, }; // Call the search method with semantic search options const results = await knowledgeGraphManager.search(String(args.query), searchOptions); return { content: [{ type: 'text', text: JSON.stringify(results, null, 2) }] }; } catch (error: Error | unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text', text: `Error performing semantic search: ${errorMessage}` }], }; }
- src/server/handlers/listToolsHandler.ts:530-531 (registration)Registers the semantic_search tool by including it in the baseTools array returned by the ListTools MCP handler.return { tools: [...baseTools, ...temporalTools, ...(process.env.DEBUG === 'true' ? debugTools : [])],
- src/KnowledgeGraphManager.ts:903-979 (helper)Core search method in KnowledgeGraphManager that implements semantic and hybrid search logic when semanticSearch option is enabled.async search( query: string, options: { semanticSearch?: boolean; hybridSearch?: boolean; limit?: number; threshold?: number; minSimilarity?: number; entityTypes?: string[]; facets?: string[]; offset?: number; } = {} ): Promise<KnowledgeGraph> { // If hybridSearch is true, always set semanticSearch to true as well if (options.hybridSearch) { options = { ...options, semanticSearch: true }; } // Check if semantic search is requested if (options.semanticSearch || options.hybridSearch) { // Check if we have a storage provider with semanticSearch method if (this.storageProvider && hasSemanticSearch(this.storageProvider)) { try { // Generate query vector if we have an embedding service if (this.embeddingJobManager) { const embeddingService = this.embeddingJobManager['embeddingService']; if (embeddingService) { const queryVector = await embeddingService.generateEmbedding(query); return this.storageProvider.semanticSearch(query, { ...options, queryVector, }); } } // Fall back to text search if no embedding service return this.storageProvider.searchNodes(query); } catch (error) { logger.error('Provider semanticSearch failed, falling back to basic search', error); return this.storageProvider.searchNodes(query); } } else if (this.storageProvider) { // Fall back to searchNodes if semanticSearch is not available in the provider return this.storageProvider.searchNodes(query); } // If no storage provider or its semanticSearch is not available, try internal semantic search if (this.embeddingJobManager) { try { // Try to use semantic search const results = await this.semanticSearch(query, { hybridSearch: options.hybridSearch || false, limit: options.limit || 10, threshold: options.threshold || options.minSimilarity || 0.5, entityTypes: options.entityTypes || [], facets: options.facets || [], offset: options.offset || 0, }); return results; } catch (error) { // Log error but fall back to basic search logger.error('Semantic search failed, falling back to basic search', error); // Explicitly call searchNodes if available in the provider if (this.storageProvider) { return (this.storageProvider as StorageProvider).searchNodes(query); } } } else { logger.warn('Semantic search requested but no embedding capability available'); } } // Use basic search return this.searchNodes(query); }
- Private helper method implementing fallback semantic search using findSimilarEntities and vector similarity.private async semanticSearch( query: string, options: { hybridSearch?: boolean; limit?: number; threshold?: number; entityTypes?: string[]; facets?: string[]; offset?: number; } = {} ): Promise<KnowledgeGraph> { // Find similar entities using vector similarity const similarEntities = await this.findSimilarEntities(query, { limit: options.limit || 10, threshold: options.threshold || 0.5, }); if (!similarEntities.length) { return { entities: [], relations: [] }; } // Get full entity details const entityNames = similarEntities.map((e) => e.name); const graph = await this.openNodes(entityNames); // Add scores to entities for client use const scoredEntities = graph.entities.map((entity) => { const matchScore = similarEntities.find((e) => e.name === entity.name)?.score || 0; return { ...entity, score: matchScore, }; }); // Sort by score descending scoredEntities.sort((a, b) => { const scoreA = 'score' in a ? (a as Entity & { score: number }).score : 0; const scoreB = 'score' in b ? (b as Entity & { score: number }).score : 0; return scoreB - scoreA; }); return { entities: scoredEntities, relations: graph.relations, total: similarEntities.length, }; }