Skip to main content

Nexus-MCP

PyPI version PyPI downloads Python 3.10–3.12 License: PolyForm Noncommercial 1.0.0 CI Glama MCP server

Hybrid search + code graph + semantic memory in a single local MCP server. About 90 MB idle and 460 MB with the embedding model loaded (measurements).

Nexus-MCP is a code intelligence server for the Model Context Protocol. It gives AI agents precise, token-efficient answers about your codebase without cloud dependencies: no API keys, no data egress, no subscriptions.

pip install nexus-mcp-ci
claude mcp add nexus-mcp -- nexus-mcp-ci

The Problem It Solves

An agent that explores a codebase with Grep and Read pays for every call: each call is one more turn, and each turn reads the whole conversation again. Nexus-MCP answers a question about code in fewer calls. search returns the whole code of its top results, find_symbol returns the code of several names in one call, and graph returns every text reference beside the call edges.

The north star of the project is lower token use with the same accuracy. It is measured, not estimated: see Token efficiency and benchmarks/.


Quickstart (60 seconds)

# 1. Install
pip install nexus-mcp-ci

# 2. Register with Claude Code
claude mcp add nexus-mcp -- nexus-mcp-ci

# 3. Verify: start Claude Code in your project and run /mcp
#    nexus-mcp should be listed as connected

The server sends its own usage instructions when it connects, so Claude knows which tool answers which question without any extra setup. Ask something like "where do we retry failed payments?" and it will call search (and index once, the first time in a project).

The plugin registers the server and adds a short routing skill that teaches Claude when to reach for each tool. Install the Python package first, then:

/plugin marketplace add jaggernaut007/Nexus-MCP
/plugin install nexus-mcp@nexus-mcp

Do not register the server twice. If you use the plugin, skip the claude mcp add line. Tool names differ by route: mcp__nexus-mcp__search after claude mcp add nexus-mcp, mcp__plugin_nexus-mcp_nexus-mcp__search through the plugin. The rest of this README writes bare names (search) and you do not need the prefix in prompts.

Optional: project instructions

If you want the rules in your own project file, a short block is enough:

## Code Navigation

The nexus-mcp server is connected. For questions about how this codebase works:
- No setup call is needed; run `index` only if a tool says the project is not indexed.
- Use `search` to find code, `find_symbol` for symbols, `map` for structure.
- Use `graph` with `transitive=true` before you change a shared function. The call graph
  is static, so also use `search` for dynamic call sites.
- Use plain grep or read when you already know the file or the exact string.

The full routing guide is in docs/AGENT_ROUTING.md.


How It Works

Indexing Pipeline (8 steps)

Source files
    │
    ├─ Step 1: Discover ──────── walk tree, filter by ext/size/.gitignore
    │
    ├─ Step 2: Parse symbols ─── tree-sitter (parallel ThreadPool)
    │           extracts: functions, classes, methods
    │           captures: name, signature, docstring, line_start/end, language
    │
    ├─ Step 3: Parse graph ────── ast-grep (sequential for consistency)
    │           extracts: containment edges, import edges, callee names of each function
    │                     (indexing/call_resolver.py makes CALLS edges after the last batch;
    │                      no inheritance edges yet)
    │           output: UniversalGraph — nodes: modules, functions, classes;
    │                                    edges: CONTAINS, IMPORTS, CALLS
    │
    ├─ Step 4: Transfer graph ── populate rustworkx PyDiGraph
    │           O(1) node lookup by name, Rust-backed traversal
    │
    ├─ Step 5: Chunk ──────────── Symbol → CodeChunk
    │           deterministic IDs: SHA256(file_path + symbol_name + line)
    │           avoids duplicate inserts on incremental reindex
    │
    ├─ Step 6: Embed ──────────── bge-small-en: 384-dim
    │           lazy-loaded, unloaded after indexing (try/finally)
    │           GPU/MPS auto-detected; falls back to CPU
    │
    ├─ Step 7: Store ──────────── write to LanceDB `chunks` table (12-col PyArrow schema)
    │           rebuild native FTS (Tantivy) index after write
    │
    └─ Step 8: Cleanup ────────── unload model, persist metadata (mtimes for incremental)
                                  save rustworkx graph to SQLite (warm-start recovery)

Incremental reindex: mtime-based — only changed files are re-processed. Corrupt index detection triggers automatic full rebuild.

Search Pipeline

search("how does auth work")
         │
         ├─► vector_engine.search(query, n=30)  ← cosine similarity on 384-dim (bge-small-en) embeddings
         │                                         "auth" finds "verify_credentials", "token_check"
         │
         ├─► bm25_engine.search(query, n=30)    ← Tantivy FTS on same LanceDB table
         │                                         fast exact-keyword matching
         │
         ├─► graph_engine.boost(query, n=30)    ← structural relevance score
         │                                         hub symbols (high in/out degree) boosted
         │
         └─► fusion.merge(v_results, b_results)
                  │
                  │  Reciprocal Rank Fusion: score = Σ weight_i / (k + rank_i)
                  │  default weights: vector=0.5, bm25=0.3
                  │
                  └─► token_budget.truncate()   ← summary / detailed / full
                           │
                           └─► Top-N chunks, scored, formatted

Technology Stack

Layer Technology Decision Rationale
Vector store LanceDB mmap disk-backed → ~20–50 MB overhead vs ChromaDB's in-memory model. Native Tantivy FTS means one store for both vector and BM25. (ADR-002)
Embeddings bge-small-en Lightweight (384-dim, no trust_remote_code). Lazy-load/unload keeps RAM flat after indexing. (ADR-003)
Graph engine rustworkx PyDiGraph Rust-backed, O(1) node lookup, PageRank + centrality algorithms. Thread-safe with RLock. (ADR-006)
Symbol parser tree-sitter 0.21.3 25+ languages, incremental parsing, AST-level symbol extraction with metadata. Parallel via ThreadPool. (ADR-005)
Graph parser ast-grep Structural matching for containment and import edges (call edges are resolved after indexing; inheritance edges are not extracted yet). Sequential run for graph consistency. (ADR-005)
Chunking Symbol-based One chunk per function/class. Deterministic SHA256 IDs prevent duplicate inserts. (ADR-008)
Persistence SQLite + LanceDB Graph in SQLite (warm-start recovery), vectors+FTS in LanceDB, mtimes in JSON. Zero-config.
MCP framework FastMCP 2.0 Stdio transport, automatic tool registration, schema generation.

Token Efficiency

Two live runs, 12 questions each, with Claude Sonnet, 3 runs for each question and condition (72 runs each) and the prompt cache warm for both conditions. The result depends on the project.

Latest (commit a67e5b4, find_symbol shows an outline of a long class):

Grep and Read Nexus-MCP
Private 460-file Python project: cost $0.571 $0.446 (-22.0%)
Private project: turns, correct 55, 36 of 36 35, 35 of 36
Django (3,000 files): cost $0.894 $0.863 (-3.4%)
Django: turns, correct 93, 34 of 36 71, 36 of 36

Only the nexus condition ran again for this commit; the Grep and Read numbers are the stored runs below. On django nexus is cheaper in total but still dearer on 8 of 12 questions (the short lookups). The one wrong answer on the private project came from a run that did not call find_symbol. With 3 runs for each question the same code can vary by about 20% in cost (measured 2026-10-28), so the change against the runs before the outline is inside the noise; all three recent nexus runs on the private project cost less than Grep and Read ($0.446 to $0.531 against $0.571), and on django nexus is about equal ($0.863 to $0.973 against $0.894). Details: docs/EVALS.md. The sections below are the runs before the outline.

Private 460-file Python project (2026-10-08, commit 91a338e):

Grep and Read Nexus-MCP
Turns (sum of the median of each question) 55 34 (-38%)
Output tokens 11,917 8,881 (-25%)
Cost $0.571 $0.459 (-20%)
Correct answers 36 of 36 36 of 36
Prompt on the first turn 12,700 tokens 16,300 tokens

Nexus is cheaper on 7 questions, equal on 3 and dearer on 2 (the two impact questions, by $0.005 and $0.004). The saving comes from fewer turns and from smaller tool results than the whole-file reads of Grep and Read (see the cost split below). Per question numbers are in docs/EVALS.md. The same questions on 2026-10-07 (before exact names, code in find_symbol, the smaller tool list and the warm-up call) gave nexus 6% more cost than Grep and Read.

Django, a public repository (3,000 files; 2026-10-27, commit 3fa8810):

Grep and Read Nexus-MCP
Turns (sum of the median of each question) 93 78 (-16%)
Output tokens 32,291 27,513 (-15%)
Cost $0.894 $0.973 (+8.9%)
Correct answers 34 of 36 35 of 36

On django nexus uses fewer turns but costs more. It is cheaper on the questions where Grep and Read need 18 to 24 turns (SQLCompiler.as_sql -21%, URLResolver.resolve -10%) and dearer on short lookups that take 2 or 3 turns. Django is a repository that the model knows from training, so part of this measures the model. One ground truth was corrected after the run (a question asked for a value, and the scorer also required a file name); details in docs/EVALS.md.

Why: the cost split of the traces. The parts below add up to the reported cost of each run.

Change, nexus against Grep and Read django jobscout
Cache read (the prompt, on each turn) +$0.011 -$0.002
Cache write (tool results and the first message) +$0.111 -$0.078
Output -$0.042 -$0.033
Total +$0.079 -$0.112
  • The 3,600 extra prompt tokens on each turn cost little: a cache read is $0.20 per million.
  • Tool results are written to the cache at $4 per million, 20 times the read price. So the size of a result matters more than the size of the prompt.
  • On jobscout the agent does not know the code and reads whole files (10,000 characters for each Read). A find_symbol result of 9,700 characters replaces a Read and saves a turn.
  • On django the agent knows the code and reads short line ranges (3,400 characters for each Read). A find_symbol result of 9,200 characters is larger than the read that it replaces. A class lookup sends up to 6,000 characters of the class body: CharField cost $0.023 with nexus and $0.013 with Grep.

This led to the outline for a class in find_symbol (methods and lines, not the body). With it, nexus on django went from $0.973 to $0.863 (see "Latest" above). Details and the other candidates are in docs/EVALS.md.

The saving is large on a project that the model does not know and small on one that it knows. Run benchmarks/ on your own project before you rely on it.


The 8 Tools

v2.1.0 breaking change: explain and health are removed from the MCP tool list, and several rarely used parameters are removed from the schemas (see CHANGELOG). find_symbol now returns the code with callers and callees.

v2.0.0 breaking change: find_callers/find_callees/impact merged into graph, overview/architecture merged into map, and remember/recall/forget merged into memory — see CHANGELOG for the old→new mapping and ADR-017 for why. Fewer, richer tools route better under MCP Tool Search than many thin ones.

Discovery & Indexing

Tool Use When
index(path) First action in any session. Supports comma-separated multi-folder paths. Incremental by default, reports progress as it runs, and starts a debounced auto-reindex watcher (NEXUS_AUTO_WATCH) when it finishes.
status() Check index health: symbol count, chunk count, memory usage, engine availability, and a stale/staleness_warning pair if files changed since the last index.
map(detail) Replaces ls + manual browsing. detail="summary" (files/languages/quality/top-modules, was overview()), "architecture" (layers/dependencies/classes/entry points/hub symbols, was architecture()), or "full" for both.
Tool Use When
search(query, limit) Primary code discovery. A query can hold exact names (parse_config RetryPolicy): their definitions come first. The top 3 results carry the whole symbol; the others show the signature. Falls back to live grep if results are sparse. Returns a warning if the index looked stale (a background reindex starts).

Graph Analysis

Tool Use When
find_symbol(symbol_name, exact) Look up one or more symbols by name (several names in one call): the code of each, with its callers and callees by name. exact=False for fuzzy matching.
graph(symbol_name, direction, transitive) direction="callers" (who calls this, was find_callers) or "callees" (what this calls, was find_callees). transitive=True (was impact()) gives the transitive change blast radius before a refactor (a lower bound: static edges only). It requires direction="callers"; direction="callees" with transitive=True returns an error. Call edges are static and name-based, so use search for call sites the graph cannot see (see Known Limitations).
analyze(path) Code quality: cyclomatic complexity, cognitive complexity, code smells, dependency metrics.

Memory

Tool Use When
memory(action, content, query, tags, memory_id) action="store" to persist a decision or note across sessions; "search" for semantic retrieval; "delete" to remove by ID or tag. With NEXUS_PERMISSION_LEVEL=read only search is allowed.

