Skip to main content
Glama
0xjcf
by 0xjcf

build-knowledge-graph

Analyze code repositories to create dependency graphs and visualize relationships for better understanding of project structure and external dependencies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repositoryUrlYes
depthNo
includeExternalDependenciesNo

Implementation Reference

  • Registration of the MCP tool 'build-knowledge-graph', including Zod input schema validation and thin handler wrapper that calls the core buildKnowledgeGraph function 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
          };
        }
      }
    );
  • Input schema for the tool using Zod: repository URL (required), analysis depth (default 2), include external deps (default true).
    {
      repositoryUrl: z.string(),
      depth: z.number().default(2),
      includeExternalDependencies: z.boolean().default(true)
    },
  • Core handler logic for building the knowledge graph: initializes SQLite DB, clones repository, lists files, analyzes each file's code to extract imports/classes/functions, creates corresponding graph nodes and relationships (contains, imports, defines), commits transaction.
    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;
      }
    }
  • Helper function to add or update a node in the knowledge graph database.
    async function addNode(node: GraphNode): Promise<void> {
      if (!db) {
        db = await createDatabase("knowledge");
      }
      
      if (!db) {
        throw new Error("Database not initialized");
      }
      
      await db.run(
        `INSERT OR REPLACE INTO nodes (id, type, name, attributes)
        VALUES (?, ?, ?, ?)`,
        [node.id, node.type, node.name, JSON.stringify(node.attributes)]
      );
    }
  • Helper function to add or update a relationship in the knowledge graph database.
    async function addRelationship(relationship: GraphRelationship): Promise<void> {
      if (!db) {
        db = await createDatabase("knowledge");
      }
      
      if (!db) {
        throw new Error("Database not initialized");
      }
      
      await db.run(
        `INSERT OR REPLACE INTO relationships (id, type, sourceId, targetId, attributes)
        VALUES (?, ?, ?, ?, ?)`,
        [
          relationship.id,
          relationship.type,
          relationship.sourceId,
          relationship.targetId,
          JSON.stringify(relationship.attributes)
        ]
      );
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/0xjcf/MCP_CodeAnalysis'

If you have feedback or need assistance with the MCP directory API, please join our Discord server