daggerheart-ai
README.md
# daggerheart-ai
MCP server for semantic search over the Daggerheart SRD (~790 markdown files +
212 bestiary creatures), exposed to Claude Code during DnD session prep.
## Tools
- **search_srd** — semantic search across all rules, abilities, classes, equipment, and lore.
- **get_entry** — fetch a named entry by category + name (exact or partial match).
- **query_monsters** — filter adversaries + creatures by tier, role, thematic
`family`, difficulty range, attack range, keyword, and source. Bestiary
environments are excluded by default (`include_environments` to add them).
- **list_entries** — list every entry in a category.
## How it works
Content is indexed once into a local SQLite database (`srd.db`) with
`bge-small-en-v1.5` embeddings (384-dim) stored in `sqlite-vec`. Searches
use sqlite-vec KNN with a brute-force cosine fallback.
Embeddings are computed **fully on-device** via
[`fastembed`](https://github.com/Anush008/fastembed-js) (ONNX Runtime) — **no
API key, no proxy, no network**. The model (~30MB) downloads once to
`.fastembed_cache/` on first use, then everything runs offline.
## Setup
Prerequisites: Node 18+. No accounts, keys, or proxies.
```bash
npm install # uses .npmrc: Netflix registry + legacy-peer-deps
```
### SRD content
The `srd/` folder is git-ignored. Populate it from your vault copy, then index:
```bash
rsync -a --exclude='.git' --exclude='.build' --exclude='.github' \
'/path/to/daggerheart-srd/' srd/
npm run index # one-time; clears + rebuilds the index (first run downloads the model)
npm run build
```
Re-run `npm run index` after any SRD change.
## Register with Claude Code
Add to the relevant project/vault `.mcp.json`:
```json
"daggerheart": {
"type": "stdio",
"command": "node",
"args": ["/Users/chrisdhanaraj/projects/daggerheart-ai/dist/index.js"]
}
```
Restart Claude Code, then `/mcp` should show `daggerheart` connected with 4 tools.
## Scripts
| Script | Purpose |
|--------|---------|
| `npm run index` | Embed the SRD into `srd.db` (one-time / after SRD updates) |
| `npm run build` | Compile `src/` → `dist/` |
| `npm run dev` | Run the server from source via tsx |
| `npm start` | Run the built server (`dist/index.js`) |
## Notes
- **Never write to stdout** in the server — it is the JSON-RPC channel. Logs go to stderr.
- Embeddings are on-device (`fastembed` / bge-small-en-v1.5, 384-dim). The query
side uses `queryEmbed` (BGE instruction prefix); indexing uses `embed`.
- sqlite-vec `vec0` primary keys must be bound as `BigInt` in better-sqlite3.
- Rebuild (`npm run build`) after any change under `src/`.
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues