High-Performance Legal & Code Intelligence for the Terminal.
A "Native & Lean" implementation of a Retrieval-Augmented Generation (RAG) server written in Rust. This server exposes high-precision search logic via the Model Context Protocol (MCP), specifically optimized for Fedora 44 and Intel iGPU (Vulkan) hardware.
By bypassing the "PCIe dinosaur" and utilizing Unified Memory Architecture (UMA), this server provides the lightning-fast "memory" required for autonomous agents like Goose and Aider.
The Rust RAG server is not an HTTP server. It communicates via:
| Mode | Protocol | Description |
|---|---|---|
| MCP Server Mode | STDIO | Started as a subprocess by Goose (or any MCP client). Uses stdin/stdout for JSON‑RPC messages. |
| CLI Mode | Command‑line | Run directly from the terminal with subcommands (e.g., query, ingest-file). |
HTTP is only used internally – the RAG server makes outgoing HTTP requests to local services:
- BGE-M3 Embedding (port 11435)
- Reranker (port 11436/11437)
- Local LLM for query expansion (port 11434)
Agentgateway is an HTTP proxy that handles cloud LLM access (port 4000), but the RAG server never serves HTTP – it only consumes.
The server communicates directly with local Vulkan-accelerated engines over native STDIO pipes, ensuring 0% data leakage and minimum latency.
graph TD
A[Goose / Aider / CLI] -->|STDIO| B(Rust RAG Server)
B -->|HTTP| C[LLM Server :11434]
B -->|HTTP| D[BGE-M3 :11435]
B -->|HTTP| E[Reranker :11436/11437]
B -->|Dynamic Loading| F[vec0.so Extension]
F <--> G[(SQLite-Vec DB)]
B -->|FTS5| H[(BM25 Index)]
B -->|Cache| I[(Query Cache)]
J[Agentgateway :4000] -.->|HTTP Proxy| C
J -.->|HTTP Proxy| D
J -.->|HTTP Proxy| E
Explanation:
- LLM Server (port 11434): Used for query expansion – generating synonyms and related terms to improve recall on broad queries.
- BGE-M3 (port 11435): Generates high-quality multilingual embeddings for semantic search.
- Reranker (port 11436/11437): Cross-encoder models for precision reranking (BGE for Swedish, Mxbai for English).
- SQLite-Vec + FTS5: Vector search + BM25 keyword search in the same database.
- Query Cache: In‑memory cache with 5‑minute TTL for repeated queries.
- Agentgateway (port 4000): Optional HTTP proxy that can route to local or cloud models; not required for the RAG server to function.
Note: The RAG server makes outgoing HTTP calls to the LLM, embedding, and reranker services. It does not accept incoming HTTP requests. All MCP communication with Goose is via STDIO.
Ensure you have the Rust toolchain and the specialized vec0 extension for SQLite.
# Install system dependencies
sudo dnf install -y sqlite-devel poppler-utils
# Download the specific vec0.so (v0.1.9+)
mkdir -p ~/.config/rag-server/extensions
cd /tmp
curl -L -O https://github.com/asg017/sqlite-vec/releases/download/v0.1.9/sqlite-vec-0.1.9-loadable-linux-x86_64.tar.gz
tar -xvf sqlite-vec-0.1.9-loadable-linux-x86_64.tar.gz
mv vec0.so ~/.config/rag-server/extensions/Download the BGE-M3 metadata required for exact tokenization.
wget https://huggingface.co/BAAI/bge-m3/resolve/main/tokenizer.json -O ~/.config/rag-server/tokenizer.jsoncd ~/.config/rag-server
cargo build --releaseIf you have an existing database, add FTS5 support for BM25 keyword search:
sqlite3 ~/.config/rag-server/vectors.db "INSERT OR IGNORE INTO docs_fts(rowid, id, collection, text) SELECT rowid, id, collection, text FROM docs;"The server defaults to optimized values for a 16GB U-series workstation but can be overridden via environment variables.
Create a dedicated environment file for your RAG configuration:
# ~/.config/rag-server/env
# RAG Server Environment Variables
# Embedding model
export RAG_EMBED_MODEL="local-llama-server-embed"
# Reranker model (primary or secondary)
export RAG_RERANK_MODEL="local-llama-server-rerank"
# Reranker URL (derived from RAG_RERANK_MODEL)
case "$RAG_RERANK_MODEL" in
local-llama-server-rerank)
export RAG_RERANK_URL="http://127.0.0.1:11436/rerank"
;;
local-llama-server-rerank-2)
export RAG_RERANK_URL="http://127.0.0.1:11437/rerank"
;;
*)
export RAG_RERANK_URL="http://127.0.0.1:11436/rerank" # Fallback
;;
esac
# Reranking settings
export RAG_RERANK_CANDIDATES=10
export RAG_RERANK_MIN_CANDIDATES=3
# Concurrency settings
export RAG_MAX_CONCURRENT=4
export RAG_MAX_CONCURRENT_REQUESTS=4
# Caching
export RAG_CACHE_TTL=300
# Database path
export RAG_DB_PATH="$HOME/.config/rag-server/vectors.db"| Variable | Default Value | Description |
|---|---|---|
SQLITE_VEC_PATH |
~/.config/rag-server/extensions/vec0.so |
Path to the vector extension. |
RAG_DB_PATH |
~/.config/rag-server/vectors.db |
Path to the local Knowledge Base. |
RAG_TOKENIZER_PATH |
~/.config/rag-server/tokenizer.json |
BGE-M3 BPE dictionary. |
RAG_EMBED_URL |
http://localhost:11435/v1/embeddings |
HTTP endpoint for embedding server. |
RAG_RERANK_URL |
http://localhost:11436/rerank |
HTTP endpoint for reranker server (primary). |
RAG_LLM_URL |
http://localhost:11434/v1/chat/completions |
HTTP endpoint for LLM query expansion. |
RAG_CHUNK_SIZE |
1024 (Legal) / 3000 (Code) |
Max tokens per segment. |
RAG_CHUNK_OVERLAP |
150 (Legal) / 400 (Code) |
Token overlap for context. |
RAG_EMBED_MODEL |
bge-m3 |
Model name sent to the embedder. |
RAG_RERANK_MODEL |
bge-reranker-v2-m3 |
Model name sent to the reranker. |
RAG_RERANK_MIN_SCORE |
0.3 |
Minimum relevance score to keep. |
RAG_MAX_CONCURRENT_FILES |
4 |
Parallelism when ingesting directories. |
RAG_BATCH_SIZE |
8 |
Embedding batch size for API requests. |
RAG_RERANK_CANDIDATES |
10 |
Number of candidates for reranking. |
RAG_MAX_CONCURRENT_REQUESTS |
4 |
Maximum parallel HTTP requests for embeddings. |
RAG_RERANK_MIN_CANDIDATES |
3 |
Skip reranking if fewer candidates (adaptive). |
RAG_CACHE_TTL |
300 |
Query cache TTL in seconds. |
Set these in your ~/.zshenv for all sessions:
# ~/.zshenv
export OPENAI_API_KEY="sk-unused"
export OPENAI_BASE_URL="http://localhost:4000/v1"
export OPENAI_TIMEOUT=7200
export SQLITE_VEC_PATH="$HOME/.config/rag-server/extensions/vec0.so"Integrate the server as a stdio extension:
extensions:
rag:
enabled: true
name: rag
type: stdio
cmd: /home/bfrost/.config/rag-server/target/release/rag-server
env:
SQLITE_VEC_PATH: /home/bfrost/.config/rag-server/extensions/vec0.so
timeout: 7200Note: The RAG server reads all
RAG_*environment variables. These can be set in~/.config/rag-server/envand sourced in your session.
Configure your ~/.zshrc with these aliases for seamless reranker switching:
# ~/.zshrc
_ensure_agentgateway() {
if ! ss -tulpn | grep -q ":4000 "; then
echo "🚀 Starting Agentgateway..."
agentgateway -f ~/.config/agentgateway/config.yaml > /dev/null 2>&1 &
local count=0
while ! ss -tulpn | grep -q ":4000 "; do
if [ $count -gt 10 ]; then
echo "❌ Fel: Agentgateway hann inte starta."
return 1
fi
sleep 1
((count++))
done
fi
}
_goose_session() {
local model="${1:-local-llama-server}"
local embed="${2}" # No default; let ~/.config/rag-server/env handle it
local rerank="${3}" # No default; let ~/.config/rag-server/env handle it
_ensure_agentgateway || return 1
# Source RAG environment variables (sets defaults)
source ~/.config/rag-server/env
# Override RAG_EMBED_MODEL and RAG_RERANK_MODEL if provided
if [ -n "$embed" ]; then
export RAG_EMBED_MODEL="$embed"
fi
if [ -n "$rerank" ]; then
export RAG_RERANK_MODEL="$rerank"
# Reload RAG_RERANK_URL from env file
unset RAG_RERANK_URL
source ~/.config/rag-server/env
fi
GOOSE_MODEL="$model" goose session
}
# ==============================================================================
# --- 1. SWEDISH STACK (Primary BGE Reranker on Port 11436) ---
# ==============================================================================
alias goose-local='_goose_session local-llama-server'
alias goose-deepseek='_goose_session local-llama-server'
alias goose-qwen-coder='_goose_session local-llama-server'
alias goose-phi='_goose_session local-llama-server'
alias goose-mistral='_goose_session mistral-large-latest'
alias goose-codestral='_goose_session codestral-latest'
alias goose-gemini='_goose_session gemini-3.5-flash'
# ==============================================================================
# --- 2. ENGLISH STACK (Mxbai Reranker on Port 11437) ---
# ==============================================================================
alias goose-local-en='_goose_session local-llama-server "" local-llama-server-rerank-2'
alias goose-deepseek-en='_goose_session local-llama-server "" local-llama-server-rerank-2'
alias goose-qwen-coder-en='_goose_session local-llama-server "" local-llama-server-rerank-2'
alias goose-phi-en='_goose_session local-llama-server "" local-llama-server-rerank-2'
alias goose-mistral-en='_goose_session mistral-large-latest "" local-llama-server-rerank-2'
alias goose-codestral-en='_goose_session codestral-latest "" local-llama-server-rerank-2'
alias goose-gemini-en='_goose_session gemini-3.5-flash "" local-llama-server-rerank-2'create_collection– Initializes a new KB (e.g.,juridikorrust-src).ingest_file– Chunks, tokenizes, and indexes a file via the iGPU.ingest_directory– Bulk‑ingests all matching files in a directory with parallel processing.add_documents– Indexes raw text strings directly from JSON.query– Performs hybrid semantic + BM25 keyword search with reranking for 97% citation accuracy.list_collections– Displays all local libraries and document counts.delete_documents– Deletes one or more documents from a collection.delete_collection– Removes an entire collection and all its data.clear_cache– Clears the in‑memory query cache.
The same binary acts as a full‑featured command‑line tool. Run it without arguments to start the MCP server (stdin/stdout). Run it with a subcommand to perform operations directly.
./target/release/rag-server --help./target/release/rag-server query --help# Create a new collection
./target/release/rag-server create-collection --name juridik
# List all collections
./target/release/rag-server list-collections
# Delete a collection
./target/release/rag-server delete-collection --name juridik# Ingest a single file (standard)
./target/release/rag-server ingest-file --collection juridik --file-path ~/dokument/lag.pdf
# Ingest with pipeline optimization (faster for large documents)
./target/release/rag-server ingest-file --collection juridik --file-path ~/dokument/lag.pdf --pipeline
# Ingest all .txt and .pdf files in a directory
./target/release/rag-server ingest-directory --collection juridik --directory-path ~/dokument/ --extensions txt,pdf
# Force re-indexing
./target/release/rag-server ingest-file --collection juridik --file-path ~/dokument/lag.pdf --force# Semantic search (vector only)
./target/release/rag-server query --collection juridik --query "vad är regeringsformen?" --top-k 3
# Hybrid search (BM25 + vector)
./target/release/rag-server query --collection juridik --query "tolkningsregler" --hybrid
# Hybrid search with custom weights (more BM25 weight)
./target/release/rag-server query --collection juridik --query "tolkningsregler" --hybrid --vector-weight 0.4 --bm25-weight 0.6
# Specify reranker URL per query
./target/release/rag-server query --collection juridik --query "constitutional law" --rerank-url http://127.0.0.1:11437/rerank
# Bypass cache (force fresh search)
./target/release/rag-server query --collection juridik --query "tolkningsregler" --hybrid --no-cache# Clear the query cache
./target/release/rag-server clear-cache{
"name": "query",
"description": "Sök i samlingen med hybrid search (BM25 + vector) och reranking",
"inputSchema": {
"type": "object",
"properties": {
"collection": { "type": "string" },
"query": { "type": "string" },
"top_k": { "type": "integer", "default": 5 },
"rerank_url": {
"type": "string",
"description": "Valfri reranker-URL (e.g., http://127.0.0.1:11437/rerank)"
},
"hybrid": {
"type": "boolean",
"description": "Använd hybrid search (BM25 + vector)",
"default": false
},
"vector_weight": {
"type": "number",
"description": "Vikt för vektorscore (0-1)",
"default": 0.7
},
"bm25_weight": {
"type": "number",
"description": "Vikt för BM25-score (0-1)",
"default": 0.3
},
"no_cache": {
"type": "boolean",
"description": "Bypass cache",
"default": false
}
},
"required": ["collection", "query"]
}
}By utilizing Quantization-Aware Training (QAT-UD) and N-Gram software speculation, this Rust implementation delivers:
- 800% Speedup: Indexing 700 project chunks reduced from 45+ mins (CPU) to ~5 mins (iGPU).
- 20–30% Faster Ingestion: The new pipeline (
--pipeline) overlaps chunk generation and embedding, reducing total time. - 100% Speedup on Repeated Queries: Query cache serves identical queries instantly.
- Linguistic Precision: Handles Swedish legal nuances and complex Rust traits without semantic drift.
- Zero Leakage: 100% of data remains on local silicon.
- Hybrid Search Recall: BM25 + vector search significantly improves recall for both exact keywords and semantic concepts.
Comprehensive testing with real legal documents validated all core features:
| Test | Result |
|---|---|
| ✅ Collection Management | Create, list, delete |
| ✅ Single File Ingestion | 7,686-line file → 96 segments in 13 min |
| ✅ Pipeline Ingestion | Faster, reliable with large documents |
| ✅ Directory Bulk Ingestion | 3 files → 15 segments |
| ✅ Mixed Content (TXT + PDF) | 33+ segments |
| ✅ Semantic Search | Exact citation retrieval with 97% accuracy |
| ✅ Hybrid Search (BM25 + Vector) | Improved recall for keyword-heavy queries |
| ✅ Reranker Switching | BGE (Swedish) ↔ Mxbai (English) seamless |
| ✅ Query Expansion | LLM-based synonym generation |
| ✅ Query Cache | Instant response on repeated queries |
| ✅ Document/Collection Deletion | Clean removal |
All critical tests passed. The server is production-ready for legal, codebase, and technical QA deployments.
- Pipeline Ingestion: New
--pipelineflag for overlapping chunking and embedding. - Query Cache: In‑memory cache (5 min TTL) for repeated query results; added
--no-cacheandclear-cachecommand. - Parallel Embedding: Concurrent HTTP requests for embedding generation (configurable with
RAG_MAX_CONCURRENT_REQUESTS). - Parallel Chunking: Automatic parallel processing for documents with >500 sentences.
- Adaptive Reranking: Skips reranking if fewer candidates than
RAG_RERANK_MIN_CANDIDATES(default 3). - Connection Pooling: Reuses HTTP connections for better performance.
- Environment Management: Added dedicated
~/.config/rag-server/envfile for cleaner configuration.
- Initial Rust port with BGE-M3 embeddings and BGE-Reranker-v2-M3.
- Hybrid search (BM25 + vector) and per-query reranker selection.
The project is continuously built, tested, and published via GitHub Actions.
| Stage | Description |
|---|---|
| Build & Push | Multi‑stage Containerfile based on Debian Bookworm (OpenSSL 3). Builds the Rust binary in a container and pushes to GHCR. |
| Smoke Tests | Runs basic CLI commands (--help, query --help, etc.) to verify the image works. |
| Cleanup | Weekly (Sundays 03:00) cleanup of old images – keeps the 5 latest versions, deletes untagged images. |
The container image is built for both amd64 (x86_64) and arm64 (Apple Silicon, AWS Graviton, Raspberry Pi) architectures.
| Platform | Use Case |
|---|---|
| amd64 | Most servers, desktops, CI/CD runners, cloud VMs |
| arm64 | Apple Silicon (M1/M2/M3), AWS Graviton, Raspberry Pi, ARM‑based servers |
Docker automatically selects the correct architecture when you pull the image.
| Tag | Description |
|---|---|
latest |
Most recent build from the main branch. |
<commit-sha> |
Exact commit hash for pinpoint rollbacks. |
vX.Y.Z |
Semantic version extracted from Cargo.toml (e.g., v2.3.0). |
- Registry:
ghcr.io - Image:
ghcr.io/bengtfrost/rag-server - Storage: Free for public repositories.
# Pull the latest image (auto‑selects your architecture)
docker pull ghcr.io/bengtfrost/rag-server:latest
# Pull a specific version
docker pull ghcr.io/bengtfrost/rag-server:v2.3.0
# Run the binary
docker run --rm ghcr.io/bengtfrost/rag-server:latest --help
# Run in foreground (STDIO MCP server mode)
docker run --rm -i ghcr.io/bengtfrost/rag-server:latest# Inspect the multi‑arch manifest
docker manifest inspect ghcr.io/bengtfrost/rag-server:latest
# Check which arch you pulled
docker inspect ghcr.io/bengtfrost/rag-server:latest | grep ArchitectureAuthor: Bengt Frost
Philosophy: Native & Lean | Unified Memory | Sovereign AI
License: MIT
Repository: github.com/bengtfrost/rag-server