SkillAgentSearch skills...

LynxMCP

100% local MCP server for semantic code search: AST-aware chunking, hybrid BM25+dense retrieval, code knowledge graph

Install / Use

claude mcp add lorenzo-cambiaghi -- npx -y github:lorenzo-cambiaghi/LynxMCP

If the server publishes to npm under a different name, use that package instead — check the repo README.

About this skill
🔌

MCP Server

Model Context Protocol server

Quality Score

77/100

Supported Platforms

Claude Code
Claude Desktop
Cursor

Tags

Lynx

A 100% local MCP server for semantic code search — AST-aware chunking, hybrid BM25 + dense retrieval, and an optional code knowledge graph. Works with any MCP client (Claude Code, Cursor, Windsurf, Antigravity, ...).

Tests License: Apache 2.0 Python 3.10+ Glama score

LynxMCP MCP server

Your AI assistant greps file names and guesses. Lynx gives it real retrieval over your code, your library docs, and your PDFs — without a single byte leaving your machine.

💸 What it saves you — every wrong file your AI opens is billed tokens

Agentic coding burns tokens re-reading files the assistant grepped into the wrong place. Lynx hands it the right code in one tool call, with file:line and symbol — measured on real codebases:

<div align="center">

| Tokens to get the answer into context | Agentic grep | Lynx | | |---|---:|---:|:--| | Django 5.2 — Python, 158k lines | 4,150 | 1,725 | −58% | | Json.NET — C#, 69k lines | 6,590 | 1,540 | −77% | | Guava — Java, 181k lines | 5,892 | 807 | −86% |

</div>

Plus: outline triage is 2.4× fewer tokens, and the code arrives in 1 tool call instead of 2+ (chunks included, with symbol + file:line + score). The token cut holds across languages — even where grep ranks results just as well, because Lynx returns the whole function in one call instead of match-lines plus a follow-up read.

That's real money at today's frontier API prices. For 25 engineers (≈31,500 retrievals/month), the yearly API bill Lynx removes:

<img src="https://raw.githubusercontent.com/lorenzo-cambiaghi/LynxMCP/main/docs/img/cost_savings.svg" alt="Yearly API bill Lynx removes, by flagship model, for Python and C# codebases" width="880">

| Flagship model (input $/1M) | Django (Python) | Json.NET (C#) | Guava (Java) | |---|---:|---:|---:| | Claude Fable 5 — Anthropic flagship ($10) | ≈ $85,000 | ≈ $95,000 | ≈ $95,000 | | GPT‑5.5 — OpenAI flagship ($5) | ≈ $42,000 | ≈ $47,000 | ≈ $47,000 | | Claude Opus 4.8 — top coding model ($5) | ≈ $42,000 | ≈ $47,000 | ≈ $47,000 |

<sub>Token deltas are measured (Django · Json.NET · Guava). The yearly figures add one eliminated grep round‑trip re‑billing a 20k‑token context; the conservative floor (tool output only, zero assumptions) is $0.4k–1.6k/mo depending on model and codebase. Run it for your own team, prices and codebase: CLI python benchmarks/savings_calculator.py --devs N, or the interactive savings calculator — pick the codebase and model from drop‑downs and edit the $/1M price live (presets in benchmarks/pricing.json + measured.json, yours to change).</sub>


  • AST-aware indexing — tree-sitter parses 18+ languages (19 grammars, counting TSX) and indexes whole functions/classes, not arbitrary text windows.
  • Hybrid retrieval — dense embeddings + code-tokenized BM25, fused with RRF; optional cross-encoder reranker.
  • Token-efficient triageview=outline returns signatures instead of bodies, so an agent scans the candidates for ~2.4× fewer tokens and reads only the code it picks (measured).
  • Code knowledge graph (opt-in) — who-calls-what, inheritance, imports: ask "what breaks if I change this?" and get the actual blast radius — or export it as a single, shareable, offline graph view (lynx graph export).
  • Joinable as SQL — search and the graph are also served as rows over a local HTTP API, so you can correlate your code with tickets, PRs, or logs in DuckDB or Coral — no data leaves your machine.
  • Multi-source — index codebases, public docs sites (fetched once, on demand; JS-rendered SPAs supported via optional headless Chromium), and PDFs side by side.
  • Live index — a file watcher re-indexes saves in ~2s. No manual rebuild ritual.
  • Web manager UIlynx manager ui gives you guided setup, a query playground, diagnostics, and client config snippets.
<p align="center"> <a href="docs/GUIDE.md#lynxmanager--guided-setup-web-ui-diagnostics-new-in-v09"> <img src="https://raw.githubusercontent.com/lorenzo-cambiaghi/LynxMCP/main/readmeData/LynxManagerV.gif" alt="LynxManager — guided setup, query playground, and diagnostics in the browser" width="820"> </a> <br> <sub><b><a href="docs/GUIDE.md#lynxmanager--guided-setup-web-ui-diagnostics-new-in-v09">LynxManager</a></b> — guided setup, query playground &amp; diagnostics, all in the browser. <a href="docs/GUIDE.md#lynxmanager--guided-setup-web-ui-diagnostics-new-in-v09">Full walkthrough →</a></sub> </p> <p align="center"> <img src="https://raw.githubusercontent.com/lorenzo-cambiaghi/LynxMCP/main/docs/img/graph_view_example.svg" alt="Blast-radius graph view: callers above the symbol, callees below, exported as a single offline file" width="820"> <br> <sub><b>Shareable graph views</b> — <code>lynx graph export --symbol GetVoxel</code> writes one self-contained, offline file (no server, no CDN): the symbol's <b>blast radius</b> — who calls it (above) and what it calls (below). Attach it to a PR or archive it for an audit.</sub> </p>

Quickstart

# 1. Install the CLI (isolated, no venv ritual)
pipx install lynx-mcp
#    or: uv tool install lynx-mcp

# 2. Create a config pointing at your project
lynx manager init

# 3. Build the index (downloads the ~130MB embedding model on first run)
lynx build

Then register Lynx in your MCP client (Claude Code shown; see the full guide for Cursor, Antigravity, and generic stdio clients — or let lynx manager ui generate the snippet for you):

{
  "mcpServers": {
    "lynx": {
      "command": "lynx",
      "args": ["serve", "--config", "/absolute/path/to/config.json"]
    }
  }
}

Prefer zero terminal? There are double-click installers for macOS and Windows.

The tools your AI gets

The tool set is fixed — it does not grow with the number of sources, so your client's tool list (and context window) stays small. Tools take a source argument where relevant.

| Tool | What it answers | |------|-----------------| | search(query, source?, outline?) | Primary hybrid search. Omit source to search every source at once (RRF-fused). outline=true returns signatures-only for cheap triage (see below). | | deep_search(queries, source?) | Escalation: tries multiple query phrasings until one passes a quality threshold. | | graph_query(operation, symbol?) | callers, callees, subclasses, superclasses, imports, neighbors, shortest_path, overview, surprising_connections, status. | | find_definition(symbol) | Where is X defined? (AST-precise when the graph is on, BM25 fallback otherwise.) | | find_usages(symbol) | Every use of X — calls and non-call references (generics, decorators, docs). | | find_tests_for(symbol) | Are there tests for X? | | find_similar(snippet) | Does code like this already exist? | | describe_symbol(symbol) | One-shot context for X: definition + who calls it + what it calls + its tests, in a single call. | | impact(symbol) | Blast radius: everything that reaches X transitively through the call graph (with hop distance) + the tests to re-run. | | module_summary(file) | A file as a unit: the symbols it defines, what it imports, and which files depend on it. (graph) | | repo_overview() | "What is this and where do I start": detected languages, frameworks, entry points, and build/test/run commands. | | export_graph(target, mode?) | Render a shareable, offline graph view — a symbol's blast radius or a file hub — as a single self-contained file. (graph) | | search_diff(query, base?) | Search only the files changed vs a base branch — built for code review. | | feedback(trying_to_do, tried, stuck) | The agent files a report when the index couldn't answer — stored 100% locally, your signal for tuning sources. | | list_sources / get_rag_status / update_source_index | Introspection and maintenance. |

Retrieval tools carry MCP readOnlyHint annotations (clients can auto-approve them); the only write is export_graph, which saves a graph view file. The server ships its usage playbook in the MCP handshake (instructions + a lynx://guide resource) — your agent knows how to query well without any rules-file setup.

(graph) tools need the optional code knowledge graph enabled for the source. The tool set is per-capability, never per-source.

How it works

flowchart LR
    A["Your code + docs + PDFs"] --> B["Tree-sitter<br/>AST chunker"]
    B --> C["bge-small<br/>dense embeddings"]
    B --> D["code-tokenized<br/>BM25"]
    B --> G["Code knowledge graph<br/>(opt-in)"]
    C --> R{{"RRF fusion"}}
    D --> R
    Q(["Your query"]) --> R
    R --> RR["Optional<br/>reranker"]
    RR --> RES["Ranked code<br/>file : line : symbol"]
    G --> GT["Graph tools<br/>callers · subclasses · usages"]

    classDef store fill:#fff3e6,stroke:#e8742c,color:#24292f;
    classDef out fill:#e8742c,stroke:#e8742c,color:#fff;
    class C,D,G store;
    class RES,GT out;

Everything runs locally: HuggingFace models are downloaded once, then Lynx switches to offline mode. No telemetry, no cloud index, no code upload. The only network access is the model download and the explicit webdoc fetch step you trigger yourself.

Restricted networks / air-gapped machines

The embedding model is a public HuggingFace model (BAAI/bge-small-en-v1.5, ~130MB) — no account or token is required. If you hit We couldn't connect to 'https://huggingface.co', the machine simply can't reach the Hub (firewall, proxy, DNS, or an offline box).

You usually don't need to do anything. When the HuggingFace download fails, Lynx automatically falls back to a copy of the model hosted on this repo's GitHub Releases and installs it from there — including on the installer's first run. You only need the steps below if GitHub is also unreachable, or if you want to use a mirror / a shared cache / your own host.

  • Point the fallback elsewhere — if you can't reach github.com either but you host the archive somewhere reachable (an internal server, an artifact store), set the base URL and the automatic fallback uses it:
    export LYNX_MODEL_ARCHIVE_BASE_URL=https://<your-host>/lynx-models
    # expects <base>/BAAI--bge-small-en-v1.5.zip (produced by --export-archive)
    
  • Mirror — point Lynx at a reachable HuggingFace mirror and (optionally) a shared cache, then download normally:
    export HF_ENDPOINT=https://<your-mirror>   # e.g. an internal proxy or hf-mirror.com
    export HF_HOME=/shared/hf-cache            # optional: shared/persistent cache
    lynx manager install --model
    
  • Transfer an archive — on a machine with access, export the model, copy the file to the offline machine (USB, scp, an internal share…), then import it:
    # online machine
    lynx manager install --model
    lynx manager install --export-archive bge-small.zip
    
    # offline machine — local path or a direct download URL both work
    lynx m
    

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated1d ago
Forks1

Languages

Python

Security Score

92/100

Audited on Aug 16, 2026

1 low