Imported from zeindev/ebook-knowledge-mcp (
AGENTS.md). Install upstream withnpx skills add zeindev/ebook-knowledge-mcp. Copyright stays with the author.
EBOOK-KNOWLEDGE-MCP
What this is
A Rust MCP server that turns ebooks into a queryable knowledge base. It
ingests EPUB, MOBI, AZW3, KFX, and text-based PDF files, chunks the text,
builds a BM25 full-text index (Tantivy) and a local vector index (fastembed,
ONNX), and answers questions with chapter citations through the ebook-
knowledge MCP tools: ingest_book, query_book, list_books, book_info,
promote_chunk, demote_chunk, pending_review, audit_log. A truth-audit layer
gates trust: chunks start unverified and only an operator decision promotes
them into verified-only retrieval. A md2pdf CLI command renders Markdown
to PDF via pdf_oxide (pure Rust, no external tools).
Where things live
- Source: /data/ebook-knowledge-mcp (this repo)
- Library data: ~/.epub-knowledge (EPUB_KNOWLEDGE_HOME overrides)
- Embedding model cache: ~/.cache/fastembed (FASTEMBED_CACHE overrides)
- MCP registration: /config.toml under [mcp_servers.ebook-knowledge]. Host defaults to open-grok (~/.opengrok); EPUB_KNOWLEDGE_MCP_HOST and EPUB_KNOWLEDGE_MCP_HOME override the CLI name and home dir (see src/install.rs).
- Skill: .opengrok/skills/ebook-knowledge/SKILL.md in this repo (mirrored at skills/ebook-knowledge/SKILL.md and installed to /skills/ebook-knowledge/SKILL.md)
Architecture
- src/extract.rs: opens any supported format. boko reads EPUB/MOBI/AZW3/KFX through one Book::open; KFX is converted to a temp epub first because its raw bytes are not HTML. PDFs are detected by magic bytes and read with pdf-extract; scanned PDFs (no text layer) are rejected with a clear error. Extensionless files are sniffed by container (zip -> epub/azw3/kfx, PalmDB BOOK/MOBI header -> mobi) and opened from a temp copy with the right extension.
- src/chunk.rs: splits chapters into paragraph-aligned chunks of roughly 1800 characters, carrying chapter id, title, and character offsets for citations. Chunks are cut only between paragraphs and never split mid-paragraph; the policy and citation model are documented in docs/chunking.md.
- src/embed.rs: lazy local embeddings (bge-small-en-v1.5, 384 dims) via fastembed; the model downloads once and caches in the home directory.
- src/bm25.rs: per-book Tantivy full-text index with English stemming.
- src/store.rs: SQLite-backed library persistence (books, rag_chunks, audit_events in library.db; per-book Tantivy indexes under tantivy//), cosine vector search, hybrid reciprocal-rank fusion, automatic migration from the legacy JSON layout, and the truth-audit operations (promote/demote/pending_review/audit_log, verified-only queries).
- src/truth.rs: the truth-audit types (SourceOfTruth, Decision, AuditEvent, PendingChunk).
- src/main.rs: rmcp stdio server exposing the eight tools, plus a standalone CLI mode (ingest/query/list/info/promote/demote/pending/audit/md2pdf).
Build and test
cargo build --release cargo test cargo clippy --all-targets cargo fmt --check
Cross-platform build (Linux/macOS/Windows): the repo ships the build/ system - one script per OS that installs missing deps, ensures Rust, builds Release, copies the binary to ./bin/, and removes target/. Run build/linux/build.sh, build/macos/build.sh, or build/windows/build.ps1.
Install: from the built binary run <binary> install. It copies itself to
~/.local/bin (EPUB_KNOWLEDGE_INSTALL_DIR overrides), registers the ebook-knowledge
MCP server via <host> mcp add (host CLI defaults to open-grok; override with
EPUB_KNOWLEDGE_MCP_HOST/EPUB_KNOWLEDGE_MCP_HOME), and writes the embedded
skill to /skills/ebook-knowledge/SKILL.md. uninstall reverses
it. The skill is embedded in the binary (src/install.rs), so the installed
copy is self-contained.
The binary is target/release/ebook-knowledge-mcp. With no arguments it speaks MCP over stdio; with a command it runs the CLI:
ebook-knowledge-mcp ingest ebook-knowledge-mcp query [mode] [k] [verified] ebook-knowledge-mcp list ebook-knowledge-mcp info ebook-knowledge-mcp promote [rank] ebook-knowledge-mcp demote [rank] ebook-knowledge-mcp pending [book] [limit] ebook-knowledge-mcp audit [limit] ebook-knowledge-mcp md2pdf <input.md> <output.pdf> [title] [author] ebook-knowledge-mcp install | uninstall
Query modes: hybrid (default, BM25 + vector fused), vector (semantic only), bm25 (exact keyword; works even before the embedding model downloads).
Typical agent flow
- The user wants information from a book.
- Check ebook-knowledge__list_books for the book id.
- If the book is not ingested, download it with the native metasearch tool (category "books" plus a download_dir, via Library Genesis) and note the saved path. Extensionless downloads are handled automatically.
- Call ebook-knowledge__ingest_book with the file path.
- Call ebook-knowledge__query_book with the question and answer using the returned passages, citing chapter titles. Use verified_only when the answer must rest on operator-audited facts (see Truth audit below).
Truth audit
The source-of-truth layer gates which facts are trusted. Every chunk carries a source_of_truth state (serialized snake_case) and a verified flag:
- unverified (0): freshly ingested; excluded from verified-only retrieval.
- operator_decision (1): the decision rank; the only rank that may promote or demote a chunk.
- verified_observation (2): promoted by an operator; the only state that passes verified-only retrieval.
Rules:
- Chunks start unverified. Only ebook-knowledge__promote_chunk with a decision_id promotes a chunk (rank defaults to operator_decision; any other rank is rejected with "promotion denied: operator decision required"). A model's own confidence, a second model's agreement, or a non-operator "looks right" are refused by design.
- ebook-knowledge__demote_chunk reverses a promotion (stale or wrong source), same operator gate.
- ebook-knowledge__pending_review is the operator queue of unverified chunks (limit 1-500, default 20; optional book scope).
- ebook-knowledge__audit_log is the append-only history (newest first, limit 1-1000, default 20): decision_id, book, chunk_id, actor, action, before/after snapshots, approved_by_operator, timestamp.
- Query hits carry each chunk's id, book, index, chapter_title, text, source_of_truth, and verified (plus score fields). verified_only=true restricts results to verified_observation chunks.
CLI equivalents: ebook-knowledge-mcp promote [rank], demote (same args), pending [book] [limit], audit [limit].
Notes
- Chunking policy: paragraph-aligned, never mid-paragraph; every chunk carries book, chapter, and character offsets as metadata. See docs/chunking.md.
- The library persists in SQLite under the library root (library.db), with per-book Tantivy indexes under tantivy//; legacy JSON libraries are migrated automatically on first open.
- Re-ingesting a file rebuilds its indexes in place.
- boko (the ebook reader) is GPL-3.0-or-later, so the crate itself is licensed GPL-3.0-or-later (see LICENSE). Tantivy is MIT and fastembed is Apache-2.0.
- Scanned PDFs would need OCR, which is intentionally not wired in.