# How the HTTP UI Server Renders the 3D Graph Visualization in codebase-memory-mcp

> Discover how the codebase-memory-mcp HTTP UI server renders 3D graph visualizations using React Three Fiber and fetches data via JSON-RPC from a SQLite store.

- Repository: [Martin Vogel/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp)
- Tags: internals
- Published: 2026-07-18

---

**The HTTP UI server serves a React frontend that renders an interactive 3D graph using React-Three-Fiber, while the C-based backend handles static assets and JSON-RPC requests to fetch graph data from a SQLite store.**

The codebase-memory-mcp project provides a high-performance interface for exploring code dependencies in three-dimensional space. While the **HTTP UI server** built in C manages asset delivery and API endpoints, the actual **3D graph visualization** is rendered entirely client-side using a React-Three-Fiber scene built on top of three.js.

## Architecture Overview

The rendering pipeline operates across three distinct layers that separate data serving from visual presentation:

- **HTTP Server Layer** ([`src/ui/http_server.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/http_server.c)): A lightweight C server that binds to localhost, serves embedded static assets (HTML, JavaScript, CSS), and exposes a JSON-RPC endpoint at `/rpc`.
- **Data Layer**: RPC handlers such as `handle_repo_info` and `handle_graph` query the SQLite-backed MCP store and return structured `GraphData` JSON containing nodes, edges, and project metadata.
- **Frontend 3D Scene** ([`graph-ui/src/components/GraphScene.tsx`](https://github.com/DeusData/codebase-memory-mcp/blob/main/graph-ui/src/components/GraphScene.tsx)): A React application that consumes the JSON payload and constructs an interactive WebGL visualization using React-Three-Fiber, complete with illuminated edges, glowing nodes, and fly-to camera animations.

## HTTP Server Layer: Asset Delivery and JSON-RPC

The server runs in a background pthread via `cbm_http_server_run`, binding exclusively to `127.0.0.1` for security. It serves content from compiled-in embedded assets defined in [`ui/embedded_assets.h`](https://github.com/DeusData/codebase-memory-mcp/blob/main/ui/embedded_assets.h), mapping routes such as `/` to [`index.html`](https://github.com/DeusData/codebase-memory-mcp/blob/main/index.html) and `/assets/` to bundled JavaScript and CSS files.

The `/rpc` endpoint handles all data requests. When the frontend calls `POST /rpc`, the server parses the JSON-RPC request using **yyjson**, dispatches the method to an internal `cbm_mcp_server_t` instance, and returns the result:

```c
/* src/ui/http_server.c – simplified JSON-RPC handling */
static void handle_rpc(cbm_http_conn_t *c, const cbm_http_req_t *req) {
    /* Parse JSON-RPC body, dispatch to MCP server */
    cbm_http_replyf(c, 200, g_cors_json, "%s", json_result);
}

```

The server enforces a strict Content Security Policy (`CBM_UI_CSP`) and limited CORS handling to prevent external network access.

## Data Layer: Graph JSON API

When the UI requests graph data, RPC methods query the SQLite store (`store/cbm_store_*`) and construct a `GraphData` payload containing arrays of nodes and edges. The `handle_graph` function assembles this response and serializes it to JSON:

```c
/* src/ui/http_server.c – assembling GraphData response */
static void handle_graph(cbm_http_conn_t *c, const cbm_http_req_t *req) {
    /* Query SQLite store for nodes and edges */
    cbm_http_replyf(c, 200, g_cors_json, 
        "{\"nodes\":%s,\"edges\":%s}", nodes_json, edges_json);
}

```

The frontend receives this payload through a standard `fetch` call and stores it in React state via the `useGraphData` hook.

## Frontend 3D Rendering with React-Three-Fiber

The visualization layer is implemented in TypeScript and React, using **React-Three-Fiber** (R3F) to create a declarative three.js scene.

### Canvas Setup

[`GraphScene.tsx`](https://github.com/DeusData/codebase-memory-mcp/blob/main/GraphScene.tsx) initializes the WebGL context through R3F's `<Canvas>` component, configuring camera parameters and performance settings:

```tsx
/* graph-ui/src/components/GraphScene.tsx */
<Canvas
  camera={{ position: [0, 0, 800], fov: 50, near: 0.1, far: 100000 }}
  dpr={GRAPH_CANVAS_DPR}
  gl={{ antialias: false, alpha: false, powerPreference: "high-performance" }}
  onPointerMissed={onBackgroundClick}
>

```

### Geometry Generation

**EdgeLines.tsx** constructs a `THREE.BufferGeometry` where each edge contributes two vertices with per-vertex colors. Density-aware intensity scaling via `edgeIntensityScale` ensures visual balance as graph size increases:

```tsx
/* graph-ui/src/components/EdgeLines.tsx */
const geometry = useMemo(() => {
  const densityScale = edgeIntensityScale(edges.length) * brightness;
  const srcMap = new Map<number, number>();
  nodes.forEach((n, i) => srcMap.set(n.id, i));

  const positions = new Float32Array(edges.length * 6);
  const colors    = new Float32Array(edges.length * 6);
  let validCount = 0;

  edges.forEach(edge => {
    const si = srcMap.get(edge.source);
    const ti = srcMap.get(edge.target);
    if (si === undefined || ti === undefined) return;

    const s = nodes[si];
    const t = (targetNodes ?? nodes)[ti];
    
    const off = validCount * 6;
    positions.set([s.x, s.y, s.z, t.x, t.y, t.z], off);
    
    const col = new THREE.Color(EDGE_TYPE_COLORS[edge.type] ?? DEFAULT_EDGE_COLOR);
    colors.set([col.r * intensity, col.g * intensity, col.b * intensity,
                col.r * intensity, col.g * intensity, col.b * intensity], off);
    validCount++;
  });

  const geo = new THREE.BufferGeometry();
  geo.setAttribute("position", new THREE.BufferAttribute(positions.slice(0, validCount * 6), 3));
  geo.setAttribute("color", new THREE.BufferAttribute(colors.slice(0, validCount * 6), 3));
  return geo;
}, [nodes, edges, highlightedIds, targetNodes, brightness]);

```

**NodeCloud.tsx** renders nodes as a `THREE.Points` cloud, applying a boost factor calculated by `nodeBoostScale` to maintain visibility across different graph densities.

### Camera and Interaction

User navigation combines **OrbitControls** from `@react-three/drei` for manual rotation and zoom, with a custom **CameraAnimator** component that implements smooth "fly-to" transitions when focusing on specific nodes:

```tsx
/* Smooth fly-to animation within CameraAnimator */
useFrame(() => {
  if (!targetRef.current || progress.current >= 1) return;
  progress.current = Math.min(1, progress.current + 0.02);
  const t = 1 - Math.pow(1 - progress.current, 3);
  camera.position.lerp(targetRef.current.position, t * 0.08);
  controls?.target.lerp(targetRef.current.lookAt, t * 0.08);
});

```

### Post-Processing Effects

An **EffectComposer** wraps the scene to apply bloom effects via `@react-three/postprocessing`, creating a soft glow around highlight nodes:

```tsx
<EffectComposer multisampling={GRAPH_COMPOSER_MULTISAMPLING}>
  <Bloom
    luminanceThreshold={0.3}
    luminanceSmoothing={0.7}
    intensity={bloomIntensity}
    mipmapBlur
    radius={0.6}
  />
</EffectComposer>

```

The bloom intensity adapts to graph size through `bloomIntensityScale`, preventing oversaturation in large codebases.

## Practical Implementation Examples

### Starting the HTTP Server (C)

```c
cbm_http_server_t *srv = cbm_http_server_new(0);   // port 0 lets OS assign free port
cbm_http_server_set_watcher(srv, watcher);
cbm_thread_t tid;
cbm_thread_create(&tid, 0, (void *(*)(void *))cbm_http_server_run, srv);

```

### Fetching Graph Data (React/TypeScript)

```tsx
// graph-ui/src/hooks/useGraphData.ts
const loadGraph = async (project: string) => {
  const resp = await fetch('/rpc', {
    method: 'POST',
    body: JSON.stringify({ 
      jsonrpc: "2.0", 
      method: "graph.get", 
      params: { project }, 
      id: 1 
    })
  });
  const { result } = await resp.json();
  setGraphData(result);
};

```

### Rendering the Scene (TSX)

```tsx
<GraphScene
  data={graphData}
  highlightedIds={selectedIds}
  cameraTarget={cameraTarget}
  showLabels={showLabels}
  display={displaySettings}
  onNodeClick={handleNodeClick}
/>

```

## Summary

- The C-based **HTTP UI server** ([`src/ui/http_server.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/http_server.c)) serves static assets from embedded memory and handles JSON-RPC requests via the `/rpc` endpoint using **yyjson**.
- Graph data is fetched from a **SQLite-backed store** and returned as structured JSON containing nodes and edges for the frontend to consume.
- The React frontend ([`graph-ui/src/main.tsx`](https://github.com/DeusData/codebase-memory-mcp/blob/main/graph-ui/src/main.tsx)) mounts a **React-Three-Fiber** `<Canvas>` that renders an interactive WebGL scene.
- **EdgeLines** and **NodeCloud** components generate geometry with density-aware scaling functions (`edgeIntensityScale`, `nodeBoostScale`) to maintain visual clarity across different graph sizes.
- Camera navigation combines **OrbitControls** with a custom **CameraAnimator** for smooth, interpolated fly-to transitions.
- **Post-processing bloom effects** add visual depth and highlight important nodes using adaptive intensity scaling (`bloomIntensityScale`).

## Frequently Asked Questions

### What technology stack renders the 3D graph visualization?

The browser-side rendering uses **React-Three-Fiber** (R3F), a React renderer for **three.js**, with post-processing effects provided by `@react-three/postprocessing`. The backend is implemented in C and serves data via JSON-RPC.

### How does the HTTP UI server communicate graph data to the frontend?

The server exposes a `/rpc` endpoint that accepts JSON-RPC requests. Methods like `graph.get` query the SQLite store and return a `GraphData` structure containing nodes and edges, which the frontend fetches using the standard `fetch` API.

### Is the HTTP server accessible from external networks?

No. According to the source code in [`src/ui/http_server.c`](https://github.com/DeusData/codebase-memory-mcp/blob/main/src/ui/http_server.c), the server binds exclusively to `127.0.0.1` (localhost) and enforces a strict Content Security Policy (`CBM_UI_CSP`). CORS headers are limited to localhost origins only.

### How does the visualization handle large codebases with thousands of nodes?

The implementation uses density-aware scaling functions defined in [`graph-ui/src/lib/density.ts`](https://github.com/DeusData/codebase-memory-mcp/blob/main/graph-ui/src/lib/density.ts). These include `edgeIntensityScale`, `nodeBoostScale`, and `bloomIntensityScale`, which automatically reduce visual intensity and adjust geometry density as the graph grows, preventing visual clutter and maintaining performance.