open_nodes
Expand specified entities to retrieve full details, including observations and relations, using a local, offline MCP memory server for persistent storage and retrieval.
Instructions
Expand specified entities: return their full details including observations and relations.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| names | Yes | Names of entities to expand. |
Implementation Reference
- src/server.js:203-219 (registration)Registers the MCP tool 'open_nodes' with Zod input schema and inline handler function that invokes KnowledgeGraphManager.openNodes and returns formatted JSON response.this.tool( 'open_nodes', 'Expand specified entities: return their full details including observations and relations.', { names: z.array(z.string()).describe('Names of entities to expand.') }, async ({ names }) => ({ content: [{ type: 'text', text: JSON.stringify( await this.#knowledgeGraphManager.openNodes(names), null, 2 ) }] }) );
- src/postgres/graph-repo.js:349-407 (handler)Postgres-specific handler implementation for openNodes: fetches entities by name, their observations, and mutual relations via SQL queries, assembles response object.async openNodes(names) { if (!names.length) { return { entities: [], relations: [] }; } /** * @type {[{entitytype, id, name}]} */ const entities = await this.#query( `SELECT * FROM entities WHERE name = ANY ($1)`, [ names ] ); if (!entities.length) { return { entities: [], relations: [] }; } const ids = entities.map(e => e.id); const observations = await this.#query( `SELECT entity_id, content FROM observations WHERE entity_id = ANY ($1)`, [ ids ] ); /** * @type {[{name, from_name, to_name, relationtype}]} */ const relations = await this.#query( `SELECT r.from_id, r.to_id, r.relationtype, ef.name AS from_name, et.name AS to_name FROM relations r JOIN entities ef ON ef.id = r.from_id JOIN entities et ON et.id = r.to_id WHERE r.from_id = ANY ($1) AND r.to_id = ANY ($1)`, [ ids ] ); return { entities: entities.map(e => ({ name: e.name, entityType: e.entitytype, observations: observations .filter(o => o.entity_id === e.id) .map(o => o.content) })), relations: relations.map(rel => ({ from: rel.from_name, to: rel.to_name, relationType: rel.relationtype })) };
- src/sqlite/graph-repo.js:305-352 (handler)SQLite-specific handler implementation for openNodes: fetches entities by name, their observations, and mutual relations via SQL queries, assembles response object.async openNodes(names) { if (!names.length) { return { entities: [], relations: [] }; } const placeholders = names.map(() => '?').join(','); const entities = await this.db.all( `SELECT * FROM entities WHERE name IN (${placeholders})`, names ); if (!entities.length) { return { entities: [], relations: [] }; } const ids = entities.map(e => e.id); const idPlaceholders = ids.map(() => '?').join(','); const observations = await this.db.all( `SELECT entity_id, content FROM observations WHERE entity_id IN (${idPlaceholders})`, ids ); /** * * @type {[{from_name, to_name, relationType}]} */ const relations = await this.db.all( `SELECT r.from_id, r.to_id, r.relationType, ef.name AS from_name, et.name AS to_name FROM relations r JOIN entities ef ON ef.id = r.from_id JOIN entities et ON et.id = r.to_id WHERE r.from_id IN (${idPlaceholders}) AND r.to_id IN (${idPlaceholders})`, [...ids, ...ids] ); return { entities: entities.map(entity => ({ name: entity.name, entityType: entity.entityType, observations: observations .filter(obs => obs.entity_id === entity.id) .map(obs => obs.content) })), relations: relations.map(relation => ({ from: relation.from_name, to: relation.to_name, relationType: relation.relationType })) };
- src/server.js:206-208 (schema)Zod schema definition for open_nodes tool input: array of entity names.{ names: z.array(z.string()).describe('Names of entities to expand.') },
- KnowledgeGraphManager helper method that delegates openNodes call to the underlying repository implementation.async openNodes(names) { return this.#repository.openNodes(names); }