Skip to main content
Glama
NabiaTech

CodeGraph MCP Server

by NabiaTech
README.md
# nabi-codegraph-mcp — Minimal Code Graph + MCP Server (TS + Python)

This is a **self-contained starter** that builds a lightweight code graph over **TypeScript** and **Python**, then exposes it via an **MCP server** so agentic clients (Claude Desktop, Cursor, Copilot Studio, OpenAI Agents, Azure) can query it.

**Design goals**: tiny, pragmatic, easy to extend. No heavyweight LSIF/SCIP indexers required to get started (though you can integrate them later).

---

## What you get

- **Ingestion (no build required):**
  - **TypeScript** parsed using the official `typescript` compiler API.
  - **Python** parsed using the standard library `ast` module.
  - We extract symbols (functions, classes, methods, variables, per-file modules) and edges (`import`, `call`, `member_of`, `defines`).

- **Graph format:**
  - Simple JSON file at `./data/graph.json` with `symbols[]` and `edges[]`.
  - Easy to swap for SQLite or SCIP later.

- **MCP Server (`code-graph`):**
  - `graph.resolve_symbol({ q })` → fuzzy lookup of symbols by name.
  - `graph.references({ id })` → inbound edges (who calls/imports this symbol).
  - `graph.related({ id, k })` → k neighbors (imports/calls).
  - `graph.impact_from_diff({ patch })` → changed files + 1‑hop neighbor impact set.
  - **Resource**: `code://file/{path}?s=..&e=..` → stream code snippets for context windows.

- **Example repo** to test ingestion (`./example` with TS + Py files).

---

## Prereqs

- **Node.js 20+** (recommended LTS).
- **Python 3.10+** (standard library only).

> Tip: This repo avoids native DB bindings for maximum portability. The graph is stored in JSON and loaded into memory by the server.

---

## Quick start (5 minutes)

```bash
# 1) Install deps
npm install

# 2) Build a graph from the example code
npm run ingest -- --target ./example

# 3) Run the MCP server (stdio)
npm run dev:server
```

You should see `code-graph` start and announce tools.

---

## Use with Claude Desktop (macOS/Linux/Windows)

Add an entry to your **Claude Desktop config** to register the MCP server via stdio.

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
- Linux: `~/.config/Claude/claude_desktop_config.json`

Use the included template and replace the absolute path to this folder:

```jsonc
{
  "mcpServers": {
    "code-graph": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/dist/mcp/server.js"],
      "environment": {
        "NABI_GRAPH_JSON": "/ABSOLUTE/PATH/TO/data/graph.json"
      }
    }
  }
}
```

Restart Claude Desktop. In a new chat, ask it to **connect to the `code-graph` MCP server** and try tools like:

- `graph.resolve_symbol` with `{ "q": "greet" }`
- `graph.related` with a returned symbol `id`
- `graph.impact_from_diff` with a pasted patch

> **Note**: Clients differ in how they surface MCP tools. In Claude, you can view connected tools/resources in the session sidebar.

---

## Commands & scripts

```bash
# Dev server (TypeScript via tsx)
npm run dev:server

# Compile to dist/ (pure JS ESM)
npm run build
npm start  # runs the built server

# Ingest (scan target directory and build ./data/graph.json)
npm run ingest -- --target ./example
npm run ingest -- --target /path/to/your/repo

# Optional: re-run impact analysis from a diff file
cat my.patch | npm run impact
```

---

## How ingestion works (tl;dr)

- **TypeScript**: We use the TS compiler API to walk each file’s AST, collect symbols (functions/classes/methods/variables), calls, and imports. We also create a per-file **module symbol** as an anchor.
- **Python**: A small `py/ingest_py.py` uses `ast` to do the same. It prints **NDJSON** on stdout which the Node orchestrator reads and merges.
- **Edge resolution**: Calls are matched to definitions by name with a simple heuristic (prefer same-file symbols first, otherwise the first match). This is intentionally simple—enough to bootstrap your graph and make MCP queries useful.

> Later, you can plug in **Tree‑sitter** or **SCIP** for deeper, cross-repo precision.

---

## Data model

```ts
type Range = { startLine: number; startCol: number; endLine: number; endCol: number };
type Symbol = {
  id: string; kind: 'function'|'class'|'method'|'variable'|'module';
  name: string; file: string; range: Range; language: 'typescript'|'python';
  signature?: string; parentId?: string|null;
};
type EdgeType = 'defines'|'call'|'import'|'member_of';
type Edge = { src: string; type: EdgeType; dst: string };
type Graph = { symbols: Symbol[]; edges: Edge[] };
```

---

## Roadmap: where to take it

- Add **SCIP ingestion** (scip-ts / scip-python) and merge edges alongside this AST path.
- Swap JSON storage for **SQLite** and add indexes for large monorepos.
- Add **structural rewrites/codemods** hooks and `graph.impact_from_diff` refinements (graph radius weighting, churn priors).
- Expose a **search resource**: `graph://symbol?q=...` that streams snippets directly.

---

## Troubleshooting

- If the server prints “No graph loaded,” run `npm run ingest` and confirm `./data/graph.json` exists.
- Windows path issues? Use absolute paths in the Claude config and wrap with quotes.
- Python not found? Edit `PYTHON_BIN` in `src/ingest/make_graph.ts` to your interpreter path.

---

**License**: MIT