Graph Query
graph_queryQuery the memory graph using an entity's canonical name to retrieve matching nodes, edges, weights, and source provenance. Use when you have the exact or near-canonical entity name.
Instructions
Query the memory graph by canonical entity name. Use when you know the entity name or close-to-canonical form (e.g. "Steve", "graph-memory"); for natural-language phrasing or synonyms (e.g. "the knowledge graph project") prefer graph_search. Returns up to limit matching nodes plus the edges that connect them within max_hops, with per-edge weight and source provenance.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| entities | Yes | Entity names to search for | |
| entity_types | No | Filter results to these entity types | |
| max_hops | No | Max traversal depth (default: 2) | |
| min_weight | No | Min edge weight to traverse (default: 0.3) | |
| limit | No | Max results (default: 20) | |
| project_context | No | Project directory or name for affinity scoring | |
| context_level | No | Response detail level (default: full) | full |
| current_only | No | Only current facts, exclude superseded (default: true) |
Implementation Reference
- src/mcp-server/index.ts:160-210 (registration)Tool registration for graph_query via server.registerTool, with inputSchema defined using zod schemas, annotations, and the async handler function that calls client.query()
// ─── Tool: graph_query ─── server.registerTool("graph_query", { title: "Graph Query", description: "Query the memory graph by canonical entity name. Use when you know the entity name or close-to-canonical form (e.g. \"Steve\", \"graph-memory\"); for natural-language phrasing or synonyms (e.g. \"the knowledge graph project\") prefer graph_search. Returns up to `limit` matching nodes plus the edges that connect them within `max_hops`, with per-edge weight and source provenance.", inputSchema: { entities: z.array(z.string()).describe("Entity names to search for"), entity_types: z.array(z.string()).optional().describe("Filter results to these entity types"), max_hops: z.number().optional().default(2).describe("Max traversal depth (default: 2)"), min_weight: z.number().optional().default(0.3).describe("Min edge weight to traverse (default: 0.3)"), limit: z.number().optional().default(20).describe("Max results (default: 20)"), project_context: z.string().optional().describe("Project directory or name for affinity scoring"), context_level: z.enum(["minimal", "full", "relations-only"]).optional().default("full").describe("Response detail level (default: full)"), current_only: z.boolean().optional().default(true).describe("Only current facts, exclude superseded (default: true)"), }, annotations: { readOnlyHint: true }, }, async (args) => { try { const result = await client.query(currentTenant(), args.entities, { entity_types: args.entity_types as EntityType[] | undefined, max_hops: args.max_hops, min_weight: args.min_weight, limit: args.limit, project_context: args.project_context, current_only: args.current_only, }); if (args.context_level === "minimal") { return toolResult({ nodes: result.nodes.map((n) => ({ id: n.id, type: n.type, name: n.name, confidence: n.confidence, })), edge_count: result.edges.length, }); } if (args.context_level === "relations-only") { return toolResult({ nodes: result.nodes.map((n) => ({ id: n.id, type: n.type, name: n.name, })), edges: result.edges, }); } return toolResult(result); } catch (err) { return toolError(`graph_query failed: ${err instanceof Error ? err.message : String(err)}`); } }); - src/mcp-server/index.ts:177-210 (handler)The async handler function for graph_query that receives args, calls client.query() with tenant-scoped parameters, and processes context_level (minimal/full/relations-only) formatting of the result
}, async (args) => { try { const result = await client.query(currentTenant(), args.entities, { entity_types: args.entity_types as EntityType[] | undefined, max_hops: args.max_hops, min_weight: args.min_weight, limit: args.limit, project_context: args.project_context, current_only: args.current_only, }); if (args.context_level === "minimal") { return toolResult({ nodes: result.nodes.map((n) => ({ id: n.id, type: n.type, name: n.name, confidence: n.confidence, })), edge_count: result.edges.length, }); } if (args.context_level === "relations-only") { return toolResult({ nodes: result.nodes.map((n) => ({ id: n.id, type: n.type, name: n.name, })), edges: result.edges, }); } return toolResult(result); } catch (err) { return toolError(`graph_query failed: ${err instanceof Error ? err.message : String(err)}`); } }); - src/mcp-server/index.ts:166-175 (schema)Input schema definition for graph_query: entities (required array), entity_types, max_hops, min_weight, limit, project_context, context_level, current_only with defaults and descriptions
inputSchema: { entities: z.array(z.string()).describe("Entity names to search for"), entity_types: z.array(z.string()).optional().describe("Filter results to these entity types"), max_hops: z.number().optional().default(2).describe("Max traversal depth (default: 2)"), min_weight: z.number().optional().default(0.3).describe("Min edge weight to traverse (default: 0.3)"), limit: z.number().optional().default(20).describe("Max results (default: 20)"), project_context: z.string().optional().describe("Project directory or name for affinity scoring"), context_level: z.enum(["minimal", "full", "relations-only"]).optional().default("full").describe("Response detail level (default: full)"), current_only: z.boolean().optional().default(true).describe("Only current facts, exclude superseded (default: true)"), },