About
MCP (Model Context Protocol) server for Veles code search
README
Veles
Crates.io Crates.io docs.rs License: MIT
Fast, hybrid (BM25 + semantic) local code search for AI agents and humans, written in pure Rust.
Veles runs entirely on CPU — no GPU, no transformer forward pass at query time. Queries return in tens of milliseconds against a persistent on-disk index, with tree-sitter-aware symbol lookups, pipe-friendly output formats, and built-in MCP / gRPC servers for integration with Claude, Cursor, or anything else that speaks JSON-RPC. Static embeddings come from the potion family via model2vec-rs.
Originally inspired by Semble — Veles started as a Rust port of the same hybrid retrieval recipe and has grown to add persistent + incremental indexing, tree-sitter symbols / defs / refs, six pipe-friendly output formats, glob/language filters, gRPC, and shell completions.
veles tui — live hybrid search, ~10ms per keystroke.
Interfaces
- CLI —
veles search "query" ./my-repo - MCP server — stdio JSON-RPC for AI agent integration (Claude, Cursor, etc.)
- gRPC — tonic-based service with
Index,Search,FindRelated,GetStatsRPCs
Features
- Persistent index under
<repo>/.veles/— searches reuse the cache and finish in tens of milliseconds. Incrementalupdatekeeps embeddings of unchanged files. - Hybrid search with Reciprocal Rank Fusion (RRF) blending BM25 and semantic scores
- Tree-sitter symbol commands —
symbols/defs/refsfor Rust, Python, JavaScript, TypeScript, Go - Identifier-aware tokenizer — splits camelCase, snake_case, and mixed-script names
- Query-type detection — symbol queries lean BM25, natural language leans semantic
- Definition boosting — promotes chunks that define the queried symbol
- Path penalties — demotes test files, compat dirs, re-export files
- File saturation — avoids stacking all results from one file
- Scope labels on every hit — search/related/refs results carry a tree-sitter-derived
defines `Foo`orin `bar`suffix so the result header alone tells you what each chunk is - Multilingual model option for Cyrillic, CJK, Arabic, etc.
- Pipe-friendly output —
pretty,compact,ripgrep,paths,json,jsonl - Filter flags —
--lang,--pathand--excludeglob patterns,--min-score - Prebuilt binaries for macOS (Intel/ARM), Linux x86_64/ARM64 (musl), Windows x86_64
Install
# Linux / macOS — prebuilt binary (one-liner)
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/julymetodiev/Veles/releases/latest/download/veles-cli-installer.sh | sh
# Windows — PowerShell
irm https://github.com/julymetodiev/Veles/releases/latest/download/veles-cli-installer.ps1 | iex
# Homebrew (macOS / Linux)
brew install julymetodiev/tap/veles-cli
# From crates.io (compiles locally; no protoc / extra deps needed)
cargo install veles-cli
# Manual download
gh release download --repo julymetodiev/Veles --pattern '*linux-gnu*' # or browse
# https://github.com/julymetodiev/Veles/releases/latest
# Verify (optional)
veles --version # → veles 0.6.0
See INSTALL.md for SHA-256 verification and other install paths.
Quickstart
veles index . # one-off, builds .veles/
veles search "parse config file" # auto-loads the cache
veles update . # refresh after edits
The first search downloads the embedding model from Hugging Face (~64 MB, cached at ~/.cache/huggingface/hub/).
Most-used commands
Search
veles search "rate limiting" # hybrid (default)
veles search "rate limiting" -t 10 -f compact # 10 results, 1 line each
veles search "rate limiting" -f rg # ripgrep-style path:line:content
veles search "rate limiting" -f json | jq '.results' # structured for scripting
veles search "rate limiting" -f paths | xargs $EDITOR # open every matching file
veles search "TokenStream" -m bm25 # exact identifier
veles search "auth flow" -m semantic # fuzzy concept
veles search "auth" -l rust,python # language filter
veles search "X" -g 'src/**/*.rs' -x 'src/legacy/**' # glob include / exclude
veles search "BM25" --min-score 0.4 # drop weak hits
Symbols (tree-sitter)
veles symbols crates/veles-core/src/persist.rs # outline a single file
veles defs Manifest # every definition named "Manifest"
veles defs save -k function -l rust # filter by kind + language
veles refs save_index -t 30 # defs + BM25 references
Related code
veles find-related src/main.rs 42 # semantically similar chunks
veles find-related src/main.rs 42 -l rust # restrict to one language
veles find-related src/main.rs 42 -g 'crates/foo/**' # restrict to a subtree
Index lifecycle
veles index . # bootstrap
veles index . --force # rebuild from scratch
veles update . # incremental refresh
veles status . # manifest + drift
veles clean . # remove .veles/
Interactive TUI
veles tui # live hybrid search with preview pane
veles tui ./my-repo # against another repo
veles tui --debug-keys # echo every keypress (terminal diagnostic)
Loads the persistent index once, then debounces queries so each keystroke re-runs in tens of milliseconds. Highlights:
- Search —
↑↓navigate,Tabcycleshybrid/bm25/semantic. - Lookups —
Ctrl-Ddefs,Ctrl-Frefs,Ctrl-Rsemantically related. With an empty query, Ctrl-D / Ctrl-F use the selected row's symbol. - History —
Ctrl-B/Ctrl-X(alsoF2/F3,Alt-←/→,Alt-h/l) jump back and forward across past views — like a browser. - Query recall —
Ctrl-↑/Ctrl-↓(alsoAlt-P/Alt-N) walk past queries, recorded at Enter, Ctrl-O, Ctrl-R/D/F, and Ctrl-U. - Filters —
Ctrl-Tcycles language filter through the indexed languages,Ctrl-Yopens a path-glob input. Both pass through to every dispatch (search, related, defs, refs). - Preview —
Shift-↑↓/Shift-PgUp/PgDnscroll within the chunk;F5–F8are non-modifier fallbacks for terminals that swallow Shift+Arrow. - Open —
Enterprintspath:lineto stdout ($EDITOR $(veles tui)works),Ctrl-Ospawns$EDITORin-place and returns to the TUI on exit. Editor heuristic covers vim / nvim / emacs / nano / VS Code / Cursor / Windsurf / Helix; set$EDITOR=vim(or$VISUAL) to pick. - Help —
?(when the query is empty) opens a scrollable keybinding overlay;Ctrl-Gcancels an in-flight search (readline convention);Esc/Ctrl-Cquit.
Servers
veles serve-mcp # MCP over stdio (default if no args)
veles serve-grpc --addr "[::1]:50051" # gRPC
Shell integration
mkdir -p ~/.zfunc ~/.local/share/man/man1
veles completions zsh > ~/.zfunc/_veles
veles man --out-dir ~/.local/share/man/man1
veles man --out-dir DIR writes one page per subcommand (veles.1,
veles-search.1, veles-defs.1, …) so man veles-search works the
same way as man git-commit.
Then once in ~/.zshrc:
fpath=(~/.zfunc $fpath)
autoload -Uz compinit && compinit
export MANPATH="$HOME/.local/share/man:$MANPATH"
Remote repos
veles search "BM25 inverted index" https://github.com/julymetodiev/Veles
See USAGE.md for the full reference, recipes (fzf, vim quickfix, jq), and troubleshooting.
MCP server
veles serve-mcp # explicit
veles # equivalent — bare `veles` starts MCP when stdin is piped
Exposed tools:
| Tool | Use it for |
|---|---|
search |
Hybrid / BM25 / semantic query, with optional lang / path / exclude / min_score. |
defs |
Tree-sitter definitions for an exact symbol name (Rust, Python, JS, TS, Go). |
refs |
Definitions plus BM25 hits — "where is X defined and where is X used", in one call. |
find_related |
Semantically similar chunks for a (file_path, line) from an earlier search. |
list_symbols |
Every tree-sitter definition across the index, with kind / lang / path filters. |
symbols |
Outline of a single file — every definition it contains. |
scope_at |
Innermost tree-sitter symbol containing a given file:line. |
files |
Distinct file paths in the index, with lang / path / exclude filters. |
read |
Line range from an indexed file (capped at 500 lines, repo-relative paths only). |
stats |
File / chunk counts, model metadata, per-language chunk breakdown. |
status |
Non-mutating drift check vs. persisted manifest; distinguishes content edits from bare touch. |
update |
Incremental refresh of a local repo's .veles/ index after edits (BLAKE3-aware). |
search, find_related, and refs accept a format argument:
default(default) — scored, fenced code blocks tagged with the enclosing scope.paths— flat per-line list.search/find_relatedemitpath:start-end;refsemitspath:lineper word-boundary occurrence of the symbol.unique_paths— collapsed to onepathline per file. For agent shortlist workflows that just want "which files matter".
Build from source
cargo build --release
tonic-build ships a vendored protoc via protoc-bin-vendored, so no system-wide protobuf compiler is required.
Embedding in your own Rust project
The workspace publishes four crates on crates.io — pick the layer you need:
| Crate | Purpose |
|---|---|
| veles-core | Indexing, chunking, BM25, dense search, hybrid ranking, persistence. |
| veles-grpc | tonic-based gRPC service wrapping veles-core. |
| veles-mcp | MCP / JSON-RPC server (stdio) for AI-agent integration. |
| veles-cli | The veles binary. |
Full API docs are on docs.rs.
[dependencies]
veles-core = "0.2"
use std::path::Path;
use veles_core::{SearchMode, VelesIndex};
let index = VelesIndex::from_path(Path::new("."), None, None, false)?;
let results = index.search("parse config", 5, SearchMode::Hybrid, None, None, None);
for r in results {
println!("{} [{:.3}]", r.chunk.location(), r.score);
}
# Ok::<(), anyhow::Error>(())
Architecture
Veles/
crates/
veles-core/ indexing, chunking, BM25, dense search, ranking, symbols
veles-grpc/ gRPC service (tonic + prost)
proto/
veles.proto gRPC schema
veles-mcp/ MCP server over stdio
veles-cli/ CLI binary
The persistent index lives under <repo>/.veles/:
.veles/
manifest.json # model, dim, per-file (size, mtime, chunk_count)
chunks.bin # bincode Vec<Chunk>
bm25.bin # bincode BM25 inverted index
dense.bin # bincode dense matrix
symbols.bin # bincode tree-sitter symbols
update reuses embeddings of files whose (size, mtime) fingerprint hasn't changed, so refreshing after a small edit is near-instant on large repos.
License
MIT
Installing Veles
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/julymetodiev/VelesFAQ
Is Veles MCP free?
Yes, Veles MCP is free — one-click install via Unyly at no cost.
Does Veles need an API key?
No, Veles runs without API keys or environment variables.
Is Veles hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Veles in Claude Desktop, Claude Code or Cursor?
Open Veles on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Veles with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
