calibre-web-mcp
Gives an AI assistant access to a Calibre-Web / Calibre-Web-Automated library: search and browse books, view details (authors, series, tags, formats, read state, shelves, description), list recent additions and shelves, mark books read/unread, create shelves and add/remove books, check e-mail/conversion task status, and send a book to the user's e-reader address.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
calibre-web-mcp
An MCP server that gives an AI assistant your Calibre-Web library, built for Calibre-Web-Automated (CWA): find books and look them up, see what is new, mark books read or unread, keep shelves, and send a book to your e-reader.
It logs in to Calibre-Web as one user and uses the same routes the web UI uses, so that user's permissions apply unchanged. It speaks MCP over streamable HTTP behind a bearer token and keeps nothing on disk. No tool deletes a book, edits metadata, or touches users or settings.
Tools
Read
Tool | |
| Search, or list the whole library; sorted by date added (newest first), title, author or series; paged. |
| The books added most recently. |
| Title, authors, series, tags, languages, publisher, dates, rating, formats with sizes, read and archived state, shelves, what can be sent to the e-reader, description. |
| This user's e-mail and conversion tasks: waiting, started, finished, failed. |
| The shelves the user can see, with book counts, and the magic shelves (read-only, rule-based). |
| The books on a shelf, a page at a time. |
Write
Tool | |
| Mark read or unread. Idempotent. |
| A private shelf, or a public one if the user may. Returns the existing shelf if there is one with that name. |
| Shelf membership. Idempotent; removing never touches the book. |
| E-mails the book to the e-reader address in the user's Calibre-Web profile. |
Annotations are honest: readOnlyHint on reads, and destructiveHint plus
openWorldHint on send_to_ereader, the one tool whose effect leaves the
library and cannot be taken back. A client can ask before that one.
search_books uses Calibre-Web's own search, which matches the query as one
piece of text inside a title, tag, series or publisher, or as words that all
appear in the authors' names. It does not combine fields: "dune herbert"
finds nothing, while "dune" or "frank herbert" do. The tool description says
so, so the model searches for one thing at a time.
Related MCP server: calibre-mcp
Running it
Requirements: a Calibre-Web or CWA instance, and Python 3.12+ with the
dependencies in pyproject.toml, or Nix:
nix run . # or: nix build, then ./result/bin/calibre-web-mcpThe server listens on MCP_LISTEN (default 0.0.0.0:8080), with MCP at /mcp
and GET /healthz. The health check needs no auth and returns no library
data. It answers ok only when Calibre-Web answers an authenticated request,
and 503 unavailable: <kind> otherwise. Every other request needs
Authorization: Bearer $MCP_BEARER_TOKEN.
Configuration
Variable | |
| Required, 16+ characters: the token MCP clients present. |
|
|
| Required: where this server reaches Calibre-Web, e.g. |
| Required: |
| Required: the Calibre-Web user this server acts as. |
| Header mode only: the header name, default |
| Form mode only: the user's password, or a file holding it. |
The server refuses to start, with a message naming the variable, when a required setting is missing or when the settings mix the two modes.
Logging in: two modes
Header mode (CALIBRE_WEB_AUTH_MODE=header) uses Calibre-Web's reverse
proxy authentication: Admin › Edit Basic Configuration › Feature
Configuration › "Allow Reverse Proxy Authentication", with "Reverse Proxy
Header Name" set to the same value as CALIBRE_WEB_AUTH_HEADER. Every request
carries the header with CALIBRE_WEB_USER as its value, and Calibre-Web
treats each request as that user. With "Auto-create users from reverse proxy"
on, a name Calibre-Web does not know becomes a new account.
Security: in header mode the header is the credential. Anything that can reach Calibre-Web and set that header is logged in as whichever user it names. Run this server where it reaches Calibre-Web on a network nothing else can reach, such as a private container network shared only by the two. If Calibre-Web is also published through a reverse proxy, that proxy must remove the header from incoming requests.
Form mode (CALIBRE_WEB_AUTH_MODE=form) logs in through Calibre-Web's
login form once and then uses its session cookie (with "remember me"),
logging in again when the session ends. Calibre-Web rate-limits logins per
username (3 a minute, 40 a day), and reaching that limit locks the person out
of the web UI as well. So after a refused login, or one that got no answer,
this server waits a minute before it tries again, then two minutes, doubling
up to an hour, and reports auth_failed in the meantime. Each successful
login is a remembered session in Calibre-Web, which keeps it for 31 days.
Behind an MCP gateway
The endpoint is stateless and answers in JSON, so each POST to /mcp is
complete on its own. That suits gateways that open a session per call, such
as LiteLLM's MCP gateway. Register it as a streamable-HTTP server at
http://<host>:8080/mcp with the header Authorization: Bearer <token>, and
give the gateway's own keys access to it as you would to any other tool.
Point the gateway's health check, or the container's, at /healthz.
Safety model
The library's text is untrusted. Titles, descriptions, tags, series, publishers and shelf names often come from internet metadata sources. The server's instructions tell the model to read them as data and never to follow them.
Sending is guarded.
send_to_ereaderuses the route behind the book page's own send button, which mails the user's configured address and nothing else. It offers only the formats that page offers, and refuses while a send of the same book is still waiting or running, so a retried call does not mail the book twice. If the user has no e-reader address, it says so (no_ereader_address) without trying.Writes are idempotent where Calibre-Web's are not. Calibre-Web only toggles read status, so the tool reads the state first, toggles only when it differs, and reads it again to confirm. Adding a book that is already on a shelf, or removing one that is not, reports
changed: false.A small, fixed surface. No route that deletes, edits metadata, changes users or settings, or uploads is ever called.
No state, no background work. Nothing goes to disk. The only state in memory is the cookie jar, the CSRF token and the login backoff.
Calibre-Web behaviour it is built around
These come from reading CWA v4.0.8's source (cps/web.py, shelf.py,
helper.py, opds.py, tasks_status.py, the templates) and checking
against a running instance:
CSRF. Every POST needs a Flask-WTF token, and the token is valid only with the session cookie it was issued with. The server takes the token from the hidden
csrf_tokeninput that every page carries, sends it the way the web UI does (form field plusX-CSRFToken), and when Calibre-Web answers its generic 400 page it fetches a fresh token and retries once. That applies in header mode too: the header logs the user in, but POSTs still need the cookie and the token.Secure cookies over plain HTTP. With "use HTTPS" or OAuth configured, Calibre-Web marks its session cookie
Secure. A browser-style cookie jar would never send that cookie to an internalhttp://URL, which would break every POST. The server keeps its cookies itself.Read status only toggles, for any id.
POST /ajax/toggleread/<id>flips the state, and for an id with no book behind it, it records that non-existent book as read. The tool checks that the book exists (through its page) before it ever toggles.Book lists.
/ajax/listbooksis the JSON behind the book table. It joins authors with&and tags with,, and leaves datetime columns empty (atom_timestampholds the date added). Without a search, it converts the offset to a page number through a float, so some offsets are rounded away (offset 1 with limit 3 returns from 0). The server asks for a page size whose round trip lands exactly on the offset.Book details. No JSON endpoint has the per-user state: read, archived, shelves and send options. Those come from the book page, using element ids, classes and
data-*attributes rather than translated text, so the parsing works in any UI language. Exact sizes and dates come from/ajax/book/<uuid>. That endpoint takes HTTP Basic auth rather than the session, and it ignores the user's tag restrictions, so tags come from the page. In v4.0.8 the book page's XHR fragment (X-Requested-With) fails with a 500, so the server fetches the full page.Sending.
POST /send/<id>/<format>/<convert>queues an e-mail to every address in the user's "Send to eReader Email Address" profile setting.convert1 or 2 first converts MOBI or AZW3 to the format. Sending needs the download permission. The book page lists only formats under the configured attachment size limit, and the route answers[{type, message}]with a translated message. The result is a queued task. Its progress shows in/ajax/emailstat, which keeps tasks in memory (a restart clears them) and shows an admin everyone's tasks; the server keeps only its own user's.Shelves. Add and remove, sent as XHR, answer with plain status codes: 204 for done, 400 for already on the shelf or an invalid shelf or book, 410 for already removed, and 403 for not allowed. The 400 bodies are fixed English strings. Creating a shelf redirects to the new shelf on success. When creation is refused, the reason is a flash message. Viewing a shelf applies the sort order the user last chose for shelves in the web UI, just as the web UI does. Magic shelves are rule-based, so they are listed but never changed.
Plain Calibre-Web shares these routes, but not all of the page markup the server reads (CWA's book page, the profile flag for a configured e-reader). It is built and tested against CWA v4.0.8.
Tests
nix flake check -L # lint (ruff, nixfmt), then the package build, which runs the suiteThe suite runs in the package's checkPhase:
configuration: each mode, and each way of mixing or leaving out settings;
the parsers, on pages and JSON rebuilt from CWA v4.0.8's templates;
the HTTP session against a mocked Calibre-Web (respx): the header on every request, the form login and its backoff, CSRF refresh, Secure cookies, timeouts and failures;
every tool against that mock, checked for the routes it calls and how it reads their answers. That includes
send_to_ereader, which is only ever tested against the mock;the MCP layer through the SDK's own client: tool listing and annotations, bearer auth, health, typed errors, and one log line per call with no secrets in the log.
Without Nix: pip install -e '.[test]', then pytest.
License
MIT.
This server cannot be deployed
Maintenance
Related MCP Connectors
AI assistant integration for Leaf — track books, log reading sessions, and manage your library.
The media memory layer for AI agents and their humans. Your AI client can search your collection, add and log what you've finished, update ratings and lists, and find patterns across everything you've read, watched, played, and listened to.
Read and update your Hardcover library, progress, lists, and goals. Sign in with Hardcover OAuth.
Academic literature search, retrieval, and private library management on top of OpenAlex.
Related MCP Servers
- AlicenseBqualityCmaintenanceConnects AI agents to Calibre ebook libraries for searching, reading, and managing digital collections. It supports metadata updates, format conversion, and full-text content searches while providing granular permission controls for library access.723MIT
- AlicenseNot gradedqualityDmaintenanceEnables searching, reading, and managing a Calibre ebook library through natural language, with features like metadata search, full-text search, content extraction, and library management.1,175 npmApache 2.0
- FlicenseAqualityCmaintenanceEnables AI assistants to interact with BookLore self-hosted libraries, allowing natural language queries to search books, manage reading status, ratings, series, authors, and highlights.71-
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to interact with a local Calibre Content Server to search libraries, list books, retrieve ebook content, chapters, and more.18 npmMIT