Install

pip install nexus-mcp-ci

# GPU (CUDA) support — adds ONNX CUDA execution provider
pip install nexus-mcp-ci[gpu]

From Source

git clone https://github.com/jaggernaut007/Nexus-MCP.git
cd Nexus-MCP
./setup.sh           # creates venv, installs, verifies
# or
pip install -e ".[dev]"

Python 3.10–3.12 supported. Python 3.13+ is not yet supported by the current dependency stack, and the packaged Glama/Docker build uses Python 3.12 for compatibility. Optional: rg (ripgrep) for 100% search coverage fallback on unindexed files.

The deprecated jina-code model requires ONNX Runtime. If you see ONNX/Optimum errors:

pip install "sentence-transformers[onnx]" "optimum[onnxruntime]>=1.19.0"

The default bge-small-en model needs neither ONNX nor trust_remote_code.


MCP Client Setup

Claude Code

# Minimal
claude mcp add nexus-mcp -- nexus-mcp-ci

# GPU embeddings
claude mcp add nexus-mcp -e NEXUS_EMBEDDING_DEVICE=cuda -- nexus-mcp-ci

# Virtualenv install — pass the full binary path
claude mcp add nexus-mcp -- /path/to/.venv/bin/nexus-mcp-ci

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "nexus-mcp": {
      "command": "nexus-mcp-ci",
      "args": [],
      "env": {
        "NEXUS_EMBEDDING_DEVICE": "cpu"
      }
    }
  }
}

Cursor / Windsurf / Cline / Any MCP Client

{
  "nexus-mcp": {
    "command": "nexus-mcp-ci",
    "transport": "stdio"
  }
}

Agent Integration Patterns

CLAUDE.md boilerplate (drop into project root)

## Code Intelligence — nexus-mcp

1. **Session start**: no setup call. Run `index` only if a tool says "No codebase indexed"
2. **To find code you cannot name**: `search`, before reading files one by one
3. **To see symbols you can name**: `find_symbol`, with all the names in one call
4. **Before refactoring**: `graph` with `transitive=true` to assess blast radius. The call graph is static (no dynamic dispatch), so also use `search` to find call sites.
5. **For project orientation**: `map` with `detail="summary"` or `detail="architecture"`
6. **When you know the exact file or string**: plain grep or read is fine

Typical agent tool-call sequence

# Session start
status()               → "indexed: True, 8,412 chunks, 1,203 symbols, 87 MB"

# Code discovery
search("JWT token validation", limit=10)
  → auth/jwt.py:42  validate_token()         score=0.94
  → auth/middleware.py:18  require_auth()    score=0.87
  → tests/test_auth.py:91  test_valid_jwt()  score=0.81

# Symbols you can name
find_symbol("validate_token, require_auth")
  → the code of each, file and lines
  → callers: [post_order, ...], callees: [...]

# Pre-refactor safety check
graph("validate_token", direction="callers", transitive=True)
  → total_impacted: N          # a lower bound: dynamic calls are not visible

# Locate call sites with search instead
search("validate_token(", mode="bm25")
  → auth/middleware.py:18  require_auth()  ...
  → auth/login.py:57  login_required()     ...

Multi-folder monorepo indexing

# Index multiple roots in one call — processed sequentially, shared engines
index(path="packages/api/src,packages/shared/src,packages/cli/src")

# Or use the paths parameter for additional roots
index(path="packages/api/src", paths="packages/shared/src,packages/cli/src")

Configuration

All settings via NEXUS_ environment variables:

Variable Default Description
NEXUS_EMBEDDING_MODEL bge-small-en bge-small-en (384-dim). jina-code is deprecated
NEXUS_EMBEDDING_DEVICE auto auto (CUDA → MPS → CPU), cuda, mps, cpu
NEXUS_STORAGE_DIR .nexus Index storage directory
NEXUS_AUTO_WATCH true Auto-reindex on file change via a debounced watcher, started after index()
NEXUS_AUTO_RESTORE true A new server process reattaches to the stored index, so status is already indexed: true
NEXUS_WARM_START true Attach the index and load the embedding model in the background while the server starts, so the first search does not wait about 7 s. The model then uses its memory (about 370 MB) from the start of each session
NEXUS_STALENESS_CHECK_INTERVAL 15 Seconds between status()/search() staleness checks (throttled, not per-call)
NEXUS_MAX_FILE_SIZE_MB 10 Skip files larger than this
NEXUS_CHUNK_MAX_CHARS 4000 Max chars per code chunk
NEXUS_EMBEDDING_BATCH_SIZE 32 Chunks per embedding batch. Lower it to cut peak RAM while indexing
NEXUS_INDEX_FILE_BATCH_SIZE 50 Files per streaming indexing batch
NEXUS_GRAPH_MAX_DEPTH 10 Max depth for transitive graph queries
NEXUS_MAX_MEMORY_MB 350 Memory budget target
NEXUS_SEARCH_MODE hybrid hybrid, vector, or bm25
NEXUS_FUSION_WEIGHT_VECTOR 0.5 Vector score weight in RRF
NEXUS_FUSION_WEIGHT_BM25 0.3 BM25 score weight in RRF
NEXUS_PERMISSION_LEVEL full full, read, or restricted
NEXUS_RATE_LIMIT_ENABLED false Enable per-tool token-bucket rate limiting
NEXUS_AUDIT_ENABLED true Structured audit logging with correlation IDs
NEXUS_TRUST_REMOTE_CODE true Needed only by the deprecated jina-code; set false with bge-small-en
NEXUS_LOG_LEVEL INFO Logging level
NEXUS_LOG_FORMAT text text or json

The Python package defaults to bge-small-en. The Dockerfile, smithery.yaml and glama.json use the same default. jina-code still loads, with a warning, so an existing index keeps working. It is deprecated and will be removed in a future major release.

Embedding Models

Model Key Dims Max Seq Backend trust_remote_code
BGE Small EN v1.5 (default) bge-small-en 384 512 PyTorch No
Jina Embeddings v2 Code (deprecated) jina-code 768 8,192 ONNX Yes

After changing model, re-index. Embeddings from different models are incompatible.


Comparison

vs. Other MCP Servers

Feature Nexus-MCP Sourcegraph MCP Greptile MCP GitHub MCP tree-sitter MCP
Fully local / private ✅ ❌ infra required ❌ cloud ❌ cloud ✅
Semantic (vector) search ✅ ❌ keyword only ✅ LLM-based ❌ ❌
Keyword (BM25) search ✅ ✅ — ✅ ❌
Hybrid fusion (RRF) ✅ ❌ ❌ ❌ ❌
Code graph (call/import) static: containment, imports, calls ✅ SCIP ❌ ❌ ❌
Semantic memory (persistent) ✅ 6 types ❌ ❌ ❌ ❌
Change impact analysis static callers only partial ❌ ❌ ❌
Token-budgeted responses ✅ 3 levels ❌ ❌ ❌ ❌
Languages 25+ 30+ many many many
Cost Free noncommercial; paid commercial license $$$ $40/mo $10–39/mo Free
API keys required No Yes Yes Yes No

vs. AI Code Tools

Capability Nexus-MCP Cursor Copilot @workspace Cody Continue.dev Aider
IDE-agnostic ✅ ❌ ❌ ❌ ❌ ✅
MCP-native ✅ partial ❌ ❌ ✅ client ❌
Fully local ✅ partial ❌ partial ✅ ✅
Hybrid search ✅ unknown unknown keyword yes ❌
Code graph partial (containment + imports) unknown unknown ✅ SCIP basic ❌
Semantic memory ✅ persistent ❌ ❌ ❌ ❌ ❌
Token-budgeted output ✅ — — — — —
Source available ✅ PolyForm Noncommercial ❌ ❌ partial ✅ ✅
Cost Free noncommercial; paid commercial license $20–40/mo $10–39/mo $0–49/mo Free Free

Development

git clone https://github.com/jaggernaut007/Nexus-MCP.git
cd Nexus-MCP
pip install -e ".[dev]"

pytest -v                    # 1,132 tests (1,120 without slow)
pytest -m "not slow"         # skip performance benchmarks
pytest tests/test_hybrid_search.py  # single module
ruff check .                 # lint

Project Structure

src/nexus_mcp/
├── server.py              # FastMCP entrypoint — 10 thin tool wrappers (permission guard, rate limit, audit), graceful shutdown
├── core_api.py            # Transport-agnostic tool logic + input validation; importable without MCP
├── config.py              # Settings (NEXUS_ env prefix)
├── state.py               # Global singleton SessionState
├── core/
│   ├── models.py          # Symbol, ParsedFile, CodebaseIndex, Memory
│   ├── graph_models.py    # UniversalNode, Relationship
│   ├── interfaces.py      # IParser, IEngine protocols
│   └── exceptions.py      # NexusException hierarchy
├── parsing/
│   ├── treesitter_parser.py   # Symbol extraction (parallel)
│   ├── astgrep_parser.py      # Structural graph extraction (sequential)
│   ├── language_registry.py   # 25+ language definitions
│   └── file_watcher.py        # Debounced watchdog for live reindex
├── engines/
│   ├── vector_engine.py   # LanceDB cosine similarity search
│   ├── bm25_engine.py     # LanceDB native FTS (Tantivy)
│   ├── graph_engine.py    # rustworkx PyDiGraph with RLock
│   ├── live_grep.py       # rg/grep fallback for unindexed or sparse results
│   ├── fusion.py          # Reciprocal Rank Fusion
├── indexing/
│   ├── pipeline.py        # 8-step indexing pipeline
│   ├── embedding_service.py   # ONNX Runtime, GPU/MPS auto-detect
│   ├── parallel_indexer.py    # ThreadPool over files
│   └── chunker.py         # Symbol → CodeChunk with deterministic IDs
├── memory/
│   └── memory_store.py    # LanceDB-backed memory, TTL, 6 types
├── analysis/
│   └── code_analyzer.py   # Cyclomatic/cognitive complexity, smells
├── formatting/
│   ├── token_budget.py    # Token counting and truncation
│   └── response_builder.py  # Structured responses
├── persistence/
│   └── store.py           # SQLite graph persistence
├── security/
│   ├── permissions.py     # READ/MUTATE/WRITE tool categories
│   └── rate_limiter.py    # Token-bucket, per-tool, thread-safe
└── middleware/
    └── audit.py           # Structured audit logs, correlation IDs, field redaction
benchmarks/                # Token-efficiency benchmark harness (ADR-018)
self_test/                 # End-to-end demo of the 8 tools and the Python API
plugin/                    # Claude Code plugin: registers the server + routing skill

Adding a New Tool

  1. Add the logic as a plain function in core_api.py
  2. Validate input there with the validate_* helpers (validate_path, validate_symbol_name, validate_query)
  3. Add a thin wrapper in server.py decorated with @mcp.tool() and @_audited, and call _guard("<tool>") first
  4. Add the permission category to security/permissions.py
  5. Write tests in tests/
  6. Update self_test/demo_mcp.py to exercise the tool

Adding a New Language

  1. Add entry to parsing/language_registry.py with the tree-sitter grammar
  2. Add structural patterns to parsing/astgrep_parser.py for call/import extraction
  3. Add test fixtures in tests/fixtures/

Self-Test

Verify your installation exercises the 8 tools and the Python API end-to-end:

python self_test/demo_mcp.py                   # built-in sample project
python self_test/demo_mcp.py /path/to/project  # your own codebase

Expected output: the 8 tools and the Python API exercised with pass/fail per tool and a summary.


Known Limitations

  • Sequential graph parsing: ast-grep runs sequentially (not parallel) to keep the call graph consistent. This is the main indexing bottleneck on large codebases.
  • bge-small-en uses PyTorch: The default model runs on PyTorch, not ONNX.
  • No incremental graph updates: Graph is rebuilt in full on incremental reindex (only vector/BM25 are incremental at the chunk level).
  • No SSE transport: Only stdio transport is currently supported.
  • Language coverage: 25+ languages get tree-sitter symbol extraction. ast-grep structure (functions, classes, imports) covers Python, JavaScript, TypeScript, Go, Java, and Rust; other languages have no graph structure.
  • Call edges are static and name-based. graph() and the callers/callees fields of find_symbol() come from parsing, not runtime tracing. Edges exist for Python, JavaScript, TypeScript, Go, Java and Rust. A call resolves only when the callee is in the same file, in an imported file, or has a unique name in the index. A name shared by several definitions gets no edge, so results are a lower bound. Dynamic dispatch, monkey-patching, callbacks and reflection do not show up, so treat graph(transitive=True) as a lower bound on blast radius.
  • Complexity is approximate: cyclomatic complexity counts branch points per function. Only Python counts and/or, and only Python functions get docstrings on graph nodes.
  • Auto-reindex has a detection lag: with the file watcher enabled (default), edits are picked up after a short debounce, and status()/search() run a throttled staleness check as a backstop — not an instant, per-call guarantee of freshness.

Architecture Decision Records

Key decisions are documented in docs/adr/:

ADR Decision
ADR-001 Merge two MCP servers into one
ADR-002 LanceDB over ChromaDB
ADR-003 ONNX Runtime over PyTorch for embeddings
ADR-004 bge-small-en as default embedding model
ADR-005 Dual parser: tree-sitter + ast-grep
ADR-006 rustworkx for graph algorithms
ADR-007 12-column PyArrow schema for LanceDB
ADR-008 Symbol-based chunking with deterministic IDs
ADR-009 8-step indexing pipeline
ADR-010 Graph tools API: serialization, ambiguity handling
ADR-011 Graceful shutdown, corruption recovery, JSON logging
ADR-012 READ/MUTATE/WRITE permission categories
ADR-013 Pydantic v2 I/O schemas — superseded by ADR-016 (never wired in, deleted)
ADR-014 Token-bucket rate limiting (off by default)
ADR-015 Auto-watch + throttled staleness detection
ADR-016 Removal of unused Pydantic schemas (supersedes ADR-013)
ADR-017 Tool consolidation 15→10, action-aware permission categories
ADR-018 Token-efficiency benchmark harness (benchmarks/)

Documentation


Acknowledgments

Nexus-MCP consolidates two earlier open-source projects:

  • CodeGrok MCP by rdondeti (Ravitez Dondeti, MIT) — Contributed the symbol extraction pipeline, embedding service, parallel indexer, core data models, and memory retrieval system.
  • code-graph-mcp by entrepeneur4lyf — Contributed the ast-grep structural parser, rustworkx graph engine, complexity analysis, and relationship extraction.

Source files retain "Ported from" attribution in their module docstrings. See ADR-001 for the consolidation rationale.


License

PolyForm Noncommercial License 1.0.0. Free to use, copy, modify, and distribute for any noncommercial purpose. Commercial use requires a separate license — contact Shreyas Jagannath to inquire.

Versions published before 2.0.1 (0.1.0, 0.1.1, 2.0.0) remain available under their original MIT terms for anyone who obtained them under that license.

Metadata

Release files for nexus-mcp-ci 2.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nexus-mcp-ci 2.1.0
File Size Uploaded Provenance Actions
nexus_mcp_ci-2.1.0.tar.gz 647.7 kB With provenance Details for nexus_mcp_ci-2.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for nexus-mcp-ci 2.1.0
File Interpreter ABI Platform Actions
nexus_mcp_ci-2.1.0-py3-none-any.whl Python 3 none any Details for nexus_mcp_ci-2.1.0-py3-none-any.whl

Total release size: 767.8 kB

Release files / nexus_mcp_ci-2.1.0.tar.gz

Download URL nexus_mcp_ci-2.1.0.tar.gz
Size 647.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5219652212febe7b8c4a37433db7d6d63a8ad2e0898dacb4d6183afcf029025f
BLAKE2b-256 checksum
How to use checksums
0a0ea5cab4c50be9391ad5bf44ac504d16f949959b503e273f3f903124edb59e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Release files / nexus_mcp_ci-2.1.0-py3-none-any.whl

Download URL nexus_mcp_ci-2.1.0-py3-none-any.whl
Size 120.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6700fac57ed799a073c2615d3eb4029ae070be10575468662e9bc5dfbd01a5f7
BLAKE2b-256 checksum
How to use checksums
c95a4f8bc93d06ef846e9ba58e497f52bbe40f3915d814c7c08da7c6ab2a0dff
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

Security for nexus-mcp-ci 2.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for nexus_mcp_ci-2.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page