Metadata-Version: 2.5
Name: grounded-rag-mcp
Version: 0.1.0
Summary: An MCP server that gives any LLM host grounded, cited retrieval over your own documents — hybrid BM25 + dense retrieval, cross-encoder reranking, and built-in eval.
Project-URL: Homepage, https://github.com/chetan1521/grounded-rag-mcp
Project-URL: Repository, https://github.com/chetan1521/grounded-rag-mcp
Author: Chetan C
License: MIT
License-File: LICENSE
Keywords: embeddings,hybrid-search,llm,mcp,rag,reranking,retrieval
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.10
Requires-Dist: mcp>=1.2
Requires-Dist: numpy>=1.24
Requires-Dist: pydantic>=2.5
Provides-Extra: dev
Requires-Dist: mypy>=1.11; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Provides-Extra: st
Requires-Dist: sentence-transformers>=2.2; extra == 'st'
Description-Content-Type: text/markdown

# grounded-rag-mcp

An **MCP server that gives any LLM host grounded, cited retrieval over your own documents** — hybrid retrieval (BM25 + dense), cross-encoder reranking, citations, and a built-in eval harness.

> Point it at a folder of documents. Your MCP host (Claude Desktop, an IDE, a custom agent) can then `search` and `answer` over them — grounded in the real text, with citations, and an honest "not in the documents" path.

[![CI](https://github.com/chetan1521/grounded-rag-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/chetan1521/grounded-rag-mcp/actions/workflows/ci.yml)

---

## Why

Most RAG-over-MCP examples are toys. This one is built production-flavored:

- **Hybrid retrieval** — BM25 (exact terms) + dense (semantics), fused with Reciprocal Rank Fusion.
- **Cross-encoder reranking** — precision on the top candidates without blowing latency.
- **Grounding + citations** — answers cite their sources; if the answer isn't in the docs, it says so.
- **Built-in eval** — measure retrieval quality (recall@k, MRR, hit-rate), not just vibes.
- **Local-first** — the default path runs with no external services or API keys.
- **Both transports** — stdio and Streamable HTTP.

## Status

🚧 Early development. Building in public, phase by phase (see `PROJECT_REQUIREMENTS.md`).

- [x] Phase 0 — scaffold, packaging, CI
- [x] Phase 1 — core retrieval (chunk → embed → BM25 + dense → RRF)
- [x] Phase 2 — MCP server (stdio) with `ingest` / `search`
- [x] Phase 3 — rerank + grounding + `answer` (via MCP sampling)
- [x] Phase 4 — tests, types, docs, resource + prompt
- [x] Phase 5 — Streamable HTTP transport + `evaluate_retrieval`
- [ ] Phase 6 — publish to PyPI

## Install

```bash
pip install grounded-rag-mcp            # lean, local-first default (no torch)
pip install "grounded-rag-mcp[st]"      # + sentence-transformers for semantic embeddings & reranking
```

## Tools

| Tool | What it does |
|---|---|
| `ingest_documents` | Chunk, embed, and index files or raw text into a named collection |
| `search` | Hybrid / dense / bm25 retrieval, optional rerank, per-stage scores |
| `answer` | Grounded, cited answer via MCP sampling; refuses when nothing is found |
| `list_collections` | List collections and chunk counts |
| `evaluate_retrieval` | hit_rate / MRR / recall@k on labeled cases |

Also exposes a resource (`rag://collections`) and a prompt (`grounded_answer`).

## Use it with an MCP host (e.g. Claude Desktop)

Add to your host's MCP config:

```json
{
  "mcpServers": {
    "grounded-rag": {
      "command": "grounded-rag-mcp"
    }
  }
}
```

Or run it directly:

```bash
grounded-rag-mcp            # stdio (default, for local hosts)
grounded-rag-mcp --http     # Streamable HTTP on 127.0.0.1:8000 (remote / multi-client)
```

## Use the retrieval engine as a Python library

```python
from grounded_rag_mcp.collection import Collection
from grounded_rag_mcp.embeddings import HashingEmbedder
from grounded_rag_mcp.ingest import load_texts
from grounded_rag_mcp.config import RetrievalConfig

col = Collection("kb", HashingEmbedder(dim=512))
col.add(load_texts(["The refund policy allows returns within 30 days of purchase."]))

for hit in col.retrieve("refund policy", RetrievalConfig(top_k=1)):
    print(hit.chunk.source, hit.score, hit.stage_scores)
```

## Development

```bash
pip install -e ".[dev]"
ruff check . && ruff format --check . && mypy src && pytest -q
```

See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md), [docs/BUILD_STORY.md](docs/BUILD_STORY.md),
and [PUBLISHING.md](PUBLISHING.md).

## License

MIT © Chetan C
