FastMCP server for conversational management of a local Calibre e-book library, with LanceDB RAG.
Project description
calibremcp
FastMCP 3.4+ server for conversational Calibre e-book library management.
Reads Calibre's metadata.db directly (local SQLite, no Content Server required),
indexes metadata for semantic search via LanceDB, and exposes portmanteau MCP tools
for natural-language library management.
Install
Requires Python 3.12+ and uv.
git clone https://github.com/moranon/calibremcp
cd calibremcp
uv sync
Configure
Create a .env file (see .env.example):
# Single library
CALIBRE_LIBRARY_PATH=/path/to/your/Calibre Library
# OR: root dir containing multiple sub-libraries
CALIBRE_LIBRARY_ROOT=/path/to/libraries
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"calibre-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/calibremcp", "run", "calibre-mcp"],
"env": {
"CALIBRE_LIBRARY_PATH": "/path/to/your/Calibre Library"
}
}
}
}
HTTP transport
MCP_TRANSPORT=http MCP_HOST=127.0.0.1 MCP_PORT=10720 uv run calibre-mcp
stdio (the default) uses no port.
MCP_PORTonly applies to thehttp/ssetransports and defaults to10720.
Tools
Most tools follow the portmanteau pattern — a single tool name with an operation
parameter. The table below lists the actual operations each handler accepts.
| Tool | Operations |
|---|---|
manage_libraries |
list, switch, stats, search, discover, test_connection |
query_books |
search, list, recent, by_author, by_series |
manage_books |
add, get, details, update, delete |
manage_metadata |
update, organize_tags, fix_issues, show |
manage_comments |
create, read, update, delete, append, replace |
manage_authors |
list, get, get_books, stats, by_letter |
manage_series |
list, get, get_books, stats, by_letter |
manage_tags |
list, get, create, update, delete, merge, statistics, find_duplicates, get_unused, delete_unused |
manage_publishers |
list, get, get_books, stats, by_letter |
manage_files |
convert, download, bulk |
manage_viewer |
open, open_file, open_random, close, get_metadata, get_page, get_state, update_state |
manage_analysis |
tag_statistics, duplicate_books, series_analysis, library_health, reading_stats, unread_priority |
manage_library_operations |
list_books, analyze_series, merge_series, fix_series_metadata |
export_books |
json, csv, html, pandoc, stats |
manage_import |
from_path, from_url, annas_search, annas_download, gutenberg_search, gutenberg_import, arxiv_search, arxiv_import |
manage_system |
status, health_check, help, tool_help, list_tools, hello_world |
manage_bulk_operations |
update_metadata, export, delete, convert |
manage_times |
added_in_range, published_in_range, recent_additions, stats_by_month_added, stats_by_month_published, date_stats |
manage_rag |
fts_index_build, fts_retrieve, metadata_index_build, metadata_search, status, job_status, list_jobs |
manage_recommendations |
similar_books, for_you, discover |
These tools are not portmanteaus (no operation parameter):
| Tool | Purpose |
|---|---|
search_fulltext |
Full-text search inside book content via Calibre's FTS database (query, limit, snippets) |
calibre_metadata_export_json |
Export full library metadata as JSON |
help_tool |
Usage guidance |
show_api_docs (a machine-readable tool catalog) is always registered. When
CALIBRE_PREFAB_APPS is enabled (the default), two MCP-App UI cards are also registered:
show_book_prefab_card and show_libraries_prefab_card.
RAG / semantic search
calibremcp includes two LanceDB backends, both stored inside the active library directory:
- FTS content index (
lancedb/books_rag) — semantic search over book passages using Calibre's full-text search data (fts_index_build/fts_retrieve). Requires FTS to be enabled in Calibre. - Metadata index (
lancedb_metadata/) — semantic search over titles, authors, tags, series, comments (metadata_index_build/metadata_search).
Index builds run as background jobs and return a job_id immediately:
manage_rag(operation="fts_index_build")
→ {"job_id": 1, "status": "pending"}
manage_rag(operation="job_status", job_id=1)
→ {"status": "done", "result": {"chunks_indexed": 42381}}
manage_rag(operation="fts_retrieve", query="murder mystery with a locked room")
Recommendations
manage_recommendations turns the metadata index into a recommendation engine — no
embedding model is loaded (it reuses the vectors stored at index-build time):
manage_recommendations(operation="similar_books", book_id=42) # more like this
manage_recommendations(operation="for_you") # picks from your ratings + read history
manage_recommendations(operation="discover", min_age_days=365) # unread hidden gems in your backlog
The taste profile is built from books rated ≥ min_rating stars (default 4) and books
marked read (CALIBRE_READ_COLUMN); both signals degrade gracefully when absent.
Requires the metadata index (manage_rag(operation="metadata_index_build")).
Environment variables
| Variable | Description |
|---|---|
CALIBRE_LIBRARY_PATH |
Absolute path to a single Calibre library directory |
CALIBRE_LIBRARY_ROOT |
Root directory containing multiple library sub-directories |
CALIBRE_LIBRARIES |
Comma-separated explicit list of library paths |
MCP_TRANSPORT |
stdio (default), http, or sse (deprecated) |
MCP_HOST |
HTTP/SSE host (default 127.0.0.1) |
MCP_PORT |
HTTP/SSE port (default 10720); ignored in stdio mode |
MCP_PATH |
HTTP endpoint path (default /mcp) |
MCP_CORS_ORIGINS |
HTTP CORS allow-list (comma-separated). Default: localhost only. * opens it (credentials disabled) |
RAG_OP_TIMEOUT |
Seconds before manage_rag retrieve/search/status time out (default 30) |
RAG_MODEL_LOAD_TIMEOUT |
Seconds allowed for the ONNX embedding model to load (default 300) |
CALIBRE_MAX_DOWNLOAD_MB |
Max size (MB) for any network import download (from_url, Anna's, arXiv, Gutenberg); default 500 |
CALIBRE_RAG_CHUNK_EXCLUDE_FORMATS |
Chunk-RAG only: comma-separated formats to skip (unset → excludes PDF) |
CALIBRE_RAG_MAX_BOOK_TEXT_CHARS |
Chunk-RAG: skip books_text rows longer than this |
CALIBRE_METADATA_COMMENT_MAX_CHARS |
Metadata RAG: cap on chars of the Comments field per book in embedding text |
CALIBRE_METADATA_STRIP_HTML |
Metadata RAG: 1 (default) strips HTML in comments; 0/false keeps raw |
CALIBRE_RAG_CACHE_DIR |
Override the fastembed model cache directory |
CALIBRE_DEFAULT_LIMIT |
Default search result limit (default 50) |
CALIBRE_MAX_LIMIT |
Maximum search result limit (default 200) |
CALIBRE_ANNAS_MIRRORS |
Comma-separated Anna's Archive mirror URLs |
CALIBRE_ANNAS_BROWSER_TIMEOUT |
Seconds for the optional headless-browser download fallback (default 180); see "Anna's Archive downloads" below |
CALIBRE_GUTENBERG_MIRROR |
Project Gutenberg base URL |
CALIBRE_PREFAB_APPS |
Set 0/false to skip the prefab MCP-App UI tools (default on) |
CALIBRE_BETA_TOOLS |
Legacy/no-op: the former beta tools are now first-class and always loaded |
Anna's Archive downloads
manage_import operation="annas_download" tries, in order: the member
fast-download API (set CALIBRE_ANNAS_SECRET_KEY), then free external mirror
links over plain HTTP. When those are all blocked by Anna's DDoS-Guard JS
challenge, it can fall back to a headless Chromium browser that solves the
challenge and drives the free slow-download flow.
That fallback is an optional extra (it is lazily imported — everything else works without it). From the project directory:
uv sync --extra browser # installs Playwright into the project venv
uv run playwright install chromium # one-time Chromium download (~150 MB)
If a CalibreMCP server is already running from this venv, stop it first —
uv syncrewrites the launcher scripts and Windows will block that while the server holds them open.
Tune the overall browser session timeout with CALIBRE_ANNAS_BROWSER_TIMEOUT
(seconds, default 180).
Safety / write policy
Close the Calibre GUI before writes. Calibre keeps metadata.db open and holds an
in-memory cache; if the GUI is running it can overwrite changes written underneath it.
How writes are routed:
- Core metadata (
title,sort,pubdate,series/series_index,authors,author_sort,tags,rating,comments) is written directly tometadata.dbvia SQLite (SQLAlchemy). The connection registers Calibre's owntitle_sort()function (db/database.py) so Calibre's triggers fire and derived sort fields stay consistent. Writes are read-back verified — a tool reportssuccess: Trueonly after confirming the change persisted. - Covers and fields not yet in the ORM (
isbn,publisher,languages) are not written directly; they route through thecalibredbsubprocess (with a timeout) or are reported as unsupported for manualcalibredbuse. - There is no second database: background job history for RAG index builds is held in memory (per server process) and cleared on restart.
The HTTP transport holds the active library in process-global state and is intended for
single-client / local use; it is not isolated for concurrent multi-client access (a
library switch changes the active library for the whole process). Use stdio for
Claude Desktop.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file calibremcp-3.0.0.tar.gz.
File metadata
- Download URL: calibremcp-3.0.0.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c03675733e6c50c6dcdea846096304b3724f5242874e6ce63d2a796ff015f03f
|
|
| MD5 |
52e58e17025bd0236e3dfacefe024b0c
|
|
| BLAKE2b-256 |
b8346eb59d21b7ebe12129f68724f553f0e34d323c72419c8c73674130a59ca7
|
Provenance
The following attestation bundles were made for calibremcp-3.0.0.tar.gz:
Publisher:
industrial-launch.yml on moranon/calibremcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
calibremcp-3.0.0.tar.gz -
Subject digest:
c03675733e6c50c6dcdea846096304b3724f5242874e6ce63d2a796ff015f03f - Sigstore transparency entry: 2151919984
- Sigstore integration time:
-
Permalink:
moranon/calibremcp@234162a096c98951c1568763867c39e4c2abe053 -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/moranon
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
industrial-launch.yml@234162a096c98951c1568763867c39e4c2abe053 -
Trigger Event:
push
-
Statement type:
File details
Details for the file calibremcp-3.0.0-py3-none-any.whl.
File metadata
- Download URL: calibremcp-3.0.0-py3-none-any.whl
- Upload date:
- Size: 359.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
413a9e93c6f09661e63bf90c0afc05d70501d11eede11c846db543cccb40c7bd
|
|
| MD5 |
c48be26b5789cf260fa93a708753e387
|
|
| BLAKE2b-256 |
3cd80208e0322cb688562b211acd0a0e20569cf2c77cfeecd4f82c1f95985277
|
Provenance
The following attestation bundles were made for calibremcp-3.0.0-py3-none-any.whl:
Publisher:
industrial-launch.yml on moranon/calibremcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
calibremcp-3.0.0-py3-none-any.whl -
Subject digest:
413a9e93c6f09661e63bf90c0afc05d70501d11eede11c846db543cccb40c7bd - Sigstore transparency entry: 2151919994
- Sigstore integration time:
-
Permalink:
moranon/calibremcp@234162a096c98951c1568763867c39e4c2abe053 -
Branch / Tag:
refs/tags/v3.0.0 - Owner: https://github.com/moranon
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
industrial-launch.yml@234162a096c98951c1568763867c39e4c2abe053 -
Trigger Event:
push
-
Statement type: