Graph Data Model in Codebase-Memory-MCP: Node Labels and Edge Types Explained

Codebase-Memory-MCP represents source code as a property graph where typed nodes represent code entities (functions, classes, variables) and typed edges represent relationships (calls, inherits, references), defined in TypeScript interfaces for visualization and analysis.

Codebase-Memory-MCP transforms your source code repository into a navigable graph structure that powers its web-based visualization interface. Understanding this graph data model is essential for developers who want to extend the tool, build custom queries, or integrate the MCP server with other systems. The model is formally defined in graph-ui/src/lib/types.ts and implemented by the Python backend indexing engine.

Core Components of the Graph Data Model

The graph data model consists of three primary TypeScript interfaces that define how code entities and their relationships are structured, aggregated, and transported.

GraphNode Structure and Node Labels

The GraphNode interface, defined at lines 3-16 in graph-ui/src/lib/types.ts, represents a concrete code entity with both semantic and visual properties.

Each node includes:

  • Positional data: x, y, and z coordinates for 3D graph layout
  • Entity metadata: name, qualified_name, file_path, start_line, and end_line
  • Visual attributes: color, size, and status (using the NodeStatus type)
  • Analytics: in_calls count tracking incoming references

The label field (line 8) encodes the entity type as a string, enabling the UI to color-code nodes and display human-readable badges. Valid node labels include:

  • function
  • class
  • module
  • enum
  • variable
  • type_alias
  • import

GraphEdge Structure and Relationship Types

The GraphEdge interface, defined at lines 39-44 in graph-ui/src/lib/types.ts, connects two nodes via directed relationships.

Each edge contains:

  • source: The ID of the originating node
  • target: The ID of the destination node
  • type: A string specifying the relationship kind (line 42)

Valid edge types include:

  • calls – Function invocations
  • references – Variable or symbol usage
  • inherits – Class inheritance relationships
  • contains – Parent-child containment (e.g., methods within a class)
  • exports – Module export relationships
  • imports – Import dependencies

The UI uses the type field to render different line styles and colors for each relationship category.

SchemaInfo and GraphData Containers

Two additional interfaces manage graph metadata and transport:

SchemaInfo (lines 76-80) provides aggregated statistics about the graph composition:

  • node_labels: Array of objects tallying count per label type
  • edge_types: Array of objects tallying count per relationship type
  • total_nodes and total_edges: Aggregate counts

GraphData (lines 62-68) serves as the top-level payload sent to the frontend:

  • nodes: Array of GraphNode objects
  • edges: Array of GraphEdge objects
  • total_nodes: Count for pagination and progress tracking
  • Optional linked_projects and missed_graph sections for multi-project views

Backend Implementation and Data Flow

The Python backend implements this graph data model through a multi-stage pipeline:

  1. AST Extraction: The backend walks the abstract syntax tree of each indexed file, creating a GraphNode for every discovered entity.

  2. Relationship Mapping: For each detected relationship (e.g., a function calling another function), the backend emits a GraphEdge with the appropriate type string.

  3. Schema Aggregation: During indexing, the system builds a SchemaInfo object that tallies node labels and edge types for statistical reporting.

  4. Serialization: All nodes, edges, and schema information serialize as JSON conforming to the GraphData interface.

  5. Transport: The data travels via the RPC endpoint /api/graph to the frontend.

  6. Rendering: The useGraphData hook (located in graph-ui/src/hooks/useGraphData.ts) consumes the payload, rendering nodes at their coordinates and styling connections according to their type.

The CLI entry point in pkg/pypi/src/codebase_memory_mcp/_cli.py drives this indexing process, while pkg/pypi/src/codebase_memory_mcp/graph_builder.py contains the core logic for AST traversal and graph construction.

Practical Code Examples

The following TypeScript examples demonstrate how to construct valid graph data structures conforming to the model:

// Building a minimal graph with two functions and a call relationship
import {
  GraphNode,
  GraphEdge,
  GraphData,
  NodeStatus,
} from "./lib/types";

const fnA: GraphNode = {
  id: 1,
  x: 0,
  y: 0,
  z: 0,
  label: "function",
  name: "foo",
  file_path: "src/foo.py",
  qualified_name: "module.foo",
  start_line: 10,
  end_line: 14,
  size: 5,
  color: "#ffcc00",
  status: "normal",
  in_calls: 0,
};

const fnB: GraphNode = {
  id: 2,
  x: 200,
  y: 0,
  z: 0,
  label: "function",
  name: "bar",
  file_path: "src/bar.py",
  qualified_name: "module.bar",
  start_line: 20,
  end_line: 25,
  size: 6,
  color: "#66ccff",
  status: "normal",
  in_calls: 1,
};

const callEdge: GraphEdge = {
  source: fnA.id,   // foo calls bar
  target: fnB.id,
  type: "calls",
};

const graph: GraphData = {
  nodes: [fnA, fnB],
  edges: [callEdge],
  total_nodes: 2,
};
// Consuming schema statistics returned by the backend
interface SchemaInfo {
  node_labels: { label: string; count: number }[];
  edge_types: { type: string; count: number }[];
  total_nodes: number;
  total_edges: number;
}

const schema: SchemaInfo = {
  node_labels: [
    { label: "function", count: 342 },
    { label: "class",    count: 87 },
    { label: "module",   count: 12 },
  ],
  edge_types: [
    { type: "calls",      count: 590 },
    { type: "inherits",   count: 73 },
    { type: "references", count: 210 },
  ],
  total_nodes: 441,
  total_edges: 873,
};

Summary

  • GraphNode entities carry positional coordinates, metadata, and a label field identifying the code entity type (function, class, variable, etc.).
  • GraphEdge connections specify relationship semantics through the type field (calls, inherits, references, etc.).
  • SchemaInfo aggregates node and edge statistics for UI dashboards and filtering controls.
  • The GraphData interface serves as the canonical transport format between the Python backend and TypeScript frontend.
  • All type definitions reside in graph-ui/src/lib/types.ts, with line-specific references to GraphNode (3-16), GraphEdge (39-44), GraphData (62-68), and SchemaInfo (76-80).

Frequently Asked Questions

What are the valid node labels in Codebase-Memory-MCP?

According to the GraphNode interface in graph-ui/src/lib/types.ts, the label field accepts strings identifying code entity types. Common values include function, class, module, enum, variable, type_alias, and import. The UI uses these labels to apply color-coding and display badges for each node.

How does the backend determine edge types?

The Python backend analyzes AST relationships during indexing. When it detects a function call, it creates a GraphEdge with type: "calls"; for inheritance relationships, it uses type: "inherits"; for variable usage, type: "references". These type strings are defined at line 42 of the types file and consumed by the frontend to style connection lines.

What is the purpose of SchemaInfo?

SchemaInfo provides a statistical summary of the entire graph, defined at lines 76-80 in graph-ui/src/lib/types.ts. It counts occurrences of each node label and edge type, enabling the web UI to display distribution charts, filtering options, and project health metrics without loading the full node list.

How is graph data transported between backend and frontend?

The backend serializes nodes and edges into JSON conforming to the GraphData interface (lines 62-68). This payload includes the complete nodes and edges arrays plus a SchemaInfo object. The data travels via the /api/graph RPC endpoint and is consumed by the useGraphData React hook in the frontend for rendering.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →