minirag
by mck-s
README.md
# minirag
A self-hostable RAG system with no signup and no cost by default. Drop in your notes, specs, and docs; they get chunked and embedded locally; retrieve them through an MCP server your AI tools can call. Ships with an evaluation harness so retrieval quality is measured, not guessed.
## Quick start
```bash
cp .env.example .env
docker compose up
# api: http://localhost:3000/health
```
No API key needed — embeddings run locally.
## Try it now (without Docker)
```bash
pnpm install
pnpm ingest ./sample-context # dry-run: parse + chunk + report by doctype
```
## Ingest your context
Point the CLI at any file or folder and pass `--write`:
```bash
pnpm ingest /path/to/your/notes --write
```
Subfolder names become doctypes automatically (`spec/file.md` → doctype `spec`), or pass
`--doctype <name>` explicitly. Re-running on the same content is idempotent — it won't duplicate
chunks.
## How it works
```
files → chunk → embed → Postgres+pgvector → search → MCP tools → your AI client
↑
eval harness (measures retrieval quality)
```
Your context is organized by **doctype** (meeting-notes, spec, codebase, …) — folder names map to doctypes automatically, so retrieval can filter by type.
## Stack
TypeScript end to end. Postgres + pgvector, local embeddings (Transformers.js, `bge-small-en-v1.5`), Fastify API, MCP server. All free, all self-hostable, one language.
## Swapping the embedder
Local (default) is free and requires no signup. OpenAI/Voyage are opt-in behind the same
`Embedder` interface, for higher quality at the cost of an API key:
1. Set `EMBEDDER=openai` (or `voyage`) and the matching API key in `.env`.
2. The vector dimension changes with the model, so old chunks won't match the new one — there's no
automated migration, clear and re-ingest:
```bash
docker compose exec db psql -U minirag -d minirag -c "TRUNCATE chunks, documents RESTART IDENTITY CASCADE;"
pnpm ingest /path/to/your/notes --write
```
3. Re-run `pnpm eval run` to confirm quality didn't regress.
The embedder id is stored per chunk; retrieval checks it against the active embedder at query time
and refuses to mix models rather than silently corrupting search.
## Status
Core pipeline (ingest, retrieve, eval, MCP) is complete and verified — see the `docs/` for the full picture.
## Docs
| Doc | What |
|---|---|
| `setup.html` | Quick-start setup guide (5 steps) |
| `docs/mcp-client-setup.md` | MCP server configuration for Claude Code/Cursor |
| `docs/project-overview.md` | Full overview, principles, doc index |
| `docs/architecture.md` | Diagram, data flow, schema, boundaries |
| `docs/eval-strategy.md` | How quality is measured |
## Using with Claude Code
Procedural guides live as skills in `.claude/skills/` (ingest, retrieve, eval) and are invoked on demand when a task matches. See `docs/architecture.md` for the architecture boundaries and working conventions.
### MCP Server
Register the minirag MCP server with Claude Code:
```bash
claude mcp add-json minirag '{
"command": "pnpm",
"args": ["-C", "/path/to/minirag", "--filter", "@minirag/mcp", "start"],
"env": {
"DATABASE_URL": "postgresql://minirag:minirag@localhost:5432/minirag",
"EMBEDDER": "local",
"EMBEDDER_MODEL": "bge-small-en-v1.5",
"EMBEDDER_DIM": "384"
}
}' --scope project
```
This writes a project-scoped `.mcp.json` at the repo root. It bakes in your absolute repo path, so it's **gitignored, not committed** — each teammate runs the command above to generate their own. `~/.config/claude/mcp.json` is **not** read by current Claude Code versions — there's no `cwd` field in the schema, so `-C /path/to/minirag` pins pnpm's working directory instead. After adding, run `claude` (or `/mcp` → reconnect) to approve and connect the server. See `.mcp.example.json` for the shape of the generated file.
See `docs/mcp-client-setup.md` for detailed setup instructions.
### /minirag Command
Use the `/minirag` slash command to search the vector store and get grounded answers with citations:
```
/minirag how do I configure the embedder?
/minirag [spec] architecture decisions
/minirag [meeting-notes] who attended the sync?
```
The command calls the MCP `search_context` tool and returns answers grounded in retrieved chunks with source citations.
## Contributing
- `pnpm lint && pnpm typecheck` and `pnpm eval run` (fixture corpus, metrics must not regress) before opening a PR.
- If you changed chunking/embedder/rerank, include the before/after eval delta in the PR.
- To add a doctype: add its chunking strategy in `packages/core` (see `docs/architecture.md`), then add golden cases in `packages/eval/golden/<name>.yaml`.
- See `docs/architecture.md` for module boundaries: `core` depends on nothing internal; `ingest`/`retrieve` never import each other; `api` and `mcp` are the only entry points and never reimplement retrieval logic; `eval` tests the real MCP tools.
## License
MIT — see [LICENSE](./LICENSE).
minirag depends on third-party open-source packages — almost all permissively licensed (MIT,
Apache-2.0, ISC, BSD), with one exception: a prebuilt `libvips` binary (LGPL-3.0-or-later,
transitively pulled in via the embedding library's image-handling dependency, never invoked by
minirag's own text-only pipeline) — and, at runtime, downloads pretrained embedding model weights
from Hugging Face (`bge-small-en-v1.5` by default, MIT-licensed; `all-MiniLM-L6-v2` as an
alternative, Apache-2.0-licensed). Neither model's weights are vendored in this repo. See
[NOTICE](./NOTICE) for the attribution list and [THIRD_PARTY_LICENSES.md](./THIRD_PARTY_LICENSES.md)
for full third-party license text, including why the LGPL dependency doesn't affect this project's
own MIT license.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues