100% local MCP server for semantic code search. Hybrid BM25 + dense search on ONNX Runtime, call graph and blast radius analysis, library docs and PDFs as sources. No cloud, no PyTorch.
LynxMCP presents 17 well-designed code search tools with strong naming conventions and comprehensive parameter schemas. All tools follow verb_noun patterns (search, find_*, describe_*, export_*, etc.) and are purpose-specific without compound responsibilities. Descriptions are detailed and contextual, explaining WHEN to use each tool relative to alternatives. Parameter schemas are fully typed with descriptions. However, output schemas are not explicitly documented in the visible source code, the tool profiles reference return types (e.g., 'Returns ranked chunks with file:line, symbol and score') but structured schemas are not formally specified. Error handling descriptions are minimal; tools mention failures (e.g., 'weak or empty' results) but lack actionable recovery guidance. The feedback and export_graph tools perform writes, but risk handling and permission gating are not visible. Overall, the definition quality is strong for discovery and read-only operations but lacks production hardening details around error recovery and security.
Escalation for when `search` came back weak or empty: runs 2-4 genuinely different phrasings of the same need and returns the first set that passes the quality threshold, or the strongest weak set with a warning. Slower than `search`; do not start here.
One-shot context for a symbol: definition, who calls it, what it calls, and its tests, in a single call. The fastest way to understand a function or class before changing it, and cheaper than find_definition, find_usages and find_tests_for one after the other. Call data needs the graph layer; definition and tests always work.
Write a self-contained offline HTML view of a symbol's blast radius (mode=symbol) or a file's imports and dependents (mode=module), for a human to open or attach to a PR. Returns the file path.
Report that the index could not answer you, before giving up. Appended to a local log (never uploaded) so the index owner can tune sources and filters.
Jump to where a symbol is defined, when you already know its name. AST-precise when the graph layer is on, BM25 fallback otherwise; each hit says which. Use `search` instead when you can only describe what the code does, and describe_symbol when you also want the callers and the tests in the same call.
Output schemas not explicitly documented. Tool descriptions reference return structures ('Returns ranked chunks with file:line, symbol and score') but formal JSON Schema output definitions are not visible in the source code. LLMs cannot reliably infer nested field structures or pagination patterns without explicit documentation.
Error handling and recovery guidance missing. Tools mention failure modes ('Escalation for when search came back weak', 'BM25 fallback otherwise') but do not include actionable recovery instructions. No error classification (retryable vs fatal) or corrective suggestions visible.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 63 | 2026-07-28+ | v2 |
Code semantically similar to a snippet you already have, dense search only: use it before writing a function, to check whether something like it exists. `search` is the one to call when you can describe the need in words instead. Snippets are cut at 2000 chars.
List the tests that mention a symbol, searched under conventional test paths (tests/, spec/, __tests__/, *_test.*, *.spec.*, *Test.cs, *Tests.cs); test_path_pattern replaces them for another layout. Use it when the tests are all you want, before or after a change; describe_symbol returns the same tests bundled with the definition and the callers, and impact returns them for a whole blast radius.
Every use of a symbol: calls (from the graph when on) plus textual references (generics, decorators, imports, docs), definition excluded. Answers 'who uses X' at one hop; `impact` walks the chain further and adds the tests.
Index state for one or all sources: freshness, chunk count, last update, drift. Check it before considering a rebuild.
Raw access to the code knowledge graph (calls, inheritance, imports), for the questions the dedicated tools do not cover: find_usages, impact and describe_symbol answer the common ones with the results already shaped. operation: callers | callees | subclasses | superclasses | imports | neighbors | shortest_path | overview | surprising_connections | status. `symbol` is matched as a case-insensitive substring; results carry file:line.
Answer 'what breaks if I change this': everything that reaches a symbol transitively through the call graph, with hop distance, plus the tests to re-run. Use find_usages for the direct, one-hop answer; use this before a risky edit, when the indirect callers are the point. max_depth trades reach for noise: 2 stays close to the change, 6 on a hub symbol can return most of the codebase. Transitive callers need the graph layer.
List which sources exist and what each one is: name, type, path, chunk count and drift flag. Read from config and metadata, no index opened. Call it first when you do not know the source names a `source` argument expects; for how fresh one index is, and whether to rebuild it, use get_rag_status instead.
A file as a unit: the symbols it defines, what it imports, and which files depend on it (via the call graph). Read it before editing a file you don't know; repo_overview does the same for the whole repository, and describe_symbol for one symbol inside the file.
Orientation for an unfamiliar codebase: languages by file count, frameworks, manifests, likely entry points, and build/test/run commands. Filesystem scan, no index needed. Call once per session.
Hybrid semantic + lexical search over the indexed code and docs. Describe what the code does in plain words ('method that clamps camera zoom'), not an identifier. Returns ranked chunks with file:line, symbol and score; a hybrid score near 0.03 is a strong match. Omit `source` to search every source at once. outline=true returns signatures only, for cheap triage of broad queries.
Search only the files added or modified against a base branch (auto-detected main / master / develop). For code review: what else in my change uses this formula? Returns the base, the modified files and the hits.
Force a full rebuild of a source's index. Expensive and blocking; the watcher keeps the index current, so use it only after a big merge or a drift warning.
Write-capable tools (export_graph, feedback, update_source_index) lack permission gating descriptions and confirmation/dry-run patterns. No audit trail or permission scope declaration visible.
Pagination not uniformly described. Some tools accept top_k/limit but no documentation of whether results are truncated, whether next_cursor or offset exists, or what happens at boundary conditions (limit=1000 on large result sets).
Parameter constraints not uniformly formal. Some numeric params lack min/max bounds (e.g., graph_query 'limit' and 'depth' have no stated ranges). File glob and extensions accept arbitrary strings without validation hint.