Skip to content
Conduit

mcp server

documind

Multi-namespace federated RAG platform — LangGraph + ChromaDB + MCP, with a Streamlit UI and RAGAS evaluation.

HarshkumarBorad/documindcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

This project does not publish an install method we can turn into a config. Follow the README instead.

README

synced Oct 23, 2026

📚 DocuMind — Enterprise RAG Platform

A multi-namespace, federated retrieval-augmented generation platform. Drop any document corpus into one of four isolated knowledge spaces and query them individually or federally across all of them — with cross-encoder reranking, inline citations, RAGAS evaluation, and an MCP server that turns the whole thing into a tool layer for multi-agent systems.

Built end-to-end as a portfolio project — every layer is independently testable and was wired in nine deliberate phases (see build phases).


✨ Highlights

  • Four isolated knowledge namespaces — HR, Tech, Research, Product — and a federated query mode that searches all of them simultaneously.
  • LangGraph orchestration with a typed state, conditional routing, and individually testable nodes (classify → retrieve | retrieve_federated → rerank → synthesize → format_citations).
  • Cross-encoder reranking with BAAI/bge-reranker-base for multilingual, precision-focused result ordering.
  • MCP server (FastMCP) exposing each namespace as a named tool — drop-in memory layer for any LLM agent (Claude Desktop, Cline, Cursor, etc.).
  • REST API (FastAPI) with auto-generated OpenAPI/Swagger docs.
  • Streamlit UI with per-domain visual identity, drag-and-drop ingest, live health monitoring, and a RAGAS evaluation dashboard.
  • RAGAS evaluation wired to the same HF Inference Providers stack — no second API key — with per-query metrics and bar-chart visualisation.
  • One-command full-stack via Docker Compose — docker compose up boots ChromaDB, the FastAPI, the Streamlit UI, and the MCP server.

🎬 Demo

Drop your demo.gif at docs/demo.gif. Suggested recording flow in the Demo recording guide below.


🚀 Quick demo with sample data (5 minutes)

Prereqs: Docker Desktop and Python 3.11+.

:: 1. Configure your HuggingFace token (free tier works)
copy .env.example .env
::    Edit .env and set HF_TOKEN=<your token>
::    Get one at https://huggingface.co/settings/tokens

:: 2. Bring up the whole stack with Docker — 4 services in one command
docker compose up -d

:: 3. Create the four namespaces and ingest the bundled sample docs
docker compose exec api python -m vectorstore.init_namespaces
docker compose exec api python scripts/ingest_samples.py

Then open:

Try the sample questions in the 🔍 Query tab:

  • "What is the leave policy?" — single-domain (hr)
  • "How do I install Aurora on Windows?" — single-domain (product)
  • "What does the company say about authentication and rate limits?" — federated

Each answer comes back with inline [N] citations and a Sources list naming the exact document and page.


🏗️ Architecture

┌──────────────────────────────────────────────────────────────┐
│                       Streamlit UI                            │
│   🔍 Query   📥 Ingest   ⚡ Status   📊 Evaluation             │
└────────────────────────────┬─────────────────────────────────┘
                             │ HTTP
┌────────────────────────────▼─────────────────────────────────┐
│                       FastAPI Layer                           │
│   /query/{domain}    /query/federated                         │
│   /ingest            /evaluation/run                          │
│   /health            /models           /namespaces            │
└────────────────────────────┬─────────────────────────────────┘
                             │
┌────────────────────────────▼─────────────────────────────────┐
│                  LangGraph Pipeline                           │
│                                                                │
│   classify ─► (retrieve │ retrieve_federated) ─► rerank        │
│                       │                              │         │
│                       │                              ▼         │
│                       │                          synthesize    │
│                       │                              │         │
│                       │                              ▼         │
│                       │                      format_citations  │
└──────────┬─────────────────────────────────────────────┬──────┘
           │                                             │
┌──────────▼─────────┐                          ┌────────▼────────┐
│     ChromaDB       │                          │   MCP Server     │
│  4 isolated        │                          │  6 tools         │
│  namespaces        │                          │  (FastMCP)       │
└────────────────────┘                          └─────────────────┘

The same compiled LangGraph is the single source of truth for query behaviour. The FastAPI, the MCP server, the CLI, and the Streamlit UI all call get_graph().invoke() — zero duplication.


📂 Knowledge spaces

DomainSample contentChunking strategy
🧑‍💼 HROnboarding handbook, leave policy, code of conductRecursive (800 / 100)
🔧 TechAPI references, SDK docs, architecture decision recordsRecursive (800 / 100)
🔬 ResearcharXiv papers on RAG / LLMs / vector searchSemantic (95th percentile)
📦 ProductInstallation guide, release notes, customer FAQRecursive (800 / 100)

Each namespace is a separate ChromaDB collection — documind_hr, documind_tech, etc. Cross-namespace contamination is impossible by construction.


🛠️ Tech stack

LayerChoiceWhy
OrchestrationLangGraphStateful pipeline with conditional routing and typed state
Vector storeChromaDB (one collection per namespace)Hosted in Docker; HTTP client only — lightweight install
EmbeddingsBGE-M3 via HF Inference APIMultilingual (German + English), strong benchmarks
RerankerBGE-reranker-base (local, sentence-transformers)Cross-encoder precision; runs on CPU
Chat LLMHF Inference Providers (Qwen / Llama / DeepSeek / Mistral / Phi)One token, multiple providers, runtime model swap
IngestionLangChain loaders + custom chunker per domainStable PDF / DOCX / MD / HTML support
APIFastAPI + UvicornOpenAPI for free, async-ready
MCP serverFastMCPStandard agentic tool protocol
FrontendStreamlitNative Python, fast iteration, polished out of the box
EvaluationRAGASIndustry-standard RAG metrics
ContainersDocker ComposeSingle-command full-stack

📁 Project structure

documind/
├── docker-compose.yml          ← 4 services: chromadb, api, ui, mcp
├── Dockerfile                  ← single image, per-service CMD override
├── .env.example                ← all configurable knobs
├── requirements.txt            ← phased — see comments for what each block adds
│
├── vectorstore/                ← Phase 1: namespace manager + Chroma client
│   ├── chroma_client.py
│   └── init_namespaces.py
│
├── ingestion/                  ← Phase 2: loaders, chunker, embedder
│   ├── loaders.py
│   ├── chunker.py
│   ├── embedder.py
│   └── ingest_pipeline.py      ← CLI: --domain X --path Y
│
├── rag_pipeline/               ← Phases 3 & 4: LangGraph pipeline
│   ├── graph.py                ← graph wiring + lru-cached compile
│   ├── state.py                ← typed GraphState / CitedSource
│   ├── llm.py                  ← HF chat client + model registry
│   ├── query.py                ← CLI for single + federated queries
│   └── nodes/
│       ├── classifier.py       ← validates input, decides routing
│       ├── retriever.py
│       ├── federated_retriever.py  ← parallel across all 4 namespaces
│       ├── reranker.py         ← cross-encoder, lazy-loaded
│       ├── synthesizer.py
│       └── citation_formatter.py
│
├── api/                        ← Phase 5: FastAPI REST layer
│   ├── main.py
│   ├── schemas.py
│   └── routers/
│       ├── system.py           ← /health /models /namespaces
│       ├── query.py            ← /query/{domain} /query/federated
│       ├── ingest.py           ← /ingest
│       └── evaluation.py       ← /evaluation/queries /evaluation/run
│
├── mcp_server/                 ← Phase 6: 6 MCP tools
│   └── server.py
│
├── ui/                         ← Phase 7: Streamlit
│   ├── app.py                  ← 4-tab UI
│   ├── api_client.py           ← thin requests wrapper
│   └── styles.py               ← per-domain colors + icons + CSS
│
├── evaluation/                 ← Phase 8: RAGAS
│   ├── eval_pipeline.py        ← main runner
│   ├── llm_wrapper.py          ← HF chat → langchain ChatModel
│   └── test_queries.json       ← Q&A ground truths per domain
│
├── docs/                       ← Phase 9: sample documents
│   ├── hr/                     ← onboarding, leave policy, code of conduct
│   ├── tech/                   ← API ref, SDK quickstart, ADR
│   ├── research/               ← (drop arXiv PDFs here)
│   └── product/                ← install guide, release notes, FAQ
│
├── scripts/
│   └── ingest_samples.py       ← one-shot ingest of all bundled samples
│
└── .streamlit/
    └── config.toml             ← theme, colors, gather-stats off

