Structural code graph server for AI agents.
Parse any repository into a queryable graph via tree-sitter AST — and expose it as an MCP tool interface your AI agent can call directly. Supports Neo4j, JanusGraph, or GraphQLite (embedded SQLite — zero setup for local dev).
Codesteward parses your codebase into a persistent structural graph and exposes four Model Context Protocol tools that AI agents (Claude Code, Cursor, Windsurf, Copilot, …) can call to answer questions like:
- "Which functions are protected by JWT auth?"
- "What does
process_paymentcall, transitively?" - "Which files depend on this external package?"
- "Is this route guarded by an auth middleware?"
Rather than scanning files repeatedly, the agent queries a pre-built graph — cross-file relationships, call chains, auth guards, and dependency edges all resolved in a single query.
Supported languages: TypeScript · JavaScript · Python · Java · Go · Rust · PHP · C# · Kotlin · Scala · C · C++ · SQL (context tagging) · COBOL (regex)
| Tool | Description |
|---|---|
graph_rebuild |
Parse a repository and write the structural graph to the configured backend (Neo4j, JanusGraph, or GraphQLite) or run in stub mode |
codebase_graph_query |
Query via named templates (lexical, referential, semantic, dependency) or raw passthrough (cypher / gremlin) |
graph_augment |
Add agent-inferred relationships (confidence < 1.0) back into the graph |
graph_status |
Return metadata: node/edge counts, last build time, Neo4j connectivity |
taint_analysis |
(optional) Run taint-flow analysis via the codesteward-taint binary and write TAINT_FLOW edges to Neo4j |
One-time setup. Works across every repository on your machine without any per-project config.
uvx --from "codesteward-mcp[graph-all,graphqlite]" codesteward-mcp setupThis auto-detects your AI tools (Claude Code, Cursor, Cline, Codex CLI, Gemini CLI), registers the MCP server globally, and merges workflow instructions into your existing config files — nothing is overwritten.
Uses GraphQLite by default: an embedded SQLite graph that persists to ~/.codesteward/graph.db. No Docker, no database server, no background processes.
To remove everything: uvx --from "codesteward-mcp[graph-all,graphqlite]" codesteward-mcp setup --uninstall
Prerequisites: uv · (optional) codesteward-taint on PATH
cd /path/to/your/project
claude # or: cursor, cline, codex, gemini# The agent will automatically:
graph_status(repo_id="my-project")
graph_rebuild(repo_path="/path/to/your/project", repo_id="my-project") # if stale
codebase_graph_query(query_type="referential", query="authenticate", repo_id="my-project")
No .mcp.json, no per-project config, no repeated setup.
For manual per-tool setup, Docker deployments, and alternative backends (Neo4j, JanusGraph), see the setup guides.
If you prefer to configure manually, add this to your MCP client config:
{
"mcpServers": {
"codesteward-graph": {
"type": "stdio",
"command": "uvx",
"args": [
"--from", "codesteward-mcp[graph-all,graphqlite]",
"codesteward-mcp", "--transport", "stdio"
]
}
}
}Note: Claude Code requires
"type": "stdio"in the server config. Other tools (Cursor, Cline) don't need it.
| Tool | Config file |
|---|---|
| Claude Code | ~/.claude.json (under mcpServers) |
| Cursor | ~/.cursor/mcp.json |
| Cline | cline_mcp_settings.json in VS Code globalStorage |
| Codex CLI | ~/.codex/config.yaml (under mcp_servers) |
| Gemini CLI | ~/.gemini/settings.json (under mcpServers) |
Requires uv. uvx downloads and caches the package on first run. The graph persists to ~/.codesteward/graph.db across sessions.
# 1. Point the server at your repository
export REPO_PATH=/path/to/your/repository
# 2. Start Neo4j + MCP server
docker compose -f docker-compose.neo4j.yml up -d
# 3. Copy config templates into the repo you want to analyse
cp templates/.mcp.json /path/to/your/repository/
cp templates/CLAUDE.md /path/to/your/repository/The server runs at http://localhost:3000/sse. Call graph_rebuild() with no arguments — the server already knows the repo path from the volume mount.
# 1. Point the server at your repository
export REPO_PATH=/path/to/your/repository
# 2. Start JanusGraph + MCP server
docker compose -f docker-compose.janusgraph.yml up -d
# 3. Copy config templates into the repo you want to analyse
cp templates/.mcp.json /path/to/your/repository/
cp templates/CLAUDE.md /path/to/your/repository/Same workflow as the Neo4j stack — all named query templates work identically. Raw query passthrough uses Gremlin instead of Cypher.
docker run -p 3000:3000 \
-v /path/to/your/repo:/repos/project:ro \
-e NEO4J_PASSWORD=secret \
ghcr.io/bitkaio/codesteward-mcp:latestFor full setup instructions covering all AI tools, see the setup guides.
# All 14 languages + GraphQLite (recommended for local dev)
uv pip install "codesteward-mcp[graph-all,graphqlite]"
# Core languages only (TypeScript, JavaScript, Python, Java) + GraphQLite
uv pip install "codesteward-mcp[graph,graphqlite]"
# Individual language extras
uv pip install "codesteward-mcp[graph-go,graphqlite]" # Go
uv pip install "codesteward-mcp[graph-rust,graphqlite]" # Rust
uv pip install "codesteward-mcp[graph-csharp,graphqlite]" # C#
uv pip install "codesteward-mcp[graph-kotlin,graphqlite]" # Kotlin
uv pip install "codesteward-mcp[graph-scala,graphqlite]" # Scala
uv pip install "codesteward-mcp[graph-c,graphqlite]" # C
uv pip install "codesteward-mcp[graph-cpp,graphqlite]" # C++
uv pip install "codesteward-mcp[graph-php,graphqlite]" # PHP
# Neo4j backend (alternative — requires a running Neo4j 5+ server)
uv pip install "codesteward-mcp[graph-all]"
# JanusGraph backend (alternative — requires a running JanusGraph 1.0+ server)
uv pip install "codesteward-mcp[graph-all,janusgraph]"Requires Python 3.12+. GraphQLite is the default backend for local development — an embedded SQLite graph database that requires no external services. The graph persists to ~/.codesteward/graph.db across sessions.
All settings can be provided via environment variables, a YAML config file, or CLI flags. Priority: CLI flags > env vars > YAML file > defaults.
| Setting | Env var | Default | Description |
|---|---|---|---|
| Transport | TRANSPORT |
sse |
sse, http, or stdio |
| Host | HOST |
0.0.0.0 |
HTTP bind host |
| Port | PORT |
3000 |
HTTP bind port |
| Graph backend | GRAPH_BACKEND |
auto |
auto, neo4j, janusgraph, or graphqlite. Auto-detects: Neo4j if password set, JanusGraph if URL changed, otherwise GraphQLite |
| Neo4j URI | NEO4J_URI |
bolt://localhost:7687 |
Neo4j connection URI |
| Neo4j user | NEO4J_USER |
neo4j |
Neo4j username |
| Neo4j password | NEO4J_PASSWORD |
(empty) | Set to enable Neo4j backend |
| JanusGraph URL | JANUSGRAPH_URL |
ws://localhost:8182/gremlin |
Gremlin Server WebSocket URL |
| GraphQLite DB path | GRAPHQLITE_DB_PATH |
~/.codesteward/graph.db |
SQLite database file path |
| Default tenant | DEFAULT_TENANT_ID |
local |
Tenant namespace |
| Default repo | DEFAULT_REPO_ID |
(empty) | Repo ID |
| Default repo path | DEFAULT_REPO_PATH |
/repos/project |
Server-side path for graph_rebuild |
| Workspace | WORKSPACE_BASE |
workspace |
Directory for build metadata |
| Log level | LOG_LEVEL |
INFO |
DEBUG / INFO / WARNING / ERROR |
The taint_analysis tool is registered automatically when the codesteward-taint binary is on
PATH. Without it the server starts normally and the other four tools are unaffected.
Pass --build-arg TAINT_VERSION=<version> to download and bundle the binary:
docker build --build-arg TAINT_VERSION=0.1.0 -t codesteward-mcp:taint .Download a pre-built binary from the
codesteward-taint releases and place it
on PATH:
# macOS (Apple Silicon)
curl -L https://github.com/bitkaio/codesteward-taint/releases/latest/download/codesteward-taint-darwin-arm64 \
-o /usr/local/bin/codesteward-taint
chmod +x /usr/local/bin/codesteward-taintgraph_rebuild # build the structural graph first
taint_analysis # trace taint paths; writes TAINT_FLOW edges to Neo4j
codebase_graph_query # query_type="semantic" to read findings
Every parsed symbol becomes a LexicalNode:
| Property | Description |
|---|---|
node_id |
Stable unique ID: {node_type}:{tenant_id}:{repo_id}:{file}:{name} |
node_type |
function, class, method, file, module, external |
name |
Symbol name |
file |
Repo-relative file path |
line_start / line_end |
Source location |
language |
Detected language |
tenant_id / repo_id |
Multi-tenancy namespace |
confidence |
1.0 for parser-emitted; < 1.0 for agent-inferred |
| Edge type | Meaning |
|---|---|
CALLS |
Function A calls function B (cross-file resolved) |
IMPORTS |
File/module imports another |
EXTENDS |
Class inherits from another |
GUARDED_BY |
Function protected by a decorator/annotation (@login_required, @UseGuards, FastAPI Depends, @PreAuthorize, …) |
PROTECTED_BY |
Function protected by router-scope middleware (APIRouter, Express router.use(), Gin group, Actix scope, Laravel route group, ASP.NET MapGroup().RequireAuthorization()) |
DEPENDS_ON |
File depends on an external package |
TAINT_FLOW |
Untrusted input reaches a dangerous sink (written by codesteward-taint; queryable via semantic) |
calls / guarded_by / taint_flow / … |
Agent-inferred edges with confidence < 1.0 via graph_augment |
# Setup
uv venv && source .venv/bin/activate
uv sync --all-packages --extra graph-all
# Run tests
pytest tests/ -v
# Run the server locally
codesteward-mcp --transport sse --port 3000
# Lint + type-check
ruff check src/ tests/
mypy src/See CHANGELOG.md for the full history or browse GitHub Releases.
Apache License 2.0 — Copyright (c) 2026, bitkaio LLC
