query-knowledge-graph
Analyze code repositories to extract and visualize relationships between components, dependencies, and structures using knowledge graphs for better understanding and navigation.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| repositoryUrl | No | ||
| contextDepth | No | ||
| includeExternalKnowledge | No | ||
| outputFormat | No | json |
Implementation Reference
- src/features/knowledge-graph/index.ts:49-105 (registration)Exact MCP tool registration for 'query-knowledge-graph' including inline Zod input schema, handler function that calls the queryKnowledgeGraph helper, handles different output formats (text, json, visualization), and error handling.server.tool( "query-knowledge-graph", { query: z.string(), repositoryUrl: z.string().optional(), contextDepth: z.number().default(2), includeExternalKnowledge: z.boolean().default(true), outputFormat: z.enum(["text", "json", "visualization"]).default("json") }, async ({ query, repositoryUrl, contextDepth, includeExternalKnowledge, outputFormat }) => { try { const results = await queryKnowledgeGraph({ query, repositoryUrl, contextDepth, includeExternalKnowledge }); if (outputFormat === "visualization") { // Convert results to a visualization const visualization = await exportKnowledgeGraph(results, "mermaid"); return { content: [{ type: "text", text: visualization, _metadata: { format: "mermaid" } }] }; } if (outputFormat === "text") { // Format results as descriptive text return { content: [{ type: "text", text: formatGraphResultsAsText(results) }] }; } return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: `Error querying knowledge graph: ${(error as Error).message}` }], isError: true }; } } );
- Core handler logic for querying the knowledge graph: initializes from repository nodes, traverses relationships up to contextDepth levels, collects nodes and relationships.export async function queryKnowledgeGraph(query: GraphQuery): Promise<GraphQueryResult> { // Simple implementation for demonstration // A real implementation would use a graph query language const { repositoryUrl, contextDepth = 1 } = query; // Start with a basic implementation that returns nodes related to a repository let nodes: GraphNode[] = []; let relationships: GraphRelationship[] = []; if (repositoryUrl) { // Get all nodes and relationships for the repository const repoNodes = await findNodesByAttribute("url", repositoryUrl); if (repoNodes.length === 0) { return { nodes: [], relationships: [] }; } const repoId = repoNodes[0].id; // Get direct relationships const directRelationships = await findRelationshipsBySourceId(repoId); relationships.push(...directRelationships); // Get target nodes of direct relationships const directNodeIds = directRelationships.map(rel => rel.targetId); const directNodes = await findNodesById(directNodeIds); nodes.push(...repoNodes, ...directNodes); // If depth > 1, get additional levels of relationships if (contextDepth > 1) { for (let i = 1; i < contextDepth; i++) { const currentNodeIds = nodes.map(node => node.id); const relationshipsResult = await findRelationshipsBySourceIds(currentNodeIds); const nextRelationships = relationshipsResult.filter((rel: GraphRelationship) => !relationships.some(r => r.id === rel.id)); if (nextRelationships.length === 0) { break; } relationships.push(...nextRelationships); const nextNodeIds = nextRelationships.map((rel: GraphRelationship) => rel.targetId) .filter((id: string) => !nodes.some(node => node.id === id)); if (nextNodeIds.length === 0) { break; } const nextNodes = await findNodesById(nextNodeIds); nodes.push(...nextNodes); } } } return { nodes, relationships }; }
- src/types/knowledge-graph.ts:1-38 (schema)TypeScript type definitions for knowledge graph structures (GraphNode, GraphRelationship, GraphQueryResult, GraphQuery) used by the query-knowledge-graph tool implementation./** * Represents a node in the knowledge graph */ export interface GraphNode { id: string; type: "function" | "file" | "class" | "variable" | "dependency" | "concept" | "repository"; name: string; attributes: Record<string, any>; } /** * Represents a relationship between nodes in the knowledge graph */ export interface GraphRelationship { id: string; type: "imports" | "calls" | "defines" | "extends" | "implements" | "uses" | "contains" | "relates_to"; sourceId: string; targetId: string; attributes: Record<string, any>; } /** * Structure for query results from the knowledge graph */ export interface GraphQueryResult { nodes: GraphNode[]; relationships: GraphRelationship[]; } /** * Parameters for querying the knowledge graph */ export interface GraphQuery { query: string; repositoryUrl?: string; contextDepth?: number; includeExternalKnowledge?: boolean; }
- Helper function to format knowledge graph query results as human-readable text, used when outputFormat='text' in the tool handler.function formatGraphResultsAsText(results: any): string { const { nodes, relationships } = results; let text = `Query returned ${nodes.length} nodes and ${relationships.length} relationships.\n\n`; // Add node information text += "Nodes:\n"; nodes.forEach((node: any, index: number) => { text += `${index + 1}. [${node.type}] ${node.name}\n`; if (Object.keys(node.attributes).length > 0) { text += ` Attributes: ${JSON.stringify(node.attributes)}\n`; } }); // Add relationship information text += "\nRelationships:\n"; relationships.forEach((rel: any, index: number) => { const source = nodes.find((n: any) => n.id === rel.sourceId); const target = nodes.find((n: any) => n.id === rel.targetId); text += `${index + 1}. ${source?.name || rel.sourceId} [${rel.type}] ${target?.name || rel.targetId}\n`; }); return text; }