🐳 Run with Docker (recommended)

:: 1. Set HF_TOKEN in .env (see .env.example)
copy .env.example .env

:: 2. Bring up the stack
docker compose up -d

:: 3. Initialize namespaces and ingest samples
docker compose exec api python -m vectorstore.init_namespaces
docker compose exec api python scripts/ingest_samples.py

Services:

ServiceURLPurpose
chromadbhttp://localhost:8000Vector store
apihttp://localhost:8001FastAPI — see /docs for Swagger
uihttp://localhost:8501Streamlit UI
mcphttp://localhost:8002/mcpMCP Streamable HTTP endpoint

docker compose logs -f to follow output. docker compose down to stop; docker compose down -v to also wipe the ChromaDB volume.


☁️ Deploy to HuggingFace Spaces

A pre-configured single-container variant lives under spaces/ — embedded ChromaDB, Streamlit talking to the graph in-process, no FastAPI or MCP services. Step-by-step deployment guide: spaces/DEPLOY.md.

This is what you'd link to a recruiter as a live demo URL — free hosting, no ongoing cost, recognized AI portfolio venue.

💻 Run locally (per-service)

Useful for development with auto-reload.

:: cmd.exe syntax — line continuation = ^
:: For PowerShell, swap ^ for ` ; for bash, swap for \

:: 0. Setup once
copy .env.example .env
::    Edit .env: HF_TOKEN=<your token>

python -m venv .venv
.venv\Scripts\activate
pip install -r requirements.txt

:: 1. ChromaDB (always in Docker — easier than a local install)
docker compose up -d chromadb

:: 2. Namespaces
python -m vectorstore.init_namespaces

:: 3. Sample ingest
python scripts/ingest_samples.py

:: 4. Start services in separate terminals
uvicorn api.main:app --reload --port 8001
streamlit run ui/app.py
python -m mcp_server.server --transport http --port 8002

🔌 REST API

Auto-generated docs at http://localhost:8001/docs (Swagger UI) and http://localhost:8001/redoc.

MethodPathPurpose
GET/healthChromaDB connectivity + per-namespace chunk counts
GET/modelsDefault + supported LLM IDs
GET/namespacesPer-namespace chunk counts
POST/query/{domain}Single-domain query — hr/tech/research/product
POST/query/federatedFederated query across all four namespaces
POST/ingestIngest a server-local directory into a namespace
GET/evaluation/queriesTest query set (grouped by domain)
POST/evaluation/runRun RAGAS evaluation for one domain

Example — federated query via curl:

curl -X POST http://localhost:8001/query/federated ^
    -H "Content-Type: application/json" ^
    -d "{\"question\": \"How do I authenticate API requests?\", \"top_k\": 5}"

🤖 MCP server — bridge to multi-agent systems

Six tools, one for each namespace plus a federated and an introspection tool:

ToolReturns
query_hr_knowledge(question)Answer + citations from HR
query_tech_docs(question)Answer + citations from Tech
query_research_papers(question)Answer + citations from Research
query_product_knowledge(question)Answer + citations from Product
federated_query(question, top_k_per_domain=5)Cross-namespace answer with domain-tagged citations
list_namespaces()Inventory + chunk counts (for agent cold-starts)

Wire it into Claude Desktop via claude_desktop_config.json:

{
  "mcpServers": {
    "documind": {
      "command": "python",
      "args": ["-m", "mcp_server.server"],
      "cwd": "/absolute/path/to/documind"
    }
  }
}

Why this matters: the next project (multi-agent system) plugs straight into these tools. Each agent gets a narrow tool — query_hr_knowledge for an HR agent, query_tech_docs for tech-support — and federated_query for a coordinator that needs cross-domain answers. Zero rework between projects.


🔍 Querying — single + federated

CLI (single-domain):

python -m rag_pipeline.query --domain hr --question "What is the leave policy?"

CLI (federated):

python -m rag_pipeline.query --federated --question "What does the company say about authentication?"

Citations in federated mode include the origin domain:

Aurora authenticates API requests with a Bearer token [1]. Free-tier accounts
are capped at 60 requests per minute [1], and the SDK reads the API key from
the AURORA_API_KEY environment variable by default [2].

Sources:
[1] [tech] api_reference.md
[2] [tech] sdk_quickstart.md

Supported LLMs (curated, gated models marked ‡ — accept their license on huggingface.co once):

  • Qwen/Qwen2.5-7B-Instruct (default — non-gated)
  • Qwen/Qwen2.5-72B-Instruct
  • meta-llama/Llama-3.1-8B-Instruct ‡
  • meta-llama/Llama-3.3-70B-Instruct ‡
  • mistralai/Mistral-Nemo-Instruct-2407
  • microsoft/Phi-3.5-mini-instruct
  • deepseek-ai/DeepSeek-V4-Flash (MIT)
  • deepseek-ai/DeepSeek-V4-Pro (MIT — flagship, burns free credits fast)

Pin a provider if HF's auto router hits an unhealthy backend: --provider together / --provider fireworks-ai / --provider sambanova.


📊 RAGAS evaluation

Test queries live in evaluation/test_queries.json. The bundled set has ground truths matched to the sample docs, so the evaluation tab gives meaningful numbers out of the box.

MetricNeeds ground truth?What it measures
faithfulnessnoDoes the answer factually align with the retrieved context?
answer_relevancynoDoes the answer actually address the question?
context_precisionyesAre the retrieved chunks relevant?
context_recallyesDo the retrieved chunks cover everything in the ground truth?

Run from the 📊 Evaluation tab in the UI, or via CLI:

python -c "from vectorstore import Domain; from evaluation import evaluate_domain; import json; print(json.dumps(evaluate_domain(Domain.HR, max_queries=3), indent=2))"

The judging LLM uses the same HF Inference stack as generation — one HF_TOKEN covers everything. The UI lets you pick a stronger model as the judge if you want to reduce self-evaluation bias.


🧭 Build phases

  • Phase 1 — Docker Compose + ChromaDB + namespace setup
  • Phase 2 — Ingestion pipeline (loaders, chunker, embedder)
  • Phase 3 — LangGraph pipeline (single domain)
  • Phase 4 — Federated search + cross-encoder reranker
  • Phase 5 — FastAPI layer
  • Phase 6 — MCP server (FastMCP)
  • Phase 7 — Streamlit UI
  • Phase 8 — RAGAS evaluation
  • Phase 9 — Sample documents, demo GIF, polished README

🎥 Demo recording guide

Record a short loop (40–60s) for docs/demo.gif. Suggested shot list:

  1. Title card (1s) — DocuMind logo / repo name.
  2. docker compose up (3s) — show the four services boot.
  3. Streamlit Status tab (3s) — 🟢 connected, four namespaces with chunk counts.
  4. Single-domain query (8s) — type "What is the leave policy?", hit Enter, answer appears with [1] [2] citations, expand a source card to show the text.
  5. Federated query (10s) — switch the mode pill to Federated, ask a cross-domain question, point out that citation badges now show different domain colors.
  6. Ingest tab (6s) — drag a PDF in, click Ingest, watch the chunk count on the header strip go up.
  7. Evaluation tab (10s) — pick a domain, click Run evaluation, show the metric bar chart filling in.
  8. (Optional) Claude Desktop (8s) — ask Claude to use query_hr_knowledge and show it returning a cited answer.

Tools that produce good GIFs:

Aim for ≤6 MB so GitHub embeds inline. ScreenToGif's "Reduce frame count" option helps without obvious quality loss.


🛣️ Roadmap — what's next

The natural extension is a multi-agent system that consumes the MCP tools as its memory layer:

  • HR agent — owns query_hr_knowledge, handles employee Q&A.
  • Tech-support agent — owns query_tech_docs, handles API/SDK questions.
  • Research agent — owns query_research_papers, summarises and compares papers.
  • Product agent — owns query_product_knowledge, handles user-facing FAQ.
  • Coordinator agent — calls federated_query when the question is ambiguous, delegates to a specialist agent based on the answer's domain mix.

Because each domain is already its own MCP tool, the agent project starts with zero re-implementation of retrieval, ranking, or synthesis.


📜 License

MIT — see LICENSE for the full text. Sample documents under docs/ are entirely fictional and depict a made-up company called "Aurora Labs".

↑↓ navigate openesc close