Local-first semantic search for your codebase via MCP (Model Context Protocol)
A personal cognitive weapon that lets GitHub Copilot (or any MCP-compatible LLM) search your entire codebase semantically β without uploading a single file to the cloud.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR CODEBASE (Local) β
β *.ts, *.tsx, *.js, *.py, *.md, *.json, *.yaml, *.sql β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β chokidar (file watcher)
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β INDEXER (on-save) β
β 1. Read file β 2. Smart chunk β 3. Embed β 4. Store β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β LANCEDB (.rag_index/) β
β Embedded vector store (SQLite-backed, zero-config) β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MCP SERVER (stdio) β
β Tool: search_codebase(query) β top-7 chunks β
ββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β VS CODE + COPILOT β
β Asks questions β Gets grounded answers β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Component | Role | Tool Used |
|---|---|---|
| Librarian | Generates embeddings (dumb but fast) | Ollama + nomic-embed-text |
| Memory | Stores vectors locally | LanceDB |
| Translator | Exposes search_codebase tool to LLMs | MCP Server |
| Brain | Answers questions using retrieved context | Copilot/Claude/GPT |
- Node.js 20+ -
node --version - Ollama - Install Ollama
- Embedding model - Run:
ollama pull nomic-embed-text
git clone <this-repo>
cd CodebaseRAG
npm installAdd a workspace-scoped config at .vscode/mcp.json:
{
"servers": {
"CodebaseRAG": {
"type": "stdio",
"command": "npx",
"args": [
"tsx",
"C:/path/to/CodebaseRAG/server.ts"
],
"env": {
"RAG_PROJECT_ROOT": "${workspaceFolder}"
}
}
}
}Note: The server prefers MCP-provided workspace roots. The env override is a fallback.
# Specify project root explicitly
npx tsx server.ts --root /path/to/project
# Or via environment variable
RAG_PROJECT_ROOT=/path/to/project npx tsx server.ts
# Force reset (wipe and rebuild index)
npx tsx server.ts --root /path/to/project --reset
# Or via environment variable
RAG_RESET=true RAG_PROJECT_ROOT=/path/to/project npx tsx server.ts- Open any workspace
- Ask Copilot: "How does authentication work in this repo?"
- Copilot will invoke
search_codebaseand answer using actual code
- Workspace root comes from MCP (preferred)
- Explicit overrides supported via
--rootorRAG_PROJECT_ROOT process.cwd()is NEVER trusted blindly- Initialization fails if no safe root is provided
Automatically blocks dangerous roots:
/,C:\,D:\(drive roots)/home,/Users,C:\Users(user directories)- Home directory and common subfolders
Never indexed, even if inside project:
node_modules/,.git/,dist/,build/.next/,.turbo/,.cache/- The vector DB directory itself (
.rag_index/) - Binary files, symlinks (not followed)
- MCP handshake completes
- Resolves workspace root (MCP roots β explicit override)
- Validates root (exists, not dangerous)
- Checks for reset flag
- Initializes LanceDB
- Scans and indexes scoped project
- Starts file watcher
- File watcher detects change
- Deletes old vectors for that file
- Re-embeds only the changed file
- Updates the vector store
- Embeds your natural language query
- Performs vector similarity search
- Returns top 7 most relevant code chunks
- Code files (.ts, .js, .py): Splits by function/class boundaries
- Prose files (.md, .json): Splits by paragraphs/sections
- Chunk size: 50-2000 characters (optimal for embedding quality)
*.ts, *.tsx, *.js, *.jsx, *.py, *.md, *.json, *.yaml, *.yml, *.sql, *.sh, *.css, *.html
node_modules/, dist/, build/, out/, .git/, .next/, .turbo/, .cache/,
__pycache__/, *.lock, *.min.js, *.min.css, .env*, *.log, coverage/
| Resource | Estimate |
|---|---|
| RAM | ~200-400MB (Ollama) + ~50MB (Node process) |
| Disk | ~1-5MB per 1000 files (LanceDB) |
| CPU | Minimal idle; spikes during indexing |
| Latency | <300ms per query (local) |
search_codebase(query: string): stringInput:
query: Natural language question or code snippet
Output:
- Top 7 relevant code chunks with file paths
"How does the user authentication flow work?"
"Where is the database connection configured?"
"Find all API error handlers"
"What environment variables are used?"
"Show me the UserService class"
# Option 1: CLI flag
npx tsx server.ts --root /path/to/project --reset
# Option 2: Environment variable
RAG_RESET=true npx tsx server.ts --root /path/to/project
# Option 3: Manual deletion
rm -rf /path/to/project/.rag_indexYou must provide an explicit root:
npx tsx server.ts --root /path/to/projectThe path you specified is too broad (e.g., C:\ or home directory). Specify a specific project folder.
# Ensure Ollama is running
ollama serve# Pull the embedding model
ollama pull nomic-embed-text- Check if
.rag_index/folder exists in your project - Run with
--resetto rebuild the index - Try more specific queries
CodebaseRAG/
βββ server.ts # MCP server + indexer
βββ package.json # Dependencies
βββ tsconfig.json # TypeScript config
βββ README.md # This file
βββ .gitignore # Ignore rules
In your project:
your-project/
βββ .rag_index/ # LanceDB storage (auto-created)
βββ ... your code ...
This system is COMPLETE when:
- Project root explicitly required (no blind cwd trust)
- Dangerous paths blocked automatically
- Reset mechanism via --reset or RAG_RESET
- File watcher scoped to project only
- Symlinks not followed
- DB directory ignored by watcher
- Startup logs resolved root and file count
- RAM under 500MB
- Query latency under 300ms
No UI. No auth. No cloud. No complexity.
Just you, your code, and an LLM that actually knows what's in your repo.