build-knowledge-graph
Create a knowledge graph from a repository to visualize code structure and dependencies, enabling deeper code analysis and AI-assisted development insights.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | ||
| includeExternalDependencies | No | ||
| repositoryUrl | Yes |
Implementation Reference
- Main handler function `buildKnowledgeGraph` that implements the core logic: clones repository, analyzes files using `analyzeCode`, creates nodes for repo/files/deps/classes/functions, adds relationships, stores in SQLite DB.export async function buildKnowledgeGraph( repositoryUrl: string, depth: number = 2, includeExternalDependencies: boolean = true ): Promise<{ nodes: number, relationships: number }> { // Initialize db if needed if (!db) { db = await createDatabase("knowledge"); } if (!db) { throw new Error("Database not initialized"); } // Get repository const repoPath = await getRepository(repositoryUrl); const files = listFiles(repoPath); let nodesCount = 0; let relationshipsCount = 0; await db.exec('BEGIN TRANSACTION'); try { // Add repository node const repoId = `repo:${uuidv4()}`; addNode({ id: repoId, type: "repository", name: path.basename(repositoryUrl), attributes: { url: repositoryUrl, fileCount: files.length } }); nodesCount++; // Process each file for (const file of files) { const fullPath = path.join(repoPath, file); try { const code = fs.readFileSync(fullPath, 'utf8'); const fileLanguage = path.extname(file).slice(1); // Create file node const fileId = `file:${uuidv4()}`; addNode({ id: fileId, type: "file", name: file, attributes: { language: fileLanguage, size: code.length, path: file } }); nodesCount++; // Link file to repository addRelationship({ id: `rel:${uuidv4()}`, type: "contains", sourceId: repoId, targetId: fileId, attributes: {} }); relationshipsCount++; // Analyze code to get dependencies, classes, functions const analysis = analyzeCode(code, fileLanguage); // Process imports/dependencies for (const importItem of analysis.imports) { let targetId: string; // Check if the import already exists as a node const existingNode = await findNodeByName(importItem); if (existingNode) { targetId = existingNode.id; } else { // Create a new node for the import targetId = `dep:${uuidv4()}`; addNode({ id: targetId, type: "dependency", name: importItem, attributes: { isExternal: !files.some(f => f.endsWith(importItem) || f.includes(importItem)) } }); nodesCount++; } // Link file to dependency addRelationship({ id: `rel:${uuidv4()}`, type: "imports", sourceId: fileId, targetId: targetId, attributes: {} }); relationshipsCount++; } // Process classes for (const className of analysis.classes) { const classId = `class:${uuidv4()}`; addNode({ id: classId, type: "class", name: className, attributes: { file: file } }); nodesCount++; // Link class to file addRelationship({ id: `rel:${uuidv4()}`, type: "defines", sourceId: fileId, targetId: classId, attributes: {} }); relationshipsCount++; } // Process functions for (const funcName of analysis.functions) { const funcId = `func:${uuidv4()}`; addNode({ id: funcId, type: "function", name: funcName, attributes: { file: file } }); nodesCount++; // Link function to file addRelationship({ id: `rel:${uuidv4()}`, type: "defines", sourceId: fileId, targetId: funcId, attributes: {} }); relationshipsCount++; } } catch (error) { console.warn(`Error processing file ${file}: ${(error as Error).message}`); } } await db.exec('COMMIT'); return { nodes: nodesCount, relationships: relationshipsCount }; } catch (error) { await db.exec('ROLLBACK'); throw error; } }
- src/features/knowledge-graph/index.ts:15-46 (registration)Registers the MCP tool 'build-knowledge-graph' via `server.tool()`, providing input schema and a thin async handler that calls `buildKnowledgeGraph` and formats response.server.tool( "build-knowledge-graph", { repositoryUrl: z.string(), depth: z.number().default(2), includeExternalDependencies: z.boolean().default(true) }, async ({ repositoryUrl, depth, includeExternalDependencies }) => { try { const result = await buildKnowledgeGraph( repositoryUrl, depth, includeExternalDependencies ); return { content: [{ type: "text", text: `Knowledge graph built successfully. Nodes: ${result.nodes}, Relationships: ${result.relationships}` }] }; } catch (error) { return { content: [{ type: "text", text: `Error building knowledge graph: ${(error as Error).message}` }], isError: true }; } } );
- Zod input schema for the tool: repositoryUrl (string), depth (number, default 2), includeExternalDependencies (boolean, default true).{ repositoryUrl: z.string(), depth: z.number().default(2), includeExternalDependencies: z.boolean().default(true)