An MCP server that combines semantic search (pluggable embeddings + LanceDB) with AST-based code exploration (tree-sitter) for AI agents.
Search your codebase with natural language, browse file structures, inspect symbol outlines, and retrieve exact source code — all through the Model Context Protocol.
MCP tool to enable semantic code search in your project.
ดาว
4
เครื่องมือ
—
อัปไทม์
—
Features
Routed search — identifier / dotted / quoted string → FTS only (never embeds; a miss is empty, not a vector guess). Intent → hybrid FTS + vectors + RRF. Language keywords refused.
Pluggable embeddings — OpenAI (default), Voyage AI (voyage-code-3, best on code), or Ollama (fully local, no internet required)
Optional re-ranking — Voyage rerank-2 or Cohere rerank-v3.5 post-RRF pass for +15-30% top-5 precision
Dependency graph — resolves imports to real file paths, tracks file→file dependencies
Blast radius analysis — BFS traversal to find what would break if you change a file
Architecture boundaries(v4.4) — enforce layer rules (stellaris.boundaries.json) at index time; violations surfaced via get_boundary_violations with zero runtime cost
Doc/spec linking(v4.4) — markdown `backtick-quoted` symbol references are linked to their definitions, queryable via find_doc_references
Context-overflow protection(v4.4) — tier-aware result limits + automatic truncation with _truncated metadata, configured by STELLARIS_CONTEXT_WINDOW (small/medium/large/massive tiers)
Graceful degradation: works without any API key (AST tools still available)
How agents should search
Grep/rg wins on a known name for occurrences. Stellaris wins for intent, ranked definition, and large-file outline/symbol. Do not send every lookup through hybrid search_code.
Need
Tool
Identifier / exact string, definition
search_code (FTS, no vector)
All occurrences, logs, lockfiles, CSS
grep / rg
Intent / name unknown
search_code (hybrid)
File known, ≳150 lines
get_file_outline then get_symbol (one body)
File known, small
Read the file
Identifier miss (skipped_vector: true, empty)
grep / rg — do not retry as intent
Copy the agent skill so this routing is loaded automatically:
Grok:~/.grok/skills/stellaris-explore/SKILL.md or <project>/.grok/skills/stellaris-explore/SKILL.md
Claude Code:~/.claude/skills/stellaris-explore/SKILL.md or <project>/.claude/skills/stellaris-explore/SKILL.md
MCP prompts /nova_explore and /nova_find already follow this contract.
Benchmark: intent / multi-file (not a known identifier)
Tested on a real-world Astro project (341 files, 430 chunks indexed), on intent questions (auth flows, payment, i18n) — not search_code("usePermissions"):
Metric
Without Stellaris
With Stellaris
Improvement
Tool calls (avg)
5.0
1.5
-70%
Full files read (avg)
2.8
0
-100%
Tokens consumed
~12 000
~2 500
-80%
Precision
Variable (noisy grep results)
High (targeted previews)
On a name you already have, grep/rg is cheaper for occurrences. search_code FTS is for the ranked definition (no embedding).
Tools
11 tools are listed by default: search_code, search_docs, get_file_tree, get_file_outline, get_symbol, get_dependencies, get_dependents, get_blast_radius, session_briefing, reindex, reindex_file.
Set STELLARIS_TOOLS=all in the server env to list the other 19 (graph analysis, architecture boundaries, DB schema, usage tracking) and to start the usage scanner. They stay callable either way.
Style and config files (.css, .scss, .less, .json, .yaml, .yml, .toml) are indexed for keyword search only: they are not embedded.
Semantic search (requires an embedding API key, or Ollama locally)
Tool
Description
search_code
Identifier / exact string → FTS only (never embeds; empty = no symbol). Intent → hybrid. Optional path = another indexed project. Returns query_kind, skipped_vector, 1 hit/file, short previews, next hint. Default filter is code extensions; pass extensions for html/css/json.
search_docs
Docs search. Same path contract as search_code / reindex.
reindex
Incremental re-indexing of the project. Builds vector index, FTS index, and dependency graph. Use force=true after switching embedding providers.
reindex_file
Re-index a single file by absolute path. Used by auto-reindex hooks after edits.
Structural exploration (no API calls)
Tool
Description
get_file_tree
Project file tree with language stats.
get_file_outline
List symbols in a file with line ranges + imports, exports, and TODO/FIXME warnings.
get_symbol
Full source code of a specific symbol + surrounding file context (imports, siblings, warnings).
Dependency graph (no API calls)
Tool
Description
get_dependencies
Files that a given file imports. Supports depth parameter for transitive traversal.
get_dependents
Files that import a given file (reverse dependencies).
get_blast_radius
BFS impact analysis: finds all files transitively affected by changes to a file. Returns severity (LOW/MEDIUM/HIGH) and files grouped by depth.
Architecture & documentation (no API calls, STELLARIS_TOOLS=all)
Tool
Description
get_boundary_violations
Returns architecture layer violations detected at index time. Rules are loaded from stellaris.boundaries.json at project root ({ "deny": [{ "from": "src/ui/**", "to": "src/db/**", "reason": "..." }] }). Glob-style patterns. Zero runtime overhead — detection happens during indexing.
find_doc_references
Find markdown/spec files that reference a code symbol or file (via `backtick` identifiers). Useful before renaming or deleting documented code.
Usage tracking (no API calls, STELLARIS_TOOLS=all)
Tool
Description
usage_stats
Token consumption and estimated API cost. Group by model, project, day, cache, anomaly, category, mcp, or core_tool.
usage_dashboard
Launches a local web dashboard (port 8090) with interactive charts, session breakdown, cache analytics, and Breakdown tab.
usage_breakdown
Structured Markdown report: task category breakdown, MCP server breakdown, core tool breakdown. Accepts period parameter.
MCP Prompts
Type /nova in Claude Code to access guided workflows:
Prompt
Description
/nova_explore
Full codebase walkthrough — file_tree → search → outline → symbol
/nova_find
Locate how a feature is implemented (semantic → drill-down)
/nova_file
Deep-dive into a specific file — outline + key symbols
/nova_review
Review recently changed files and assess their blast radius
/nova_usage
Show token consumption stats and open the interactive usage dashboard
Context-aware design
A common pitfall with code search tools is returning results that are too precise — the LLM gets the exact function it asked for, but misses the surrounding context needed to make safe decisions (imports, sibling functions, TODO warnings).
Stellaris addresses this with automatic context enrichment:
get_symbol returns the requested source code plus file-level context by default:
Imports — only the ones the symbol refers to, so the LLM knows where its dependencies come from
Sibling symbols — names and line ranges of other functions/classes in the same file, preventing duplications and revealing patterns
Warnings — TODO, FIXME, HACK, NOTE, @deprecated comments found anywhere in the file
get_file_outline returns symbol names plus the file's imports and exports, so the LLM understands the dependency graph before diving into code.
This adds ~100-200 tokens of "useful noise" per call — far cheaper than reading the entire file (~800-2000 tokens), while preventing blind refactoring errors.
On files ≤150 lines, get_symbol omits file_context (Read the small file instead). The context parameter can be set to false if you only need the raw source.
reindex — index the project for the first time (builds vector, FTS, and graph indexes)
get_file_tree — discover the project structure
Find code — intent → search_code (hybrid). Known identifier definition → search_code (FTS). Occurrences of a known name → grep/rg. Optional path to search another already-indexed project.
get_file_outline — view symbols + imports/exports in a matched large file (Read small files directly)
get_symbol — one body from a large file; follow the next: hint. Do not Read the whole file.
get_dependents — find who imports a file you're about to change
get_blast_radius — get full transitive impact before making changes
get_dependencies — understand what a file relies on
Steps 2, 4, 5, and all graph tools consume zero API tokens.
After the first reindex, a .stellarisrc file is created in the project root with auto_index=true. Subsequent server startups will automatically run incremental indexing (only changed files).
Auto-reindex hook (Grok + Claude Code)
auto_index=true only runs at MCP startup. While a session is open, new/edited files are indexed by a PostToolUse hook.
Grok (automatic).npm install installs ~/.grok/hooks/stellaris-reindex.json when ~/.grok exists and Node 22 (nova-node) is available. It fires after write / search_replace (and Claude aliases Write / Edit), reads the path from hook stdin, and reindexes that file. Re-run:
npm run install-hooks
Then start a new Grok session (or /hooks-list to confirm stellaris-reindex). The hook must run under Node 22 — never PATH Node 26 — because it loads better-sqlite3.
Claude Code (manual). Add this to ~/.claude/settings.json (replace the path):
git clone https://github.com/GDM-Pixel/stellaris-code-search.git
cd stellaris-code-search
npm install
npm run build
Node 22 only (ABI 127). Grok / Nova launch this server with nova-node, not PATH node. This repo has a mise.toml pin. Do not npm rebuild better-sqlite3 under Node 24/26 — it breaks the MCP for every project until you reinstall with Node 22.
# if PATH node is not 22:
/home/charles/.local/bin/nova-node "$(command -v npm)" install
npm run doctor # must print ABI 127
Configuration
Environment variables
Variable
Required
Description
OPENAI_API_KEY
For OpenAI provider (default)
API key for text-embedding-3-small
EMBEDDING_PROVIDER
No (default: openai)
openai | voyage | ollama
VOYAGE_API_KEY
For Voyage provider
API key for voyage-code-3 embeddings
VOYAGE_MODEL
No (default: voyage-code-3)
Override Voyage embedding model
OLLAMA_HOST
No (default: http://localhost:11434)
Ollama base URL
OLLAMA_MODEL
No (default: nomic-embed-text)
Ollama embedding model
RERANK_PROVIDER
No (default: off)
off | voyage | cohere — enables re-ranking
VOYAGE_RERANK_MODEL
No (default: rerank-2)
Voyage re-rank model
COHERE_API_KEY
For Cohere re-ranker
API key for rerank-v3.5
STELLARIS_TOOLS
No (default: 11 core tools)
all lists the 30 tools and the nova_usage / nova_db prompts, and starts the usage scanner
STELLARIS_CONTEXT_WINDOW
No (default: 128000)
Calling LLM's context window in tokens. Drives tier-based result limits and truncation thresholds: small (<50K), medium (50–150K), large (150–500K), massive (>500K).
The server and the per-edit hook read DOTENV_CONFIG_PATH, then the .env of the working directory, then the .env next to the install: one .env in the Stellaris folder is enough for every project.
Without any embedding API key (and no Ollama), the server starts normally — get_file_tree, get_file_outline, and get_symbol work without it.
Switching embedding providers
If you change EMBEDDING_PROVIDER on an existing index, Stellaris will refuse to run an incremental reindex (to avoid silently corrupting the vector store). Run:
# Force-rebuild the index with the new provider
reindex force=true
This deletes the old LanceDB table and meta.json, then rebuilds from scratch.
Place at the project root to enforce architecture layer rules at index time. Any depends_on edge that matches a deny rule is flagged as a boundary violation and surfaced through get_boundary_violations. Detection happens during reindex — there is no runtime cost.
{
"deny": [
{
"name": "ui-never-imports-db",
"from": "src/ui/**",
"to": "src/db/**",
"reason": "UI layer must go through services, not DB directly"
},
{
"from": "src/domain/**",
"to": "src/infrastructure/**",
"reason": "Hexagonal architecture: domain must stay infrastructure-agnostic"
}
]
}
Glob syntax: ** matches any depth, * matches one path segment, ? matches one character. Paths are relative to project root, forward slashes.
.stellarisrc (auto-generated)
Created automatically after the first successful reindex. Controls auto-indexing and embedding configuration.
# Stellaris Code Search configuration
auto_index=true
# Embedding provider (openai | voyage | ollama) — default: openai
# embedding_provider=voyage
# embedding_model=voyage-code-3
# Re-ranking (off | voyage | cohere) — default: off
# rerank_provider=voyage
# Import-alias overrides (safety net if auto-detection from
# tsconfig paths / vite resolve.alias fails). Path is relative
# to the project root.
# alias.@=src
# alias.#utils=src/lib/utils
You can toggle auto_index via the reindex tool (enable_auto_index: false) or edit the file manually.
Import alias resolution. The dependency graph auto-detects path aliases from the tsconfig.json/jsconfig.json nearest each source file (following extends, including monorepo subdirectories), falling back to vite.config.*resolve.alias. The @/ and ~/ conventions resolve to the nearest src/ automatically. Use the alias.<name>=<path> lines above only as an override when auto-detection can't find your config.
.vectorignore (optional)
Same syntax as .gitignore, to exclude files from indexing.
Security
Stellaris never indexes sensitive files. Two layers of protection ensure secrets are never sent to OpenAI:
Glob exclusions (DEFAULT_EXCLUDE) — files matching these patterns are never scanned:
.env*, secrets.*, credentials.*
*.pem, *.key, *.cert, *.p12, *.pfx, *.keystore
Ignore filter (defense in depth) — same patterns applied via the ignore library during file scanning, as a second safety net.
Additionally, .gitignore and .vectorignore rules are always respected.
This directory is automatically excluded from scanning.
Usage data is stored globally in ~/.claude/usage.db (SQLite). Data older than 180 days is automatically purged at startup. The dashboard shows the last 90 days.
At every startup, an integrity check runs automatically:
Orphaned chunks (in LanceDB/FTS/graph but absent from meta.json) are purged from all 3 stores
Stale meta.json entries (source file deleted from disk) are removed so the next reindex handles them correctly
Development
npm run dev # Run with tsx (hot reload)
npm run build # Compile TypeScript
npm run watch # Watch mode compilation
npm test # All test files (Node 22)
Native addons (better-sqlite3, LanceDB, tree-sitter) are built for Node 22: run npm install, npm run build and npm test under Node 22 (mise exec -- in this repo).
Maintenance scripts
The server repairs an index at startup (integrity check, then incremental reindex). These scripts do the same for a list of projects, without opening a session in each:
Script
What it does
scripts/check-integrity.ts [--reindex] <root>...
Purge chunks no file owns, forget half-indexed files, optionally reindex
scripts/repair-zero-vectors.ts <root>...
Re-embed chunks stored without a vector by versions before 4.9.1
scripts/rebuild-graph.ts <root>...
Rebuild the dependency graph from the files (no embedding call)
scripts/purge-lance-indexes.ts <dir>...
Drop old LanceDB versions in every index under the directories
scripts/eval-search.ts <root>
Relevance check against <root>/.vectors/eval.json (top-1, top-5, MRR)
Run them with npx tsx. eval.json is a list of { "q": "question", "expect": "part of the file path" }.