AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Vex

mcp-tenatarika-vex · by tenatarika

Fast hybrid code search built for AI agents

No reviews yet
0 installs
26 views
0.0% view→install

Install

$ agentstack add mcp-tenatarika-vex

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-tenatarika-vex)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Vex? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Vex

[](LICENSE) [](https://github.com/tenatarika/vex/actions/workflows/ci.yml) [](https://www.rust-lang.org/) []() []() []()

Fast hybrid structural + semantic code search. Vector + index.

[Why Vex?](#why-vex) · [How It Compares](#how-it-compares) · [Installation](#installation) · [Quick Start](#quick-start) · [Commands](#commands) · [Configuration](#configuration) · [How Search Works](#how-search-works) · [Benchmarks](#benchmarks) · [Supported Languages](#supported-languages) · [Integration](#integration) · [Testing](#testing) · [Architecture](#architecture)

$ vex check "TelemetryProcessor"           # 4ms — does it exist? where? (exact name)
$ vex show "TelemetryProcessor"            # extract the class body (not the whole file)
$ vex usages "Config" --strict             # who references this symbol? (binder-resolved, no noise)
$ vex callers "process_event"              # who calls this function? (~4ms; covers module-scope + Python/Java decorators)
$ vex implementations "BaseService"        # who extends/implements this?
$ vex search "timeout retry"               # fuzzy / multi-word — BM25 finds rare body terms
$ vex search "handle alert" --semantic     # find by meaning, not just name
$ vex pattern 'fn $NAME($$$) -> Result'    # AST pattern matching (like ast-grep)
$ vex similar "PaymentService"             # semantically close symbols
$ vex duplicates --threshold 0.95          # near-duplicate pairs
$ vex bundle --mode symbol --symbol Foo    # body + callers + callees + similar in 1 call

Pick the right tool: vex check for "does Foo exist?", vex search for "find me something about retries". search is a ranked blend — it surfaces neighbors (callers / imports) when no symbol literally matches, which is great for exploration and wrong for exact-name lookup. v1.15.0 prints a stderr hint when an identifier-shaped search returns 0 FST hits.

Why Vex?

  • ~4ms search after indexing — FST-based O(query_len) lookup, not O(symbols). Requires a pre-built index (indexing takes 20ms-600ms+ depending on project size)
  • 3-channel hybrid search — structural FST (names) + BM25 (rare body terms) + semantic HNSW (meaning), fused via Reciprocal Rank Fusion. Find symbols when you don't know the exact name AND when generic semantic-only search would be too noisy
  • Persistent call graphvex callers/vex callees reads from an FST built at index time (~4ms), not a live tree-sitter scan (seconds). Module-scope expressions are reported via synthetic ` callers (Phase 14.1); Python + Java function/method decorators (Phase 14.2), Kotlin annotations + C# method/constructor attributes (Phase 14.2.2), and TypeScript method decorators + Rust outer attributes (Phase 14.2.1) emit forward edges to their targets. Class-level decorators remain invisible — see [docs/LIMITATIONS.md`](docs/LIMITATIONS.md)
  • Pluggable embedderEmbedder trait + registry; swap MiniLM-L6-v2 for future code-specific models (BGE, CodeBERT) without touching call sites
  • Token-efficient — compact output saves typically 6-10x fewer tokens than grep on average lookups (up to 88x on minified JS/CSS); vex show extracts just the symbol body instead of the whole file
  • 19 languages indexed via tree-sitter, with three coverage tiers: type-aware --strict usages on 5 binder languages (Rust / TypeScript / Python / C# / C++); indexed pattern prefilter on 12 T1+T2a languages; baseline structural + semantic search on all 19 (see [Supported Languages](#supported-languages) for the matrix)
  • Single binary, zero config — no LSP servers, no databases, no Docker. Just vex index && vex check Foo

What Vex isn't

vex is a static-analysis indexing tool, not a language server. Set expectations honestly:

  • Not an LSP replacement. No go-to-definition into third-party packages, no rename refactoring, no type-checking, no hover docs. For those, keep your LSP.
  • vex search is a ranked blend, not an exact-name lookup. Structural FST + BM25 + semantic fused via RRF return relevance-ordered results — when no symbol literally named Foo lives in the index (imported from a dependency, deleted, typo), BM25 may surface callers / imports as if they were the definition. For exact-symbol questions ("does it exist?", "show me the body", "who calls it?") use vex check Foo / vex show Foo / vex usages Foo --strict — they bypass the ranker. v1.15.0 prints a one-line stderr hint when an identifier-shaped query gets zero FST hits.
  • No dynamic-dispatch visibility. Decorator routing (@router.get("/path")), string-resolved factories (uvicorn.run("main:app")), reflection (getattr(obj, name)()), and macro-expanded references are all invisible to every vex command. vex grep '\bname\b' is the textual escape hatch.
  • vex callers has uneven coverage outside function scope. Module-level expressions like app = create_app() are reported via synthetic ` callers (Phase 14.1). Python + Java function/method decorators (Phase 14.2), Kotlin annotations + C# method/constructor attributes (Phase 14.2.2), and TypeScript method decorators + Rust outer attributes on fns/methods (Phase 14.2.1) emit forward edges — vex callers GetMapping lists every Spring handler, vex callers HttpGet every ASP.NET action, vex callers test every #[tokio::test]`. Class-level decorators (14.6) remain on the roadmap.
  • vex usages quality varies by language. 5 binder-supported languages get refactor-grade --strict refs; the other 14 use an identifier scanner with a higher false-positive rate.

See [docs/LIMITATIONS.md](docs/LIMITATIONS.md) for the full coverage matrix, concrete repros, and recommended workarounds per query type. Read it before evaluating vex on a Python/FastAPI/Django codebase — the framework patterns are the most-flagged gaps.

How It Compares

| | vex | ripgrep | ast-index | ast-grep | Serena | |---|---|---|---|---|---| | What it searches | Symbol definitions | All text | Symbol definitions | AST patterns | Symbols (via LSP) | | Requires indexing? | Yes (20ms-600ms+) | No | Yes | No | No | | Search speed | ~4ms (pre-built FST) | 75-120ms (disk scan) | 22-60ms (SQLite) | ~30ms (scan) | LSP-dependent | | Semantic search | HNSW + embeddings | -- | -- | -- | -- | | Pattern matching | fn $NAME($$$) | regex only | -- | fn $NAME($$$) | regex only | | Index size | 5 MB / 20K syms | no index | 190 MB / 20K syms | no index | no index | | Token efficiency | 6-88x fewer than rg | baseline | ~3x fewer than rg | N/A | N/A | | Symbol body extraction | vex show | -- | -- | -- | -- | | Languages | 19 | any | 10+ | 10+ | 40+ (LSP) | | Refactoring | -- | -- | -- | -- | rename, move, inline | | Runtime deps | none | none | none | none | Python + LSP |

Note: vex search speed assumes a pre-built index. Ripgrep and ast-grep require no upfront indexing and work immediately on any directory. The tradeoff is amortized: if you search the same codebase many times (typical in agent workflows), the one-time indexing cost pays for itself.

Best for: fast symbol search in AI agent workflows where token efficiency matters. Not a replacement for LSP-based tools (no refactoring, no go-to-definition in dependencies).

Installation

# Homebrew (macOS/Linux)
brew tap tenatarika/tap
brew install vex

# From source (any platform with a Rust toolchain)
git clone https://github.com/tenatarika/vex.git
cd vex
cargo build --release
cp target/release/vex ~/.local/bin/

Linux

Pre-built vex ships in every GitHub Release for x86_64-unknown-linux-gnu:

curl -L https://github.com/tenatarika/vex/releases/latest/download/vex-x86_64-unknown-linux-gnu.tar.gz | tar -xz
mv vex ~/.local/bin/      # or: sudo mv vex /usr/local/bin/
vex --version

Built on the current ubuntu-latest GitHub runner (glibc-linked). For older glibc distros, musl-based distros (Alpine, NixOS without nix-ld), or aarch64 Linux (Graviton, Pi 5, Ampere) — build from source via cargo build --release.

Windows

Pre-built vex.exe ships in every GitHub Release.

  1. Download vex-x86_64-pc-windows-msvc.tar.gz from the latest release
  2. Extract vex.exe somewhere stable (e.g. C:\Users\\bin\) — tar -xzf vex-x86_64-pc-windows-msvc.tar.gz from a recent PowerShell, or 7-Zip / WinRAR via right-click. Security note: vex.exe loads the bundled DirectML.dll from its own folder, so on a multi-user machine or shared drive prefer a directory other users can't write to (e.g. C:\Program Files\vex\ — with the trade-off that vex self-update then needs an elevated shell). See [GPUSUPPORT.md §6](docs/GPUSUPPORT.md).
  3. Add that folder to PATH (System Properties → Environment Variables → edit Path → add the folder)
  4. Open a fresh terminal and run vex --version

To update, run vex self-update — it fetches the latest release, picks the right archive for your platform, verifies its signature, and replaces the binary in-place. On Windows it also installs/refreshes the bundled DirectML.dll sidecar (skipped when byte-identical; re-installed if an older self-update dropped it — updaters up to v1.16.0 extracted only the binary). Same command works on macOS and Linux too.

> GPU acceleration is built into the prebuilt binaries — Windows ships with DirectML (any DX12 GPU, driver-only; the redist DirectML.dll is bundled in the archive) and macOS arm64 with CoreML. NVIDIA CUDA is a source-build opt-in. Run vex gpu to check, and see [GPU Acceleration](#gpu-acceleration).

Quick Start

# Index a project (structural only — fast)
vex index --path /path/to/project

# Index with semantic embeddings (slower first time, downloads 86 MB model)
vex index --path /path/to/project --semantic

# Exact-name lookup (does this symbol exist?)
vex check "PaymentService"

# Extract a symbol's body (no whole-file read)
vex show "PaymentService"

# Fuzzy / multi-word search (returns ranked neighbors when no symbol matches)
vex search "payment processing" --semantic

# Find all usages of a symbol (--strict drops string-literal / comment / wrong-scope noise)
vex usages "IndexReader" --strict

# File structure outline
vex outline src/main.rs

# Find implementations of a trait/interface
vex implementations "Iterator"

# Callgraph: who calls / is called by a function (fast path via persistent index)
vex callers "process_event"
vex callees "process_event"

# Multi-hop call graph (v1.7)
vex paths "main" "process_event"          # all caller chains from main → process_event
vex reachable "process_event"             # everything that transitively reaches it
vex tests-for "process_event"             # tests covering process_event (path globs + name heuristic; framework label per row)

# Symbol-level diff against a branch (v1.7)
vex diff --base main                      # what symbols did this branch change?

# Historical view of a symbol — every commit that touched it (v1.15.0; v1.16.0 expanded)
vex index --history                       # build the persistent history sidecar once
vex history "PaymentService"              # ~10ms — every version reachable from HEAD
vex history "PaymentService" --diff       # unified diffs between consecutive versions
vex history "Foo" --since 2026-01-01 --author alice --kind function
vex history "deleted_symbol" --exact-presence    # exact commit set where each blob lived (revert-aware)

# Semantic similarity by existing symbol — explain what's actually similar (v1.7)
vex similar "PaymentService" --limit 5 --min-score 0.7 --explain

# Near-duplicate pairs with reasoning (v1.7)
vex duplicates --min-score 0.95 --min-body-lines 5 --explain

# Search with per-call scope + metadata filters (v1.7)
vex search "Repository" --include 'src/**' --exclude '**/*.gen.*' --visibility public --async-only

# Why did the search return these results? (v1.7)
vex search "Foo" --why 2>trace.json

# Bundle: 4 round-trips → 1 envelope (v1.9, Phase 13.2)
vex bundle --mode symbol --symbol PaymentService          # body + callers + callees + similar
vex bundle --mode pr-impact --base origin/main            # changed symbols + transitive callers + tests
vex bundle --mode project --top-n 30                      # top-N by reverse call-graph indegree

# Diff-context filters on every search-shaped command (v1.9, Phase 13.7-D3)
vex search "Repository" --since-branched                  # only files changed since branching from main
vex usages "Config" --since HEAD~3                        # refs within the last 3 commits
vex callers "Foo" --changed-only                          # working-tree changes only

# Extract just a symbol's body — replaces Read for a specific function/class
vex show "PaymentService"                                 # full body of the class / fn
vex show "Foo" "Bar" "Baz"                                # multiple symbols in one call

# Smart show truncation for token efficiency (v1.9, Phase 13.3)
vex show "BigClass" --signature-only                      # just the signature line
vex show "PaymentService" --head 20                       # first 20 lines of the body
vex show "Foo" --no-body                                  # signature + docstring, no body

# Ranking-eval harness — CI regression guard (v1.9, Phase 13.12)
vex eval --bench benches/ranking_golden/queries.toml      # nDCG@10 / recall@10 / MRR per query
vex eval --min-ndcg 0.85                                  # fail if mean nDCG drops below threshold

# Capability discovery for MCP clients (v1.9, Phase 13.0)
vex capabilities                                          # JSON: protocol_version, signals, bundle_modes, …

# Fast existence check
vex check "Foo" "Bar" "Baz"

# Incremental update (re-parses only changed files, reuses unchanged from index)
vex update

# Watch mode (re-indexes on file changes)
vex watch

# Show index stats
vex status

# GPU doctor — is the compiled EP actually engaging on this machine? (v1.16.0)
vex gpu                                   # probes the compiled-in EP with strict registration
vex gpu cuda                              # narrow to one EP
vex gpu --enable                          # persist working device to VEX_DEVICE

# Shell completions
vex completions zsh > ~/.zfunc/_vex

Commands

| Command | Description | |---------|-------------| | vex index [--path .] [--semantic] [--embedder ID] [--history [--history-depth N]] | Build full index. --semantic generates embeddings + HNSW + BM25. --embedder selects embedding model (default minilm-l6-v2). --history (v1.15.0) builds the Phase 14.8 persistent history-symbol section (/index.git_history) so vex history runs in FST-lookup time. --history-depth N caps the walk at N newest commits (global, not per-file). | | vex search [--semantic] [--no-bm25] [--limit N] [--kind def,fn,…] [--visibility V] [--async-only] [--code-only] [--why] | Hybrid search: structural + BM25 + semantic (when --semantic). 3-way RRF fusion. Multi-value --kind (canonical names + meta-selectors def/comment/test/ref). Metadata post-filters narrow by signature keywords. v1.20.0 (D4): per-result signals block now carries raw bm25_score + semantic_cosine alongside the rank ordinals so agents can read absolute relevance quality; _meta.vex.dev/semantic_channel reports "not_requested" / "index_lacks_vectors" when the semantic channel didn't run; --code-only drops hits in *.md/*.markdown/*.txt/*.rst/*.adoc for code-intent queries. --why appends a JSON trace to stderr. v1.15.0 search-drift hint: when the query is identifier-shaped (compile_query, Foo, _internal) and the structural FST finds zero matches, vex prints a one-line stderr hint pointing at vex check / vex show / vex usages --strict — the typical "imported-from-dependency" case where BM25 would otherwise surfac

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.