Skip to main content
Glama

localnest_memory_suggest_relations

Identify potential connections between memory entries by analyzing semantic similarity, helping users discover relevant links without creating them automatically.

Instructions

Find semantically similar memory entries that could be linked to a given memory. Uses dense embeddings (all-MiniLM-L6-v2) when available, falls back to token overlap. Returns candidates ranked by similarity without creating any relations — use localnest_memory_add_relation to confirm.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYes
thresholdNo
max_resultsNo
response_formatNojson

Implementation Reference

  • Implementation of the suggestRelations logic that calculates semantic similarity for memory entries.
    export async function suggestRelations(adapter, memoryId, { threshold = 0.55, maxResults = 10 } = {}) {
      const id = String(memoryId || '').trim();
      if (!id) throw new Error('id is required');
    
      const source = await adapter.get('SELECT * FROM memory_entries WHERE id = ?', [id]);
      if (!source) throw new Error(`memory not found: ${id}`);
    
      let sourceEmbedding = null;
      if (source.embedding_json) {
        try { sourceEmbedding = JSON.parse(source.embedding_json); } catch {
          // Invalid embedding payloads fall back to token overlap scoring.
        }
      }
    
      const linked = await adapter.all(
        `SELECT target_id AS other_id FROM memory_relations WHERE source_id = ?
         UNION SELECT source_id AS other_id FROM memory_relations WHERE target_id = ?`,
        [id, id]
      );
      const linkedSet = new Set(linked.map((r) => r.other_id));
      linkedSet.add(id);
    
      const candidates = await adapter.all(
        `SELECT id, title, summary, embedding_json
           FROM memory_entries
          WHERE id != ? AND status = 'active'
          ORDER BY importance DESC, updated_at DESC
          LIMIT 200`,
        [id]
      );
    
      const scored = [];
    
      if (sourceEmbedding) {
        for (const row of candidates) {
          if (linkedSet.has(row.id)) continue;
          if (!row.embedding_json) continue;
          try {
            const emb = JSON.parse(row.embedding_json);
            const cosine = cosineSimilarity(sourceEmbedding, emb);
            const score = (cosine + 1) / 2;
            if (score >= threshold) {
              scored.push({ memory_id: row.id, title: row.title, similarity: Number(score.toFixed(3)) });
            }
          } catch {
            // Ignore malformed candidate embeddings.
          }
        }
      } else {
        const sourceTerms = splitTerms(`${source.title} ${source.summary}`);
        for (const row of candidates) {
          if (linkedSet.has(row.id)) continue;
          const rowTerms = splitTerms(`${row.title} ${row.summary}`);
          const score = scoreTokenOverlap(sourceTerms, rowTerms);
          if (score >= threshold) {
            scored.push({ memory_id: row.id, title: row.title, similarity: Number(score.toFixed(3)) });
          }
        }
      }
    
      scored.sort((a, b) => b.similarity - a.similarity);
      return {
        id,
        source_title: source.title,
        count: scored.length,
        threshold,
        using_embeddings: sourceEmbedding !== null,
        suggestions: scored.slice(0, maxResults)
      };
    }
  • MCP tool registration for localnest_memory_suggest_relations, which calls the suggestRelations service function.
    registerJsonTool(
      ['localnest_memory_suggest_relations'],
      {
        title: 'Memory Suggest Relations',
        description: 'Find semantically similar memory entries that could be linked to a given memory. Uses dense embeddings (all-MiniLM-L6-v2) when available, falls back to token overlap. Returns candidates ranked by similarity without creating any relations — use localnest_memory_add_relation to confirm.',
        inputSchema: {
          id: z.string().min(1),
          threshold: z.number().min(0).max(1).default(0.55),
          max_results: z.number().int().min(1).max(50).default(10)
        },
        annotations: {
          readOnlyHint: true,
          destructiveHint: false,
          idempotentHint: true,
          openWorldHint: false
        }
      },
      async ({ id, threshold, max_results }) => normalizeMemorySuggestionResult(
        await memory.suggestRelations(id, { threshold, maxResults: max_results }),
        id,
        threshold
      )
    );

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/wmt-mobile/localnest'

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