gurbani-mcp
by grusingh
README.md
# gurbani-mcp
A local, self-hosted tool for looking up and **verifying that a quote is
authentically from Sri Guru Granth Sahib (SGGS)**. This project covers SGGS
only (not other Banis).
It runs entirely on your own machine. No data leaves your computer unless you
choose to expose it to an AI client (Claude, ChatGPT, etc.), and even then,
only the query text you send is transmitted — never the underlying database.
- **Search** — keyword search with Gurbani concept expansion (e.g. "sewa" also matches "service", "selfless service")
- **Verify** — check a Gurmukhi quote against SGGS; get back the verbatim text + citation (Ang, Shabad, author), or a clear "not found"
- **Guard** — scan a block of text for every Gurmukhi quote in it and verify each one individually
- **Two ways to connect an AI client**: an [MCP](https://modelcontextprotocol.io) server (Claude Desktop, Claude Code, Cursor) and a plain HTTP API (ChatGPT via Custom GPT Actions, or any REST client)
Gurbani text is only ever returned from the source database — never
paraphrased, summarized, or generated. See [Quote Verification](#quote-verification--how-authenticity-is-guaranteed) below.
---
## Quick start
**Prerequisites:**
| Tool | Why | Install |
|------|-----|---------|
| [Docker](https://docs.docker.com/get-docker/) (or [Colima](https://github.com/abiosoft/colima) on macOS) | one-time database build | `brew install colima docker && colima start --cpu 4 --memory 8` |
| [uv](https://docs.astral.sh/uv/) | run the Python servers | `curl -LsSf https://astral.sh/uv/install.sh \| sh` |
```bash
git clone <this-repo-url> gurbani-mcp
cd gurbani-mcp
bash scripts/setup.sh
```
`setup.sh` builds `database/dist/banidb.sqlite` from the official
[Khalis Foundation BaniDB](https://github.com/KhalisFoundation/banidb-api)
Docker image (the dataset behind SikhiToTheMax), then installs Python
dependencies. It takes several minutes the first time (downloading + seeding
a ~640MB dataset); nothing about your database is uploaded anywhere.
**Verify it worked:**
```bash
bash scripts/test_search.sh "benefits of sewa"
uv run --extra dev pytest
```
---
## Connect to an AI client
### Claude Desktop / Claude Code (MCP)
Add this to your Claude Desktop config
(`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS,
`%APPDATA%\Claude\claude_desktop_config.json` on Windows):
```json
{
"mcpServers": {
"gurbani": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/gurbani-mcp", "python", "-m", "mcp_server.server"]
}
}
}
```
Restart Claude Desktop. You should see a 🔨 tools icon indicating the
`gurbani` server is connected, exposing `search_gurbani`, `verify_quote`,
`guard_text`, `get_shabad_by_ang`, `get_line`, and `get_shabad_by_line`.
For Claude Code, add the same server with:
```bash
claude mcp add gurbani -- uv run --directory /absolute/path/to/gurbani-mcp python -m mcp_server.server
```
### ChatGPT (Custom GPT Actions, via the HTTP API)
1. Start the HTTP API:
```bash
uv run uvicorn api_server.app:app --port 8421
```
2. ChatGPT Actions need a public HTTPS URL — they can't reach `localhost`.
The fastest way to get one without an account is a
[Cloudflare quick tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/trycloudflare/):
```bash
cloudflared tunnel --url http://localhost:8421
```
This prints a temporary `https://<random>.trycloudflare.com` URL. Treat it
as sensitive while it's live — anyone with the URL can query your local
API. It's meant for short sessions; for anything longer-lived, put an API
key or auth layer in front of it first (not included here — see
[Follow-ups](#follow-ups)).
3. In ChatGPT: **Explore GPTs → Create → Configure → Actions → Import from URL**,
and paste `https://<random>.trycloudflare.com/openapi.json`. ChatGPT will
pick up all the endpoints (`/api/search`, `/api/verify`, `/api/guard`, etc.)
automatically.
4. Give the GPT instructions like: *"When asked to verify a Gurbani quote,
always call the verify or guard action and quote its `source_text` back
verbatim — never answer from your own memory."*
---
## Example: verifying every quote in a document
```bash
curl -s "http://localhost:8421/api/guard" --get \
--data-urlencode "q=$(cat my_document.txt)" | jq
```
Returns every Gurmukhi span found in the text, each marked `verified`,
`verified_fuzzy` (found, but with minor punctuation/spelling differences), or
`not_found` — with the exact source citation (Ang, author, full line) for
anything that verified.
---
## Quote verification — how authenticity is guaranteed
Four layers, all sharing one matching core in `gurbani_rag/verify.py`:
1. **Build gate** (`scripts/validate_db.py`) — structural checks (row counts,
Ang coverage, no gaps/duplicates) run automatically during `setup.sh`, so
an incomplete or corrupted database can never reach runtime.
2. **Retrieval** — every search result comes straight from the source
database with its citation attached. Authentic by construction.
3. **Verify** (`verify_quote`) — exact match first (punctuation-agnostic),
then fuzzy match via FTS5 + rapidfuzz with a 0.90 confidence floor. Below
that: `not_found`. **The text returned is always the source's own — never
your input echoed back.**
4. **Guard** (`guard_text`) — scans arbitrary text for every Gurmukhi span
and verifies each one independently. This is the tool for auditing any
drafted or existing content.
See `CLAUDE.md` for the full architecture and schema.
---
## Optional: semantic search
The default search is keyword + concept expansion (works well, no extra
setup). An optional ChromaDB-based semantic index can also be built:
```bash
uv run python scripts/build_index.py
```
## Running tests
```bash
uv run --extra dev pytest
```
`tests/test_golden.py` checks known-authentic quotes verify at their correct
Ang, and known fakes are correctly rejected.
## Data attribution
Scripture text, translations, and transliterations: [Khalis Foundation BaniDB](https://github.com/KhalisFoundation/banidb-api) (SikhiToTheMax dataset).
BaniDB's compiled/proprietary form is not redistributed by this repo —
`database/dist/banidb.sqlite` is always built locally from the official
BaniDB Docker image (see `scripts/setup.sh`).
## Follow-ups (not built yet)
- The HTTP API has no authentication — fine for a short-lived tunnel session,
not for leaving it exposed long-term.
- No CI workflow yet.
## License
MIT — see [LICENSE](LICENSE).
TDQS
A4.4/5.0
Scored across 6 tools
Disambiguation5/5
Each tool serves a clearly distinct purpose: search, retrieval by Ang or line, expanding to full Shabad, and two levels of quote verification (single quote vs. full text audit). No two tools appear to do the same thing.
Naming Consistency5/5
All tool names follow a consistent verb_noun pattern with snake_case: search_, get_, verify_, guard_. The naming style is uniform and predictable.
Tool Count5/5
Six tools is well-scoped for a scripture server covering search, retrieval, and verification. Each tool earns its place with no redundancy.
Completeness5/5
The domain is covered end-to-end: search to find lines, retrieve by page or line, expand to full shabad, and verify quotes with the source. No obvious gaps for the stated purpose.
Maintenance
ActivityMaintained
ResponsivenessNo issues