Nexus-MCP

io.github.jaggernaut007由 GitHub 账号 jaggernaut007 发布v2.3.0更新于 Nov 7, 2026

Local code-intelligence server: hybrid code search, call graph and project memory.

概览

AI 生成的概览

本地代码智能 MCP 服务器,让助手进行混合代码搜索、查看静态调用图并保存项目记忆,全程无需云端调用。

可以做什么
  • 索引与查看项目:建立或增量刷新索引、检查索引健康与过期状态、梳理文件、语言、分层与入口点
  • 以向量、关键词与图加权融合的方式搜索代码,结果稀少时回退到实时 grep
  • 按名称查找符号,并通过静态调用图追踪调用方、被调用方与传递性变更影响
  • 用复杂度、代码坏味道和依赖指标评估代码质量
  • 存储、语义检索和删除跨会话保留的项目笔记与决策
适用场景
适合助手在中等至大型代码库中工作、希望减少整文件读取并快速定位相关文件,或在重构前评估影响范围时使用。README 指出效果因项目而异:在不熟悉的私有项目上收益明显,在模型已熟悉的公开项目上成本略高。
运行要求
以 Python 包形式通过 stdio 在本地运行,需 Python 3.10 至 3.12,用 pip 安装并在 MCP 客户端中注册。嵌入模型首次运行需从 Hugging Face 下载,设置 NEXUS_OFFLINE=1 可阻止后续下载。索引默认存放在项目的 .nexus 目录,可用 NEXUS_STORAGE_DIR 更改。可选安装 ripgrep 以增强回退搜索。无需 API 密钥。
安装前请注意
索引、记忆和图会写入项目的 .nexus 目录且包含代码,应加入 .gitignore。首次运行会从 Hugging Face 下载模型。eval 子命令可克隆 URL,使用 --agent 或 share 时会把提示、代码或数字发送给 Anthropic 或 OpenAI,两者都会先询问。NEXUS_PERMISSION_LEVEL=read 时记忆仅允许搜索。调用图是静态的,影响分析结果只是下限。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Nexus-MCP,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

Nexus-MCP

[PyPI version] [PyPI downloads] [PyPI downloads (pypistats)] [Python 3.10–3.12] [License: MIT] [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 local code-intelligence MCP server for Claude Code, Codex, Cursor and any Model Context Protocol client. It gives AI agents precise, token-efficient answers about your codebase without cloud dependencies: no API keys, no data egress, no subscriptions.

Not sure yet? Measure it on your own code first. It is free, runs offline, calls no LLM and takes a few minutes:

bash
uvx nexus-mcp-ci eval            # the current folderuvx nexus-mcp-ci eval --example  # or the Nexus-MCP source, if you have no project at hand

You get a verdict ("Strong fit", "Likely fit" or "Weak fit") and the tokens an agent needs to reach the right file, with and without Nexus-MCP. Nothing leaves your machine. See Evaluate on your project.

Ready?

bash
pip install nexus-mcp-ciclaude mcp add nexus-mcp -- nexus-mcp-ci

Results at a glance

ProjectCost: Grep and Read → Nexus-MCPTurnsCorrect answers
Private Python project (460 files)$0.571 → $0.446 (-22%)55 → 3536 → 35 of 36
Django (3,000 files)$0.894 → $0.863 (-3%)93 → 7134 → 36 of 36

Live runs: Claude Code, Claude Sonnet, headless (claude -p), 12 questions per project, 3 runs each, version 2.1.0 (2026-10-28). The same code can vary by about 20% in cost with 3 runs per question (measured 2026-10-28). Search hit@1 on the four retrieval suites: jobscout 0.81, nexus_mcp 0.80, shop_repo 0.50, flask 0.64.

nexus-mcp-ci eval (the free offline check, no LLM) on 3 projects:

ProjectVerdictMedian tokens to the right fileRight file first
Chromium base/ (3,638 files)Strong fit17,998 → 95040% → 70%
pallets/click (91 files)Strong fit24,774 → 1,30127% → 97%
Nexus-MCP source (59 files)Likely fit5,385 → 1,23470% → 93%

Nexus-MCP and GitNexus on Chromium base/ (C++, 4,243 files): 8 tasks, 3 runs each, 2026-11-04.

ConditionVersionTokens (median)Cost per task (median)Correct
Grep and Readbuilt-in tools62,450$0.05724 of 24
Nexus-MCP2.2.0 with the C++ parser fixes of 2.2.182,900$0.06224 of 24
GitNexus1.6.12164,192$0.08524 of 24

Nexus-MCP used fewer tokens than GitNexus on 8 of 8 tasks and cost less on 6; GitNexus cost $0.002 less on one task, and one task was a tie. Grep and Read cost less than both on this C++ code. Nexus-MCP cost less than Grep and Read on 3 of 8 tasks (the two needle tasks and WeakPtr). Each condition had the same agent, model, prompt and built-in tools, and each tool had its MCP server and its always-loaded instructions (method).

All numbers: benchmarks page · JSON · CSV.


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/.


Evaluate on your project

Decide with your own numbers. The quick check is free, offline and calls no LLM:

bash
uvx nexus-mcp-ci eval                                   # the current folderuvx nexus-mcp-ci eval path/to/project                   # another folderuvx nexus-mcp-ci eval https://github.com/pallets/flask  # a public repo (shallow clone)uvx nexus-mcp-ci eval --example                         # the Nexus-MCP source, offline

It asks about 30 questions made from your own code and compares Grep and Read with one Nexus-MCP search. The right answer is the file that defines the symbol, from the parser, never from the Nexus-MCP ranking. On this repo's source (59 files) it gave "Likely fit": 1,234 median tokens to reach the right file against 5,385, and the right file first in 93% of questions against 70%. On Chromium's base/ (3,638 files of C++, Java and Python) it gave "Strong fit": 950 median tokens against 17,998 (95% fewer), and the right file first in 70% of questions against 40%. On pallets/click (91 files, from its URL) it gave "Strong fit": 1,301 median tokens against 24,774 (95% fewer), and the right file first in 97% of questions against 27%. On a tiny project Grep and Read win, and the report says so.

Want the real agent cost? The agent tier runs your own Claude Code or Codex login on tasks from your code, with and without Nexus-MCP. It shows the cost first and asks:

bash
nexus-mcp-ci eval --agent claude                       # Claude Sonnetnexus-mcp-ci eval --preset efficient --agent claude:haiku,claude:sonnet

Results are saved in ~/.nexus-mcp/evals/ (eval list, eval show <id>). eval share <id> posts the numbers (no code, no paths) to the community table, only after you say yes. Full guide: docs/EVALUATE.md. In Claude Code, the plugin adds /nexus-mcp:evaluate.


Privacy and Data

Your code stays on your machine. The server makes no network calls and has no telemetry.

  • In: the package from PyPI, and the embedding model from Hugging Face once (set NEXUS_OFFLINE=1 after that). eval <url> also runs a git clone.
  • Out: nothing, unless you run eval --agent (prompts and code go to Anthropic or OpenAI through your own CLI) or eval share (numbers only). Both ask first.
  • Stored: the index, memories and graph in <project>/.nexus/ (it holds code: add it to .gitignore), the model in ~/.cache/huggingface/, eval results in ~/.nexus-mcp/evals/.
bash
nexus-mcp-ci data where              # every location and its sizenexus-mcp-ci data clear --all        # dry run; add --yes to delete

Every location, the shell commands that do the same, and the uninstall steps: docs/PRIVACY.md.


Quickstart (60 seconds)

You need uv. Nothing else.

Ask your agent. Open your agent (Claude Code, Codex, Cursor, Gemini CLI) in your project and say:

Install Nexus-MCP from https://github.com/jaggernaut007/Nexus-MCP

The agent reads llms-install.md and runs one command. You can run the same command yourself:

bash
uvx nexus-mcp-ci setup

setup finds the MCP clients on your machine, shows each change, and asks before it writes anything. It adds the server and a short skill that tells the agent when to use each tool. Add --dry-run to see the changes only, --client codex to pick one client, and --uninstall to remove what it wrote. Then reload your client (or start a new session) and ask something like "where do we retry failed payments?". The agent calls search, and index once, the first time in a project.

The server sends its own usage instructions when it connects, so the agent knows which tool answers which question even without the skill.

Other ways in, each with the same server:

  • VS Code: Install in VS Code
  • Cursor: the "Add to Cursor" button on the website
  • Claude Desktop: download nexus-mcp.mcpb from the latest release and open it
  • Gemini CLI: gemini extensions install https://github.com/jaggernaut007/Nexus-MCP
  • Docker: docker run -i --rm -v "$PWD:/workspace" -v nexus-data:/data ghcr.io/jaggernaut007/nexus-mcp
  • GitHub Actions: uses: jaggernaut007/Nexus-MCP@v2

All channels, and what each needs: docs/DISTRIBUTION.md.

Claude Code plugin

The plugin registers the server and the same routing skill. It runs the server through uvx, so it needs only uv, no pip install:

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

Use setup or the plugin for Claude Code, not both, or the server is registered twice. Tool names differ by route: mcp__nexus-mcp__search after setup, 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:

markdown
## 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

LayerTechnologyDecision Rationale
Vector storeLanceDBmmap 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)
Embeddingsbge-small-enLightweight (384-dim, no trust_remote_code). Lazy-load/unload keeps RAM flat after indexing. (ADR-003)
Graph enginerustworkx PyDiGraphRust-backed, O(1) node lookup, PageRank + centrality algorithms. Thread-safe with RLock. (ADR-006)
Symbol parsertree-sitter 0.21.325+ languages, incremental parsing, AST-level symbol extraction with metadata. Parallel via ThreadPool. (ADR-005)
Graph parserast-grepStructural 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)
ChunkingSymbol-basedOne chunk per function/class. Deterministic SHA256 IDs prevent duplicate inserts. (ADR-008)
PersistenceSQLite + LanceDBGraph in SQLite (warm-start recovery), vectors+FTS in LanceDB, mtimes in JSON. Zero-config.
MCP frameworkFastMCP 2.0Stdio 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): the numbers are in Results at a glance, generated from benchmarks/published/results.json.

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 ReadNexus-MCP
Turns (sum of the median of each question)5534 (-38%)
Output tokens11,9178,881 (-25%)
Cost$0.571$0.459 (-20%)
Correct answers36 of 3636 of 36
Prompt on the first turn12,700 tokens16,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 ReadNexus-MCP
Turns (sum of the median of each question)9378 (-16%)
Output tokens32,29127,513 (-15%)
Cost$0.894$0.973 (+8.9%)
Correct answers34 of 3635 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 Readdjangojobscout
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

New in v2.3.0 (no breaking change): uvx nexus-mcp-ci setup installs the server and the skill into your MCP clients, new install routes cover Claude Desktop, Gemini CLI, VS Code, Cursor, Docker and GitHub Actions, and the license is now MIT. The MCP tools do not change.

New in v2.2.0 (no breaking change): nexus-mcp-ci eval measures Nexus-MCP on your own code (Evaluate), and nexus-mcp-ci data shows and clears every stored file (Privacy). The MCP tools do not change.

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

ToolUse 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.

Search

ToolUse 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

ToolUse 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

ToolUse 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

From PyPI (recommended)

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

From Source

bash
git clone https://github.com/jaggernaut007/Nexus-MCP.gitcd Nexus-MCP./setup.sh           # creates venv, installs, verifies# orpip 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:

bash
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

bash
# Minimalclaude mcp add nexus-mcp -- nexus-mcp-ci
# GPU embeddingsclaude mcp add nexus-mcp -e NEXUS_EMBEDDING_DEVICE=cuda -- nexus-mcp-ci
# Virtualenv install — pass the full binary pathclaude mcp add nexus-mcp -- /path/to/.venv/bin/nexus-mcp-ci

Claude Desktop

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

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

Cursor / Windsurf / Cline / Any MCP Client

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

Agent Integration Patterns

CLAUDE.md boilerplate (drop into project root)

markdown
## 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 one3. **To see symbols you can name**: `find_symbol`, with all the names in one call4. **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 startstatus()               → "indexed: True, 8,412 chunks, 1,203 symbols, 87 MB"
# Code discoverysearch("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 namefind_symbol("validate_token, require_auth")  → the code of each, file and lines  → callers: [post_order, ...], callees: [...]
# Pre-refactor safety checkgraph("validate_token", direction="callers", transitive=True)  → total_impacted: N          # a lower bound: dynamic calls are not visible
# Locate call sites with search insteadsearch("validate_token(", mode="bm25")  → auth/middleware.py:18  require_auth()  ...  → auth/login.py:57  login_required()     ...

Multi-folder monorepo indexing

python
# Index multiple roots in one call — processed sequentially, shared enginesindex(path="packages/api/src,packages/shared/src,packages/cli/src")
# Or use the paths parameter for additional rootsindex(path="packages/api/src", paths="packages/shared/src,packages/cli/src")

Configuration

All settings via NEXUS_ environment variables:

VariableDefaultDescription
NEXUS_EMBEDDING_MODELbge-small-enbge-small-en (384-dim). jina-code is deprecated
NEXUS_EMBEDDING_DEVICEautoauto (CUDA → MPS → CPU), cuda, mps, cpu
NEXUS_STORAGE_DIR.nexusIndex storage directory
NEXUS_AUTO_WATCHtrueAuto-reindex on file change via a debounced watcher, started after index()
NEXUS_AUTO_RESTOREtrueA new server process reattaches to the stored index, so status is already indexed: true
NEXUS_WARM_STARTtrueAttach 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_INTERVAL15Seconds between status()/search() staleness checks (throttled, not per-call)
NEXUS_IDLE_TIMEOUT10800Stop the server after this many seconds with no tool call (3 hours). 0 turns it off
NEXUS_EXIT_ON_PARENT_EXITtrueStop the server when the client process that started it is gone
NEXUS_SHUTDOWN_TIMEOUT10Longest wait for a running index at shutdown; the process then exits
NEXUS_MAX_FILE_SIZE_MB10Skip files larger than this
NEXUS_CHUNK_MAX_CHARS4000Max chars per code chunk
NEXUS_EMBEDDING_BATCH_SIZE32Chunks per embedding batch. Lower it to cut peak RAM while indexing
NEXUS_INDEX_FILE_BATCH_SIZE50Files per streaming indexing batch
NEXUS_GRAPH_MAX_DEPTH10Max depth for transitive graph queries
NEXUS_MAX_MEMORY_MB350Memory budget target
NEXUS_SEARCH_MODEhybridhybrid, vector, or bm25
NEXUS_FUSION_WEIGHT_VECTOR0.5Vector score weight in RRF
NEXUS_FUSION_WEIGHT_BM250.3BM25 score weight in RRF
NEXUS_PERMISSION_LEVELfullfull, read, or restricted
NEXUS_RATE_LIMIT_ENABLEDfalseEnable per-tool token-bucket rate limiting
NEXUS_AUDIT_ENABLEDtrueStructured audit logging with correlation IDs
NEXUS_TRUST_REMOTE_CODEtrueNeeded only by the deprecated jina-code; set false with bge-small-en
NEXUS_LOG_LEVELINFOLogging level
NEXUS_LOG_FORMATtexttext or json

The Python package defaults to bge-small-en. The Dockerfile, docker/Dockerfile.stdio 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

ModelKeyDimsMax SeqBackendtrust_remote_code
BGE Small EN v1.5 (default)bge-small-en384512PyTorchNo
Jina Embeddings v2 Code (deprecated)jina-code7688,192ONNXYes

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


Comparison

vs. other code-intelligence MCP servers

Features only, from each project's own documentation. We make no performance claims about other tools: run nexus-mcp-ci eval on your code instead.

FeatureNexus-MCPSerenaclaude-context
How it finds codehybrid: vectors + BM25language servers (LSP)hybrid: vectors + BM25
Where the index liveslocal LanceDBnone (live LSP)a vector database (Milvus or Zilliz Cloud)
Embeddingslocal model, no API keynonean embedding provider (OpenAI by default; Ollama possible)
Call graphstatic, 6 languagesLSP referencesno
Project memoryyesyesno
Edits codeno (read only)yesno
Measure it on your reponexus-mcp-ci eval——

Other servers in this space include codebase-memory-mcp, code-graph-rag, code-index-mcp and ast-grep-mcp. Check each project's docs. Corrections to this table are welcome.

vs. Other MCP Servers

FeatureNexus-MCPSourcegraph MCPGreptile MCPGitHub MCPtree-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 analysisstatic callers onlypartial❌❌❌
Token-budgeted responses✅ 3 levels❌❌❌❌
Languages25+30+manymanymany
CostFree (MIT)$$$$40/mo$10–39/moFree
API keys requiredNoYesYesYesNo

vs. AI Code Tools

CapabilityNexus-MCPCursorCopilot @workspaceCodyContinue.devAider
IDE-agnostic✅❌❌❌❌✅
MCP-native✅partial❌❌✅ client❌
Fully local✅partial❌partial✅✅
Hybrid search✅unknownunknownkeywordyes❌
Code graphpartial (containment + imports)unknownunknown✅ SCIPbasic❌
Semantic memory✅ persistent❌❌❌❌❌
Token-budgeted output✅—————
Source available✅ MIT❌❌partial✅✅
CostFree (MIT)$20–40/mo$10–39/mo$0–49/moFreeFree

Development

bash
git clone https://github.com/jaggernaut007/Nexus-MCP.gitcd Nexus-MCPpip install -e ".[dev]"
pytest -v                    # all tests (-m "not slow" skips the performance ones)pytest -m "not slow"         # skip performance benchmarkspytest tests/test_hybrid_search.py  # single moduleruff 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 redactionbenchmarks/                # Token-efficiency benchmark harness (ADR-018)self_test/                 # End-to-end demo of the 8 tools and the Python APIplugin/                    # 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:

bash
python self_test/demo_mcp.py                   # built-in sample projectpython 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/:

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

Documentation

Start at the docs index.


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

MIT. Free to use, copy, modify and distribute, for any purpose, including at work.

Versions 2.0.1 to 2.2.3 were released under the PolyForm Noncommercial License 1.0.0. Anyone who obtained one of those versions keeps the terms they got. Versions 0.1.0, 0.1.1 and 2.0.0 were MIT. Every new release is MIT.

If Nexus-MCP saves you tokens at work, a star or a sponsorship is welcome. Neither is required.

来源:README.md,提交 8986398

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

2
  1. v2.3.0最新Nov 7, 2026
  2. v2.2.0Nov 3, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分