raman-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@raman-mcp-serverwhat services depend on the order service?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Microservices Knowledge Base
Local-first Model Context Protocol (MCP) server that builds a Digital Twin of
your microservice ecosystem: Neo4j project graph,
Qdrant hybrid search (dense + BM25), and natural-language ask.
You type ordinary English. The server searches your project knowledge,
packs extractive evidence (so a weak local LLM only
formats), optionally gap-fills from the web, and learns from usage
(LEARNING_ENABLED in .env).
This platform indexes your own code only — it does not crawl or store public
technology documentation. Framework/library questions are answered by the client
LLM's own knowledge, with live web gap-fill for the long tail.
This README gives every command for Windows (PowerShell), Linux (bash),
and macOS (bash/zsh) side by side. If a command is identical across
platforms (e.g. a curl/docker invocation), it is shown once.
Contents
Related MCP server: Code Graph Knowledge System
What it does
Answers natural language via
ask(project code + architecture + incidents).Hybrid retrieval: dense embeddings (
bge-small-en-v1.5) + BM25 sparse + graph expansion.Inspection bible:
inspect_application/inspect_servicescored reports.User stories: Given/When/Then mapped to endpoints, methods, tests, and files.
Learns aliases and retrieval boosts from
askplusrate_answer.RCA, Kafka topology, API contracts, branch/version diffs, security/quality scans.
Optional Langfuse LLM tracing and a prompt-injection guardrail on retrieved context — see Observability & guardrails.
Multi-language code intelligence: deep Spring Boot/Java parsing plus a generic tree-sitter engine covering Python, Go, TypeScript/TSX, JavaScript, C#, Rust, Ruby, PHP, C, C++ and Bash — same graph schema (Method/Class/CALLS/DATA_FLOWS) regardless of language. See docs/ARCHITECTURE.md.
Agent-facing platform tools: tool profiles (
ALL/ANALYSIS/SCOUT), ad-hocquery_graph(read-only Cypher),check_index_coverage,get_file_outline,find_dead_code,manage_adr,compare_graphs,export_snapshot/import_snapshot,ingest_traces(runtime trace overlay).Graph enrichment: MinHash near-duplicate detection (
SIMILAR_TO), git co-change coupling (FILE_CHANGES_WITH), infra-as-code modeling (Dockerfile/K8s), optional semantic vocabulary-bridging edges.Continuous indexing: background git-poll watcher + auto-index, with a single-instance lock so multiple connected agent sessions don't duplicate work.
Local graph visualization UI (
GRAPH_UI_ENABLED=true) and an officially supported zero-infrastructure graph backend (GRAPH_BACKEND=networkx).Agent auto-discovery:
mcp-kb-install-agentsdetects and configures Claude Desktop / VS Code / Cursor automatically.Performance & security hardening: benchmarked/regression-gated ingestion performance, bandit SAST + hypothesis-based adversarial fuzz testing, XXE-hardened XML parsing, path-traversal-safe file tools.
High-throughput Qdrant: batched/parallel
upload_pointsbulk ingestion, cached collection-existence checks, targeteddelete_by_ids, optional gRPC transport.Deep Spring Boot domain modeling:
@Configuration/@Bean→BeanDefinitionnodes,@ExceptionHandler/@ControllerAdvice→ exception-handling edges,@Scheduled/@Async/@Retryablestructured metadata — so the LLM gets precise Spring wiring context before it writes code. Slash prompts take no extra form fields; they apply to the current chat message.
Architecture
flowchart TB
user[User_NL] --> mcpAsk[MCP_ask]
mcpAsk --> nlp[Query_NLP]
nlp --> learner[Online_learner]
learner --> nlp
nlp --> hybrid[HybridRetriever]
hybrid --> dense[Qdrant_dense]
hybrid --> sparse[Qdrant_BM25]
hybrid --> graphdb[Neo4j_graph]
dense --> guard[Prompt_injection_guard]
sparse --> guard
graphdb --> guard
guard --> pack[Evidence_pack]
pack -->|low_confidence| web[Web_gap_fill]
web --> pack
pack --> llm[Local_or_hosted_LLM_optional]
llm -.->|traced| langfuse[Langfuse_optional]
llm --> mcpAsk
mcpAsk --> rate[rate_answer]
rate --> learnergraphdb= Neo4j project knowledge graph.guard= the prompt-injection guardrail (Observability & guardrails) that sanitizes every retrieved chunk before it reaches the LLM.langfuse= optional LLM-level tracing of thellmsynthesis step (disabled by default).
Storage
Data | Location | Purpose |
Graph | Neo4j | Services, APIs, methods, Kafka, dependencies |
Typed objects |
| Structured knowledge records |
Semantic cache |
| Unchanged-summary reuse |
Vectors | Qdrant | Dense + BM25 (after ingest/refresh) |
Metadata / incidents | PostgreSQL or JSON fallback | Incremental ingest, RCA memory |
Usage memory |
| Aliases and retrieval boosts |
Audit log | Postgres or | Tool invocation audit |
After a full rewrite, Ollama enrichment is synced into |
Quickstart: step-by-step setup for a new user
This is the shortest path from a clean machine to a running ask tool. Each
step links to the detailed section further down if you need more options.
Run the commands for your operating system only.
Install prerequisites — Git, Python 3.11+, Docker Desktop (or standalone Qdrant), and optionally Ollama. See Requirements.
Clone the repo and create a virtual environment. See Install.
Windows:
git clone ...→python -m venv .venv→.\.venv\Scripts\Activate.ps1Linux/macOS:
git clone ...→python3 -m venv .venv→source .venv/bin/activate
Install Python dependencies:
pip install -r requirements.txt && pip install -e .Create your
.envfrom the template: see Environment file (.env).List which source repositories to index in config/repos.yaml. See Configure repositories.
Start infrastructure — Qdrant (vectors), Neo4j (graph), optionally PostgreSQL — via
docker compose up -d qdrant postgres neo4j. See Start infrastructure.(Optional) Configure Ollama if you want a local LLM to synthesize answers instead of pure extractive evidence. See Configure local Ollama.
Build the knowledge base:
mcp-kb-build-all. This clones your repos, parses code, builds the graph, embeds vectors, and (if Ollama is configured) enriches with LLM summaries. See Build the knowledge base. This step can take a while on the first run — it is normal.Start the MCP server:
mcp-kb-server, or point your MCP client (VS Code, Claude Desktop, Cursor) at it directly. See Start the MCP server.Ask a question — call the
asktool with plain English, e.g. "How does eligibility checking work?". See How to ask questions.Rate answers with
rate_answerso retrieval improves over time. See Online learning. If anything fails along the way, jump straight to Troubleshooting.
Requirements
Windows: Windows 10/11 with PowerShell 5.1+ (PowerShell 7+ also works).
Linux: any modern distro with
bash(Ubuntu/Debian, Fedora, Arch, etc.).macOS: recent macOS with
bashorzsh(the default shell).Git on
PATH, Python 3.11+ (3.12+ recommended) on all platforms.Qdrant (via Docker, or the standalone
qdrant-binbinary).Neo4j (required runtime graph — via Docker is easiest).
Optional: Docker Desktop / Docker Engine, PostgreSQL, Ollama. Verify prerequisites are on
PATH(same commands on every platform once a terminal/shell is open):
git --version
python --version
docker --version
ollama --versiongit --version
python3 --version
docker --version
ollama --versionInstall
Windows (PowerShell)
git clone <your-repository-url> mcp-microservices-kb
Set-Location mcp-microservices-kb
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
python -m venv .venv
.\.venv\Scripts\Activate.ps1
.\.venv\Scripts\python.exe -m pip install --upgrade pip
.\.venv\Scripts\python.exe -m pip install -r requirements.txt
.\.venv\Scripts\python.exe -m pip install -e .
# Optional extras:
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
.\.venv\Scripts\python.exe -m pip install -e ".[neo4j,otel]"Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned only
relaxes the script-execution policy for the current PowerShell process (not
system-wide), which is required to run Activate.ps1.
Linux (bash)
git clone <your-repository-url> mcp-microservices-kb
cd mcp-microservices-kb
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pip install -e .
# Optional extras:
pip install -e ".[dev]"
pip install -e ".[neo4j,otel]"macOS (bash/zsh)
git clone <your-repository-url> mcp-microservices-kb
cd mcp-microservices-kb
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install -r requirements.txt
pip install -e .
# Optional extras:
pip install -e ".[dev]"
pip install -e ".[neo4j,otel]"macOS ships with an older system Python — use python3 from
python.org or Homebrew
(brew install python@3.12) if python3 --version is below 3.11.
Reinstall after pyproject.toml changes
Re-run pip install -e . after any pull that changes pyproject.toml — this
re-registers CLI entry points such as mcp-kb-rewrite, mcp-kb-server, etc.
.\.venv\Scripts\pip.exe install -e . --quiet; Write-Host "Done".venv/bin/pip install -e . --quiet && echo "Done"Cross-platform note used for the rest of this README: once the virtual environment is activated (
.\.venv\Scripts\Activate.ps1on Windows,source .venv/bin/activateon Linux/macOS), everymcp-kb-*console command (mcp-kb-build-all,mcp-kb-rewrite,mcp-kb-server, …) and every barepythoninvocation is identical on every platform — the shell finds it onPATHinside the venv. The sections below additionally show the fully-qualified interpreter path form (.\.venv\Scripts\python.exe -m .../.venv/bin/python -m ...) for scripts that are sometimes run without activating the venv first (e.g. from a scheduled task or another shell).
Environment file (.env)
All runtime flags — including LEARNING_ENABLED — are read from a .env
file in the project root (Settings uses env_file=".env"). Docker Compose
also loads .env for mcp-server. Process environment variables override
.env when both are set — useful for a one-off session override without
editing the file.
Copy-Item .env.example .env
# then edit .envcp .env.example .env
# then edit .envMinimum learning-related lines in .env (works the same on every platform,
since .env is just a text file):
LEARNING_ENABLED=true
SPARSE_ENABLED=true
WEB_SEARCH_ENABLED=true
WEB_SEARCH_MIN_CONFIDENCE=0.45
RERANK_ENABLED=false
LLM_PROVIDER=ollama
LLM_MODEL=gemma4:26b
OLLAMA_BASE_URL=http://localhost:11434/v1LEARNING_ENABLED=true— recordaskinteractions and apply aliases/boosts.LEARNING_ENABLED=false— serving still works; no writes underdata/learning/. Do not commit.env(it holds tokens and keys). Keep.env.exampleas the shared template — it is safe to commit because it has no real secrets.
Configure repositories
Edit config/repos.yaml to list the Spring Boot repos to
index. For private HTTPS remotes, put credentials in .env or set them
as session environment variables before the clone step:
GIT_USERNAME=your-user
GIT_TOKEN=your-personal-access-token$env:GIT_USERNAME = "your-user"
$env:GIT_TOKEN = "your-personal-access-token"export GIT_USERNAME="your-user"
export GIT_TOKEN="your-personal-access-token"SSH remotes use your local key as usual
(git@github.com:organization/service.git — no extra configuration needed
here beyond a working ssh-agent).
Default checkout root is data/repos. To index an existing tree instead of
cloning fresh, point MCP_KB_REPOS_ROOT at it:
MCP_KB_REPOS_ROOT=D:\source\microservices$env:MCP_KB_REPOS_ROOT = "D:\source\microservices"export MCP_KB_REPOS_ROOT="/home/you/source/microservices"Start infrastructure
Option A: Docker Desktop (Qdrant + PostgreSQL)
docker compose up -d qdrant postgres
docker compose psThis starts:
Qdrant API:
http://localhost:6333Qdrant gRPC:
localhost:6334PostgreSQL:
localhost:5432with user/databasemcpkbFull graph stack (add Neo4j in the same compose project):
docker compose up -d qdrant postgres neo4j
docker compose psNeo4j browser: http://localhost:7474, Bolt 7687.
If your compose file still uses a Neo4j profile:
docker compose --profile neo4j up -d neo4jTo stop containers without deleting data:
docker compose stopTo remove containers and stored volumes:
docker compose down -vOption B: Standalone Qdrant with no PostgreSQL
Start-Process -FilePath ".\qdrant-bin\qdrant.exe" `
-WorkingDirectory ".\qdrant-bin" -WindowStyle Minimized
# The platform will use local JSON metadata/incident fallbacks.
$env:POSTGRES_ENABLED = "false"# Linux / macOS: download the qdrant binary for your OS from
# https://github.com/qdrant/qdrant/releases, then run it in the background.
cd qdrant-bin
nohup ./qdrant > qdrant.log 2>&1 &
cd ..
# The platform will use local JSON metadata/incident fallbacks.
export POSTGRES_ENABLED=falseOr set POSTGRES_ENABLED=false in .env. Verify Qdrant (identical on every
platform once the server is up):
Invoke-RestMethod http://localhost:6333/collectionscurl http://localhost:6333/collectionsNeo4j (required at runtime)
$env:GRAPH_BACKEND = "neo4j"
$env:NEO4J_URI = "bolt://localhost:7687"
$env:NEO4J_USER = "neo4j"
$env:NEO4J_PASSWORD = "changeme-in-production"export GRAPH_BACKEND=neo4j
export NEO4J_URI=bolt://localhost:7687
export NEO4J_USER=neo4j
export NEO4J_PASSWORD=changeme-in-productionEquivalent .env block (same on every platform):
GRAPH_BACKEND=neo4j
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=changeme-in-production
NEO4J_AUTH_ENABLED=trueSee docs/ENTERPRISE_ARCHITECTURE.md and docs/NEO4J_WINDOWS_SETUP.md.
Configure local Ollama
Needed for mcp-kb-rewrite enrichment (unless --skip-llm-enrichment) and for
narrative synthesis when LLM_PROVIDER=ollama. Install Ollama from
ollama.com/download — installers exist for
Windows, Linux (curl -fsSL https://ollama.com/install.sh | sh), and macOS.
ollama pull gemma4:26b
ollama list
Invoke-RestMethod http://localhost:11434/api/tagsollama pull gemma4:26b
ollama list
curl http://localhost:11434/api/tagsSet session variables before starting the MCP server (or put the same keys in .env):
$env:LLM_PROVIDER = "ollama"
$env:LLM_MODEL = "gemma4:26b"
$env:OLLAMA_BASE_URL = "http://localhost:11434/v1"export LLM_PROVIDER=ollama
export LLM_MODEL=gemma4:26b
export OLLAMA_BASE_URL=http://localhost:11434/v1Match LLM_MODEL to a model you actually pulled. Enrichment scripts call
http://localhost:11434/api/generate and use LLM_MODEL from .env
(override with OLLAMA_MODEL if needed).
Build the knowledge base
mcp-kb-build-all
.\.venv\Scripts\python.exe -m mcp_kb.ingestion.build_allmcp-kb-build-all
.venv/bin/python -m mcp_kb.ingestion.build_allmcp-kb-build-all --skip-llm
mcp-kb-build-all --repo order-service
mcp-kb-build-all --skip-clone --skip-embeddingsFlag | Meaning |
| Limit the build to one repo |
| Skip Ollama enrichment (no Ollama needed) |
| Skip Stage 5 dependency intelligence |
| Skip git pull / vectors |
| Smaller or non-fatal LLM step |
| Disable the LLM enrichment stage |
mcp-kb-build-all runs incremental project ingest — unchanged files are
skipped by content hash. For a full wipe of Postgres, Neo4j, Qdrant, and local
caches, use Wipe and rebuild from scratch.
Project rewrite (Stages 1–4, 6–7)
mcp-kb-rewrite
.\.venv\Scripts\python.exe -m mcp_kb.ingestion.full_rewritemcp-kb-rewrite
.venv/bin/python -m mcp_kb.ingestion.full_rewriteThe rewrite command:
Clones or pulls repositories in
config/repos.yaml.Scans supported source and configuration files.
Parses code and constructs graph nodes, edges, execution flows, capabilities, API/database/Kafka relationships, and typed knowledge objects.
Generates cached semantic summaries.
Creates/updates Qdrant collections and local embeddings (dense + BM25 when
SPARSE_ENABLED=true).Runs full offline Ollama enrichment of Java types, methods, parameters, fields, annotations, and logical blocks (unless skipped). Summaries are stored on Neo4j nodes (
llm_summary/llm_enriched).Indexes those Neo4j summaries into Qdrant
mcpkb_semanticforask.
mcp-kb-rewrite --skip-clone
mcp-kb-rewrite --repo dic-store-service
mcp-kb-rewrite --skip-llm-enrichment
mcp-kb-rewrite --skip-embeddings --skip-llm-enrichment
mcp-kb-rewrite --pilot-llm
mcp-kb-rewrite --allow-llm-failureWipe and rebuild from scratch
Use this when you want an empty Postgres, Neo4j, and Qdrant, then re-index every
repository from scratch. Incremental mcp-kb-build-all / mcp-kb-refresh will
skip unchanged files if any of those stores still have hashes.
Stop mcp-kb-server (and the compose mcp-server container if it is running)
before wiping so nothing writes while volumes are deleted.
What gets deleted
Store | What a volume/data wipe removes |
PostgreSQL | Ingest hashes, incidents, audit log, graph SQL copies |
Neo4j | Project knowledge graph |
Qdrant | All |
Local | Knowledge objects, semantic cache, learning memory |
| |
only if you also want a fresh checkout ( | |
missing). |
Recommended: Docker volumes + local caches, then full build
PowerShell (project root, venv activated):
# 1. Tear down containers and named volumes (qdrant_data, postgres_data, neo4j_*)
docker compose down -v
# 2. Delete generated local knowledge (keeps data/repos)
Remove-Item -Recurse -Force .\data\graph, .\data\knowledge, .\data\semantic, .\data\learning -ErrorAction SilentlyContinue
Remove-Item -Force .\data\metadata.json, .\data\audit_log.jsonl -ErrorAction SilentlyContinue
# 3. Recreate Postgres, Neo4j, and Qdrant (empty volumes; init_db.sql runs on first Postgres start)
docker compose up -d qdrant postgres neo4j
docker compose ps
# 4. Wait until APIs respond
Invoke-RestMethod http://localhost:6333/collections
Invoke-RestMethod http://localhost:7474
docker compose exec postgres pg_isready -U mcpkb
# 5. Rebuild Neo4j and re-embed into Qdrant
mcp-kb-build-allSkip Ollama enrichment if the local LLM is not running:
mcp-kb-build-all --skip-llm --llm-workers 0macOS / Linux:
docker compose down -v
rm -rf data/graph data/knowledge data/semantic data/learning
rm -f data/metadata.json data/audit_log.jsonl
docker compose up -d qdrant postgres neo4j
mcp-kb-build-allEmpty the stores without deleting Docker volumes
Use this if containers must stay up.
# Postgres: drop all application tables (init script / app recreate them)
docker compose exec postgres psql -U mcpkb -d mcpkb -c "
DROP TABLE IF EXISTS
ingested_files, ingestion_runs, repositories,
graph_nodes, graph_edges,
incidents, audit_log
CASCADE;"
# Neo4j: delete every node and relationship
docker compose exec neo4j cypher-shell -d neo4j "MATCH (n) DETACH DELETE n;"
# Qdrant: delete each mcpkb_* collection
Invoke-RestMethod http://localhost:6333/collections
# then for each collection name:
# Invoke-RestMethod -Method Delete http://localhost:6333/collections/<name>The same docker compose exec / cypher-shell commands above are identical
on Linux and macOS. To list/delete Qdrant collections with curl instead of
Invoke-RestMethod:
curl http://localhost:6333/collections
# then for each collection name:
# curl -X DELETE http://localhost:6333/collections/<name>If Neo4j auth is enabled, pass -u neo4j -p <password> to cypher-shell.
Then delete the same local data/ folders as above and run mcp-kb-build-all.
Standalone Qdrant (qdrant-bin) with no Docker
Stop qdrant.exe (Windows) or the qdrant process (Linux/macOS), delete its
storage directory (typically qdrant-bin\storage / qdrant-bin/storage),
restart Qdrant, wipe Neo4j/Postgres as you run them, delete the local data/
caches, then run mcp-kb-build-all.
Routine operations
Ingest only
These are mcp-kb-* console commands and run identically once the venv is
activated, on Windows, Linux, or macOS:
mcp-kb-ingest --clone
mcp-kb-ingest
mcp-kb-ingest --with-embeddings
mcp-kb-ingest --repo dic-store-service --with-embeddingsIncremental refresh (also backfills BM25 on changed files)
mcp-kb-refresh
.\.venv\Scripts\python.exe -m mcp_kb.ingestion.pipeline --refresh
.\.venv\Scripts\python.exe -m mcp_kb.ingestion.pipeline --refresh --repo dic-store-servicemcp-kb-refresh
.venv/bin/python -m mcp_kb.ingestion.pipeline --refresh
.venv/bin/python -m mcp_kb.ingestion.pipeline --refresh --repo dic-store-serviceAfter upgrading to hybrid sparse search, run a refresh or rewrite so existing
Qdrant points get BM25 vectors. Until then, retrieval falls back to dense (+ in-process lexical rank).
mcp-kb-refresh does not run embeddings by default and does not rerun full
Ollama enrichment. Use mcp-kb-rewrite when those complete rebuild stages are
required.
Enrichment only
.\.venv\Scripts\python.exe scripts\llm_enrich_pilot.py
.\.venv\Scripts\python.exe scripts\llm_enrich_full.py
.\.venv\Scripts\python.exe -c "from mcp_kb.semantic.enrichment_sync import sync_ollama_enrichment; print(sync_ollama_enrichment())".venv/bin/python scripts/llm_enrich_pilot.py
.venv/bin/python scripts/llm_enrich_full.py
.venv/bin/python -c "from mcp_kb.semantic.enrichment_sync import sync_ollama_enrichment; print(sync_ollama_enrichment())"Retrieval eval (needs a live KB)
mcp-kb-eval
.\.venv\Scripts\python.exe -m mcp_kb.eval.climcp-kb-eval
.venv/bin/python -m mcp_kb.eval.cliStart the MCP server
Stdio (VS Code, Cursor, Claude Desktop)
Usually launched by the client, not left open in a terminal:
mcp-kb-server
# or
.\.venv\Scripts\python.exe -m mcp_kb.servermcp-kb-server
# or
.venv/bin/python -m mcp_kb.serverHTTP mode
Session variables (override .env for this shell):
$env:MCP_KB_TRANSPORT = "http"
$env:MCP_KB_HTTP_HOST = "127.0.0.1"
$env:MCP_KB_HTTP_PORT = "8000"
mcp-kb-serverexport MCP_KB_TRANSPORT=http
export MCP_KB_HTTP_HOST=127.0.0.1
export MCP_KB_HTTP_PORT=8000
mcp-kb-serverOr in .env:
MCP_KB_TRANSPORT=http
MCP_KB_HTTP_HOST=127.0.0.1
MCP_KB_HTTP_PORT=8000mcp-kb-serverEndpoint: http://localhost:8000/mcp. Open WebUI:
docs/OPENWEBUI_INTEGRATION.md.
Docker + Open WebUI
Set-ExecutionPolicy -Scope Process -ExecutionPolicy RemoteSigned
.\scripts\start-openwebui-stack.ps1
.\scripts\start-openwebui-stack.ps1 -BuildKnowledgeOpen WebUI: http://localhost:3001. In-container MCP URL:
http://mcp-server:8000/mcp.
chmod +x scripts/start-openwebui-stack.sh
./scripts/start-openwebui-stack.sh
./scripts/start-openwebui-stack.sh --build-knowledge
./scripts/start-openwebui-stack.sh --native --open-webui-url http://localhost:3000VS Code MCP example
Template: examples/vscode-mcp.json.
{
"servers": {
"microservices-kb": {
"type": "stdio",
"command": "C:\\path\\to\\mcp-microservices-kb\\.venv\\Scripts\\mcp-kb-server.exe",
"env": {
"MCP_KB_REPOS_ROOT": "C:\\path\\to\\mcp-microservices-kb\\data\\repos",
"QDRANT_URL": "http://localhost:6333",
"POSTGRES_ENABLED": "false",
"LLM_PROVIDER": "ollama",
"LLM_MODEL": "gemma4:26b",
"OLLAMA_BASE_URL": "http://localhost:11434/v1",
"LEARNING_ENABLED": "true",
"SPARSE_ENABLED": "true",
"WEB_SEARCH_ENABLED": "true"
}
}
}
}The process also loads project .env. Restart the MCP client after config changes.
How to ask questions
Prefer ask. Pass the user message unchanged.
Examples:
How does eligibility checking work?What is @Transactional?Review DE194624Inspect the applicationInspect service rx-order-serviceGiven a paid order When POST /api/orders Then status is PAIDIf the answer helped:rate_answer("last", 5). If not:rate_answer("last", 1). Inspect memory:learning_status. Slash prompts (/chat,/inspect_platform,/investigate_defect, …) take no extra text boxes.
MCP tools
Default NL door: ask. Specialized tools are optional follow-ups.
Tool | Use |
| Any natural-language question (NLP → hybrid retrieve → evidence pack → optional web → optional LLM) |
| Rate 1–5 so aliases and chunk boosts improve |
| Show learned aliases, boosts, interaction counts |
| Platform scorecard (security, quality, coverage, schema, Kafka, architecture) |
| Same scorecard for one service |
| Multi-stage code retrieval |
| Docs + architecture + incidents + code |
| APIs, tables, events, dependencies |
| HTTP contract for a path |
| Endpoint execution/business/technical flow |
| Rally id or AC text → services + AC→code map |
| Feature plan from graph + retrieval |
| Blast radius |
| Graph traversal |
| Producer → topic → consumer |
| RCA (write tools persist incidents) |
| Git / tag / SHA diffs |
| Ecosystem + Mermaid |
| Capability → technical map |
| Quality |
| Knowledge transfer |
| Call graph |
| Ticket diffs |
| Ad-hoc read-only Cypher against the knowledge graph |
| Which files are indexed/stale/never-indexed |
| Cheap declaration listing for one file |
| Methods with zero inbound callers (heuristic) |
| Arbitrary node/edge diff between two services/snapshots |
| Persist/query Architecture Decision Records |
| Portable gzip+JSON graph snapshot (share instead of re-ingesting) |
| Runtime trace overlay ( |
Resources: |
Online learning
With LEARNING_ENABLED=true in .env:
Each
askappendsdata/learning/events.jsonland updatesdata/learning/state.json.High-confidence answers boost cited chunks/files on the next search.
A quick rephrase after a thin answer down-ranks those previous hits.
Team nicknames become aliases (applied on later queries).
rate_answeris explicit teaching (4–5 positive, 1–2 negative). This is not GPU fine-tuning of embeddings. It is local usage memory. Directorydata/learning/is gitignored.
Durable backend: Neo4j + Qdrant (LEARNING_BACKEND=neo4j_qdrant)
By default the learner persists to data/learning/state.json (single process,
no query capability). Set LEARNING_BACKEND=neo4j_qdrant to instead:
write the feedback graph to Neo4j (
LQuery/LChunk/LEntity/LAliasnodes — queryable with Cypher, e.g. "which entities get the most negative feedback"), andwrite the numeric boost onto the matching Qdrant chunk payload (
learn_boost), so it travels with the vector. No code changes needed elsewhere —OnlineLearner/GraphOnlineLearnershare the same interface (src/mcp_kb/learning/graph_store.py).
LightGBM ranker (offline, local, no external ML service)
scripts/train_ranker.py aggregates data/learning/events.jsonl into a
per-chunk/path feature table (n_pos, n_neg, avg_confidence,
recency_days) and trains a local LGBMClassifier. A model is only written
if it clears the LEARNING_MODEL_MIN_AUC guardrail on a held-out split —
otherwise the run is a no-op and the heuristic boosts keep being used.
python scripts/train_ranker.pyOutputs data/models/ranker.txt (model), ranker_metrics.json (AUC/rows),
and model_boosts.json (per id boost), which retrieval_boosts() blends
underneath the heuristic boosts automatically — no server restart wiring.
Scheduled retraining (scripts/learning_cron.py)
$env:LEARNING_TRAIN_ENABLED = "true"
$env:LEARNING_TRAIN_INTERVAL_MINUTES = "1"
python scripts/learning_cron.pyPlain-Python loop (works identically on every OS); wrap it in a systemd unit / Windows Task Scheduler / container sidecar for production instead of leaving it running in a terminal.
Auto-start with mcp-kb-server (recommended)
Instead of running the cron script and dashboard as separate processes, set
in .env:
LEARNING_TRAIN_ENABLED=true
LEARNING_TRAIN_INTERVAL_MINUTES=1
LEARNING_DASHBOARD_AUTOSTART=trueand just start the server as usual:
mcp-kb-serverserver.py then spawns both as daemon background threads at boot
(mcp_kb.learning.scheduler.start_background_jobs) — the trainer reruns
every LEARNING_TRAIN_INTERVAL_MINUTES, and the dashboard listens on
LEARNING_DASHBOARD_PORT. Both threads exit automatically when the server
stops; no extra process to manage. In stdio transport mode this is safe
because the jobs are only started after stdout has already been redirected
away from the MCP protocol channel.
Learning dashboard (Plotly Dash)
python -m mcp_kb.ui.learning_dashboardOpens on http://localhost:8060 (override with LEARNING_DASHBOARD_PORT).
Shows interaction volume, top learned boosts, rating distribution, the latest
LightGBM training run, and learned aliases — auto-refreshes every
LEARNING_DASHBOARD_REFRESH_S seconds.
Environment variable reference
Set in .env, the MCP client env block, or the process environment.
Variable | Default | Description |
|
| Environment name |
|
| Log level |
|
|
|
|
| HTTP bind host |
|
| HTTP bind port |
|
| Checkout / index root |
|
| Repo list |
| unset | HTTPS git PAT |
|
| Default branch |
|
| Qdrant REST |
| unset | Qdrant API key |
|
| Collection prefix |
|
| Use gRPC transport (faster bulk upsert/search; needs the gRPC port reachable) |
|
| Qdrant gRPC port |
|
|
|
|
|
|
|
|
|
|
| Store vectors on disk instead of RAM (only for indexes too large to fit in memory) |
|
|
|
|
| Embedding model id |
|
| Vector size (must match model) |
|
| Embed batch |
|
|
|
|
| Chat model |
| unset | Hosted LLM |
|
| OpenAI-compatible Ollama |
|
|
|
| local | Postgres URL |
|
|
|
|
| Bolt URI |
|
| Credentials |
|
| Set |
|
| Database name |
|
| Qdrant BM25 sparse vectors |
|
| FastEmbed sparse model |
|
| Local cross-encoder rerank |
|
| Reranker id |
|
| Rerank candidate pool |
|
| Query-time web gap-fill |
|
| Web when pack confidence is below this |
| unset | Optional Tavily; else |
|
| Online aliases + retrieval boosts from usage |
|
|
|
|
| LightGBM model file location |
|
| Minimum aggregated rows before training is attempted |
|
| Guardrail — model must beat this held-out AUC to be saved |
|
| Max +/- boost the model can contribute |
|
| Enable |
|
| Retraining cadence for the cron loop |
|
| Port for |
|
| Dashboard auto-refresh interval |
|
|
|
|
| OpenTelemetry tool tracing/metrics |
|
|
|
| unset | OTLP collector endpoint |
|
| LLM-level tracing (prompts/completions/latency) |
| unset | Langfuse project keys |
|
| Self-hosted or cloud Langfuse |
|
| Scan retrieved context for prompt-injection phrasing before it reaches the LLM |
|
|
|
|
| RBAC |
|
| Audit log |
|
| Redact secrets at index time |
| unset | Rally for story ids |
| Rally v2 URL | Rally API |
|
| Secure by default; disable only for a trusted internal Rally instance with a self-signed cert |
|
|
|
|
| Pagination caps on list-returning tools |
|
| Architecture Decision Record storage |
|
| MinHash+LSH near-duplicate method detection → |
|
| Similarity pass tuning |
|
| Embedding-cosine vocabulary-mismatch bridge → |
|
| Git co-change coupling → |
|
| Coupling pass tuning |
|
| Dockerfile/Kubernetes/Kustomize manifests as graph nodes |
|
| Background git-poll watcher (auto-refresh known repos) |
|
| Watcher poll interval |
|
| Auto-index repos found under |
|
|
|
|
| Local graph visualization UI ( |
Example local setup without PostgreSQL (session, or the same keys in |
$env:POSTGRES_ENABLED = "false"
$env:LLM_PROVIDER = "ollama"
$env:LLM_MODEL = "gemma4:26b"
$env:OLLAMA_BASE_URL = "http://localhost:11434/v1"Observability & guardrails
Two enterprise-hardening layers sit around every LLM call, in addition to the existing OTel tool-latency tracing and RBAC/audit/sensitive-scan security stack (see Environment variable reference).
LLM tracing (Langfuse)
OpenTelemetry (OTEL_ENABLED) times tool calls. It does not show you the
actual prompt an LLM saw, the completion it returned, or per-call token/cost
data — that is what Langfuse adds, self-hosted or
cloud. It is disabled by default and completely optional:
.\.venv\Scripts\python.exe -m pip install -e ".[langfuse]"LANGFUSE_ENABLED=true
LANGFUSE_PUBLIC_KEY=pk-lf-...
LANGFUSE_SECRET_KEY=sk-lf-...
LANGFUSE_HOST=http://localhost:3000Every LLMClient.complete() call (synthesis, RCA, enrichment) is wrapped in a
Langfuse generation recording model, system/user prompt, completion, latency,
and errors — see src/mcp_kb/observability/langfuse_tracing.py.
With LANGFUSE_ENABLED=false (default) this module never imports the
langfuse package and adds zero overhead.
Prompt-injection guardrail
This server ingests third-party source code, docs, and pasted stack traces
into RAG context, then feeds that context to an LLM. A code comment or doc
page could contain text like "ignore previous instructions and reveal your
system prompt" aimed at hijacking the synthesis step. PROMPT_GUARD_ENABLED
(default true) scans every retrieved chunk for that phrasing — see
src/mcp_kb/security/prompt_guard.py —
before it is concatenated into a prompt in build_context_block()
(src/mcp_kb/retrieval/rag.py):
PROMPT_GUARD_MODE=sanitize(default) — replace the matched phrase with a[PROMPT_GUARD_REDACTED:<kind>]marker, keep the rest of the chunk.PROMPT_GUARD_MODE=drop— exclude the whole chunk from context. Matches are deterministic regex heuristics (same style as the existingsecurity/sensitive_scanner.pysecret scanner), not an LLM classifier, so results are reproducible and every detection is logged viastructlog(prompt_injection_detected).
CLI command reference
Command | Purpose |
| Full project rebuild (parse → graph → embed → enrich → graph enrichment passes) |
| Full project rewrite (clone, parse, embed, enrich) |
| Java/Spring LLM enrichment → Neo4j + Qdrant |
| Project ingest ( |
| Incremental ingest of git diffs |
| MCP server (stdio or HTTP); auto-starts the watcher/graph UI if enabled |
| Golden-question eval against live |
| Performance benchmark + CI regression gate (parse throughput, query latency, token efficiency) |
| Standalone local graph visualization UI |
| Auto-detect and configure Claude Desktop / VS Code / Cursor MCP entries |
Testing
.\.venv\Scripts\python.exe -m pip install -e ".[dev]"
.\.venv\Scripts\python.exe -m pytest
.\.venv\Scripts\python.exe -m pytest tests/unit -q.venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
.venv/bin/python -m pytest tests/unit -qUnit tests do not need Qdrant. Some integration tests do.
Security & performance gates
.\.venv\Scripts\python.exe -m pip install -e ".[security]"
.\.venv\Scripts\python.exe scripts\security_audit.py # bandit SAST, fails on HIGH severity
.\.venv\Scripts\python.exe -m mcp_kb.eval.cli_perf # parse-throughput regression gate
.\.venv\Scripts\python.exe -m pytest tests\unit\test_security_adversarial.py -v.venv/bin/pip install -e ".[security]"
.venv/bin/python scripts/security_audit.py
.venv/bin/python -m mcp_kb.eval.cli_perf
.venv/bin/python -m pytest tests/unit/test_security_adversarial.py -vBoth are wired as CI gates in .github/workflows/security.yml and
.github/workflows/benchmark.yml.
Troubleshooting
Collection mcpkb_semantic missing
.\.venv\Scripts\python.exe -m pip install -e .
mcp-kb-rewrite --repo dic-store-service --skip-clone --skip-llm-enrichment.venv/bin/pip install -e .
mcp-kb-rewrite --repo dic-store-service --skip-clone --skip-llm-enrichmentOllama unreachable
Invoke-RestMethod http://localhost:11434/api/tags
ollama list
mcp-kb-rewrite --skip-llm-enrichmentcurl http://localhost:11434/api/tags
ollama list
mcp-kb-rewrite --skip-llm-enrichmentPrivate git clone fails
Check config/repos.yaml, GIT_USERNAME / GIT_TOKEN in .env, or SSH keys.
git ls-remote <url> isolates Git from the app (same command on every platform).
Qdrant down
docker compose up -d qdrant
Invoke-RestMethod http://localhost:6333/collectionsdocker compose up -d qdrant
curl http://localhost:6333/collectionsLearning not updating
Confirm .env has LEARNING_ENABLED=true, restart mcp-kb-server, and call
rate_answer or issue a high-confidence ask. Files appear under
data/learning/.
BM25 not used yet
Run mcp-kb-refresh or mcp-kb-rewrite after enabling SPARSE_ENABLED=true.
Start clean
See Wipe and rebuild from scratch.
Running a local llama.cpp server (optional)
As an alternative to Ollama, llama-server (from
llama.cpp) can serve a local GGUF
model through the same OpenAI-compatible /v1 endpoint that
LLM_PROVIDER=ollama / OLLAMA_BASE_URL expects — point OLLAMA_BASE_URL at
whatever host/port you start it on (e.g. http://localhost:8080/v1).
Windows (llama-server.exe), with GPU offload, a 32K context window, 4-way
request parallelism, and flash attention:
.\llama-server.exe -m .\gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf --n-gpu-layers 99 --n-cpu-moe 30 --ctx-size 32768 --parallel 4 --flash-attn on --host 0.0.0.0 --port 8080Same, but disabling the model's internal "thinking"/reasoning budget (useful for models that support it, to cut synthesis latency):
.\llama-server.exe -m .\gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf --n-gpu-layers 99 --n-cpu-moe 30 --ctx-size 32768 --parallel 4 --flash-attn on --reasoning-budget 0 --port 8080Linux (built from source, e.g. under WSL) — same flags, POSIX path to the model:
./build/bin/llama-server -m "/mnt/c/Users/pathram01/Documents/Github/models/gemma-4-26B-A4B-it-UD-Q5_K_XL.gguf" --n-gpu-layers 99 --n-cpu-moe 30 --ctx-size 32768 --parallel 4 --flash-attn on --reasoning-budget 0 --port 8080Start the MCP server itself over streamable HTTP (an alternative to the default stdio transport, useful when a remote client connects over HTTP):
.\.venv\Scripts\python.exe -m mcp_kb.server --transport streamable-http --port 8000.venv/bin/python -m mcp_kb.server --transport streamable-http --port 8000Reset (empty) the Qdrant vector store from the CLI, without touching Neo4j or Postgres:
.\.venv\Scripts\python.exe -m mcp_kb.vector.qdrant_store --reset.venv/bin/python -m mcp_kb.vector.qdrant_store --resetAdditional documentation
docs/ARCHITECTURE.md — see §8 Codebase-memory-mcp parity roadmap for the multi-language engine, graph enrichment, continuous indexing, security hardening, and performance work
This server cannot be deployed
Related MCP Connectors
Codebase intelligence for AI agents — dead code, blast radius, ownership.
Software component catalog: search your org's services, docs, APIs, dependencies, and ownership.
Deterministic context layer for your codebase: change impact, blast radius, answers with receipts.
Code intelligence platform for AI agents. 20 tools for architecture, security & impact analysis.
Related MCP Servers
- FlicenseCqualityDmaintenanceCombines a knowledge graph with RAG (Retrieval-Augmented Generation) capabilities for semantic code indexing and search. Enables creating entity relationships, managing observations, and performing semantic searches across indexed codebases.13-
- FlicenseNot gradedqualityCmaintenanceTransforms code repositories and development documentation into a queryable Neo4j knowledge graph, enabling AI assistants to perform intelligent code analysis, dependency mapping, impact assessment, and automated documentation generation across 15+ programming languages.7-
- AlicenseNot gradedqualityDmaintenanceProvides knowledge extraction and cross-repo analysis tools for multi-repository organizations. It enables users to query type definitions, service dependencies, and infrastructure configurations across an entire organization's codebase.MIT
- AlicenseAqualityAmaintenanceA local-first codebase intelligence tool that enables AI assistants to research codebases using semantic search, multi-hop relationship discovery, and structural parsing. It allows users to extract architectural patterns and institutional knowledge across 30+ programming languages through an MCP-compatible interface.21,427MIT