From 3d9c98f5bd6cceff0a00d90f4a8e915d5f157574 Mon Sep 17 00:00:00 2001 From: Georg Doll Date: Wed, 9 Jul 2025 00:11:58 +0200 Subject: [PATCH] Add get_node_relations function for efficient graph traversal - Implements new get_node_relations tool that returns incoming/outgoing relations for a specific node - Enables efficient graph traversal without loading entire knowledge graph - Returns connected entity names for further exploration - Solves limitation where search_nodes and open_nodes only show relations between filtered results - Updated README with comprehensive API documentation --- src/memory/README.md | 10 ++++++++++ src/memory/index.ts | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/memory/README.md b/src/memory/README.md index 5b18d8413c..5df80ca28a 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -125,6 +125,16 @@ Example: - Relations between requested entities - Silently skips non-existent nodes +- **get_node_relations** + - Get all relations for a specific node, including incoming and outgoing connections + - Input: `nodeName` (string) + - Returns: + - `outgoing` (array): Relations where this node is the source + - `incoming` (array): Relations where this node is the target + - `connected_entities` (string[]): Names of all connected entities + - Enables efficient graph traversal without loading entire graph + - Returns empty arrays if node has no relations + # Usage with Claude Desktop ### Setup diff --git a/src/memory/index.ts b/src/memory/index.ts index b7993a3a08..8dc5d71f38 100644 --- a/src/memory/index.ts +++ b/src/memory/index.ts @@ -181,6 +181,30 @@ class KnowledgeGraphManager { return filteredGraph; } + + async getNodeRelations(nodeName: string): Promise<{ + outgoing: Relation[], + incoming: Relation[], + connected_entities: string[] + }> { + const graph = await this.loadGraph(); + + // Find all outgoing relations (where this node is the source) + const outgoing = graph.relations.filter(r => r.from === nodeName); + + // Find all incoming relations (where this node is the target) + const incoming = graph.relations.filter(r => r.to === nodeName); + + // Get all connected entity names (removing duplicates) + const connected_entities = [ + ...new Set([ + ...outgoing.map(r => r.to), + ...incoming.map(r => r.from) + ]) + ]; + + return { outgoing, incoming, connected_entities }; + } } const knowledgeGraphManager = new KnowledgeGraphManager(); @@ -369,6 +393,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { required: ["names"], }, }, + { + name: "get_node_relations", + description: "Get all relations for a specific node, including incoming and outgoing connections", + inputSchema: { + type: "object", + properties: { + nodeName: { + type: "string", + description: "The name of the entity to get relations for", + }, + }, + required: ["nodeName"], + }, + }, ], }; }); @@ -402,6 +440,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.searchNodes(args.query as string), null, 2) }] }; case "open_nodes": return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.openNodes(args.names as string[]), null, 2) }] }; + case "get_node_relations": + return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.getNodeRelations(args.nodeName as string), null, 2) }] }; default: throw new Error(`Unknown tool: ${name}`); }