Skip to main content
Glama
rcarmo

python-umcp-calibre

by rcarmo

python-umcp-calibre

Calibre keeps its database, caches and filesystem state in the GUI process. python-umcp-calibre runs an MCP server in that process, so clients use Calibre's APIs and job machinery without opening metadata.db from a sidecar.

Version 0.3.3 provides the released plugin and an older read-only compatibility server. Mutations are tested against exactly Calibre 9.12.0; the plugin hides them on every other Calibre version.

Process boundaries

Component

Location

Interface

Library access

Calibre Interface Action plugin

plugins/calibre_umcp_plugin/

Streamable HTTP

Runs in the Calibre GUI process and uses the live database object

Read-only compatibility server

src/calibre_umcp/server.py

stdio or Streamable HTTP

Uses Calibre CLI commands, or the older JSON-RPC bridge when configured

JSON-RPC bridge helper

serve_bridge() in plugins/calibre_umcp_plugin/bridge.py

HTTP JSON-RPC

Kept for tests and older wiring; the plugin UI does not publish it

Inactive-library reads use Calibre's GuiLibraryBroker handles. They do not switch the visible GUI library. Explicit library switching goes through Calibre's GUI action and requires a generation guard plus SWITCH_LIBRARY:<alias> confirmation.

Related MCP server: access-calibre

HTTP endpoints

Server

Method and path

Authentication

Use

Released plugin

POST /mcp

Bearer token when configured

Streamable HTTP MCP endpoint

Released plugin

GET /health

None

Returns plugin, schema and toolset versions

Compatibility server

POST /mcp

Depends on the compatibility server deployment

Streamable HTTP MCP endpoint when started with --http

JSON-RPC helper

POST /rpc

Bearer token when configured

Older bridge protocol used by compatibility code and tests

JSON-RPC helper

GET /health

None

Basic helper-process liveness check

The released plugin endpoint is /mcp. CALIBRE_UMCP_BRIDGE_URL belongs to the compatibility client and expects the older /rpc endpoint.

Tool discovery

Start with capabilities_readonly(). Read list_libraries_readonly() before choosing a library, then search with a small result limit and fetch details for one selected book. Responses include schema_version and toolset_version; reconnect and refresh tools/list after either value changes.

Read-only tools

Tool

Inputs

Result

capabilities_readonly

None

Versions, limits, stable errors and a compact tool index

describe_tool_readonly

tool_name

Arguments and result notes for one exposed tool

bridge_status_readonly

None

Plugin version, active library alias and generation

list_libraries_readonly

None

Configured aliases, labels, availability and policy flags

search_books_readonly

query, limit, library, cursor

Bounded metadata rows with an opaque continuation cursor

get_book_metadata_readonly

book_id, library

Metadata for one library-scoped book ID

get_book_formats_readonly

book_id, library

Path-free format sizes, modification times and availability

inspect_book_format_readonly

book_id, format, library, include_text_sample=false

Bounded EPUB structure and content signals; no ebook text

assess_book_quality_readonly

book_id, library, optional formats

Score, reasons, warnings and structured inspection errors

compare_book_quality_readonly

left, right, policy

Two assessments and a non-mutating retention proposal

find_duplicates_readonly

library, limit, target_limit, cursor

One bounded pair-comparison segment

find_cross_library_duplicates_readonly

source and target aliases, limits, optional query and cursor

One bounded cross-library comparison segment

content_server_status_readonly

None

Authenticated content-server URL when it can be stated unambiguously

list_scheduled_news_readonly

None

Enabled or bridge-disabled recipe state, schedule, retained prior schedule, last download and customisation metadata

list_bridge_jobs_readonly

None

Bridge audit and job records

get_bridge_job_status_readonly

job_id

One bridge audit or job record

EPUB inspection accepts files up to 64 MiB and archives with at most 4,096 entries or 256 MiB of expanded data. It scans no more than 8 MiB of content and runs for at most five seconds. Assessment and comparison convert supported inspection failures into grade: unknown results with inspection_errors; a direct inspection call returns the corresponding stable error.

Duplicate searches are segmented. Pass next_cursor back unchanged with the same arguments until it becomes null.

Mutation gate

capabilities_mutation() and all mutation tools appear only when every condition in this table holds:

Condition

Required state

Calibre runtime

Exactly 9.12.0

UI token

Saved in the plugin configuration

Mutation setting

Enable implemented mutation tools checked in the plugin UI

Environment override

CALIBRE_UMCP_BRIDGE_TOKEN, when set, matches the saved UI token

An environment-only token can authenticate HTTP requests. It cannot enable mutations. A mismatched environment override hides the mutation surface.

Metadata, format, cover, recipe-schedule, import, deletion, merge, conversion, copy, move, export and e-mail mutations accept expected_active_library and expected_active_generation. The bridge checks both before changing Calibre. Library switching requires both guards.

Mutation tools

Tool

Main inputs

Operation

capabilities_mutation

None

Mutation policy, stable errors and a compact tool index

update_book_metadata_mutation

book_id, changes

Updates validated standard or custom metadata with rollback

begin_import_attachment_mutation

filename, byte count, SHA-256, optional format

Opens a bounded staged upload

append_import_attachment_mutation

upload_handle, base64 chunk

Appends one bounded chunk

finalize_import_attachment_mutation

upload_handle

Verifies size and SHA-256, then returns a one-time staged handle

stage_import_attachment_mutation

filename, base64 content, optional format

One-call staging for small attachments

add_book_format_mutation

book_id, configured path or staged handle, format, replace

Adds or replaces one format

delete_book_format_mutation

book_id, format, allow_last_format

Removes one format; final-format deletion needs explicit permission

set_book_cover_mutation

book_id, configured path or remove=true

Replaces or removes a cover with rollback

add_book_mutation

configured path or staged handle, format, duplicate policy

Queues a native Calibre book import

download_scheduled_news_mutation

recipe urn

Queues an existing recipe through FetchNewsAction and Calibre's scheduler

update_scheduled_news_schedule_mutation

urn, days_of_week, hour, minute

Changes an existing weekly schedule through RecipeModel.schedule_recipe()

disable_scheduled_news_mutation

recipe urn

Disables future recurrence through RecipeModel.un_schedule_recipe() while retaining resume metadata

delete_books_mutation

IDs, dry-run flag, confirmation

Previews, then moves confirmed books to Calibre trash

merge_duplicates_mutation

survivor ID, source IDs, confirmation, cover options

Adds missing formats and merges metadata while retaining source records

convert_book_mutation

book ID, output format, options, result/export policy

Queues a native Calibre conversion job

copy_books_to_library_mutation

IDs, destination alias, duplicate policy, optional destination map

Copies books and verifies destination hashes

move_books_to_library_mutation

copy inputs plus dry-run and confirmation

Verifies the copy before moving source books to Calibre trash

save_book_to_disk_mutation

book ID, configured destination, options, overwrite flag

Queues Calibre's save-to-disk engine

email_book_mutation

book ID, configured recipient, existing format

Submits the format through Calibre's configured mail path

cancel_bridge_job_mutation

job_id

Requests cancellation at the next boundary supported by the native job

switch_library_mutation

alias, active-library guards, exact confirmation

Switches the visible GUI library with repair disabled

Metadata changes support title, authors, series, series_index, tags, identifiers, publisher, language, languages, comments, rating, pubdate, timestamp and custom columns through custom or #column_name.

Conversion options are limited to base_font_size, font_size_mapping, line_height, the four margin fields, output_profile, input_encoding, remove_paragraph_spacing, insert_blank_line, chapter, chapter_mark, page_breaks_before and pretty_print.

Save-to-disk options are limited to template, formats, save_cover, write_opf, save_extra_files, update_metadata, asciiize, to_lowercase, replace_whitespace and single_dir.

Controls and limits

Area

Behaviour

Import paths

Book, format and cover files must be below a UI-configured import root

Attachment staging

Opt-in root; 1 KiB to 1 GiB files; 60-second to 24-hour expiry; 8 MiB decoded chunks; SHA-256 verification; one-time handles

Export paths

Save and conversion exports must stay below a UI-configured export root

Library aliases

Must match ^[a-z][a-z0-9_-]{0,63}$; paths are omitted from MCP results

Copy and move

Destinations use configured aliases marked as copy targets; a move trashes sources after verified copying

Duplicate policies

reject, skip, add, merge_missing or replace; merge policies require explicit destination IDs

Scheduled news

Only registered builtin: or custom: URNs; one active job per URN; schedule days use Monday 0 through Sunday 6; disabling preserves the prior schedule and last-download marker in plugin preferences without changing the recipe, its customisation or library records

E-mail

Recipient and format must already exist in Calibre's mail configuration; automatic conversion is unsupported

Content server

Returns a URL only for a running authenticated server with a concrete or explicitly advertised host

Short mutations

GUI-thread database calls cannot be interrupted after they start

Long operations

Use Calibre jobs; audit records report partial work and delayed cancellation

Deletion

Permanent deletion is unsupported; book removal uses Calibre trash

Audit

Optional redacted JSONL file plus 10 to 10,000 in-memory records; default 500

update_scheduled_news_schedule_mutation() reads the existing schedule, calls Calibre's live recipe model, checks the stored result and verifies that recipe identity, title, last-download marker and customisation fields did not change. It restores the previous schedule if the update or verification fails.

disable_scheduled_news_mutation() calls Calibre's live RecipeModel.un_schedule_recipe() on the GUI thread. It refuses a queued or running recipe, verifies that the recipe remains registered and unscheduled, and persists its prior schedule and last-download marker in the plugin preferences. Repeating the request for a known disabled recipe returns changed=false; an unknown recipe returns NEWS_RECIPE_UNKNOWN. No MCP operation re-enables a recipe in this release.

content_server_status_readonly() withholds the URL when the server is stopped, authentication is disabled or a wildcard bind has no advertised host. Its reason_code states the failed condition.

Arbitrary recipients, automatic e-mail conversion, public temporary links and device actions are unsupported. The singular copy_book and move_book methods return explicit failures.

Build and test

The test suite uses Python's unittest runner:

PYTHONPATH=.:src python3 -W error::ResourceWarning -m unittest discover -s tests -v

Build the plugin ZIP with:

sh plugins/build-plugin.sh

The output is plugins/calibre-umcp-plugin.zip. The build copies umcp.py and umcp_shared.py from src/calibre_umcp, keeping one protocol implementation in the repository.

Install the plugin

Install from a checkout:

calibre-customize -a plugins/calibre-umcp-plugin.zip

linuxserver/calibre runs its profile as abc, so container installs normally use:

s6-setuidgid abc calibre-customize -a plugins/calibre-umcp-plugin.zip

Restart or reload Calibre after replacing the ZIP. The plugin starts MCP about one second after initialisation, once the active library is available. The µMCP Bridge menu has Status, Configure, Stop and Start commands if automatic startup fails.

Configure network access

Loopback is the default:

CALIBRE_UMCP_BRIDGE_HOST=127.0.0.1
CALIBRE_UMCP_PORT=9000

A container or LAN bind needs a token:

CALIBRE_UMCP_BRIDGE_HOST=0.0.0.0
CALIBRE_UMCP_PORT=9000
CALIBRE_UMCP_BRIDGE_TOKEN=<long-random-token>

Variable

Default

Effect

CALIBRE_UMCP_BRIDGE_HOST

127.0.0.1

MCP bind address; non-loopback binds require a token

CALIBRE_UMCP_PORT

9000

MCP HTTP port

CALIBRE_UMCP_BRIDGE_TOKEN

Unset

Authenticates /mcp; must match the UI token to expose mutations

CALIBRE_UMCP_CONTENT_SERVER_ADVERTISED_HOST

Unset

Concrete host returned for an authenticated content server bound to a wildcard address

CALIBRE_UMCP_AUDIT_PATH

Unset

Redacted JSONL audit file

Clients send Authorization: Bearer <token> to /mcp whenever a token is configured, including loopback connections. /health stays unauthenticated. Configure import roots, staging, export roots, library aliases, copy destinations, switching and mutation discovery in the plugin UI.

Compatibility server

The calibre-umcp command, equivalent to python -m calibre_umcp.server, runs the read-only compatibility server. It uses stdio without transport flags. --http --port N publishes Streamable HTTP at /mcp.

The supplied Dockerfile and docker-compose.yml build this compatibility server. They do not install the Interface Action plugin or expose its mutation tools.

Legacy mutator names such as convert_book, copy_book, move_book_destructive and email_book fail with directions to the corresponding plugin tool.

Design notes

Document

Subject

Architecture

Process and trust boundaries

Design

Implementation choices

Multiple libraries

Alias discovery, brokered reads, switching and duplicate checks

Calibre 9.12 API map

Audited read and mutation APIs

Plugin README

ZIP contents and container installation

The project is released under the MIT licence.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Read-only MCP server for accessing local Kindle library data, exposing tools to query profile, health, and book metadata.
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    Read-only MCP server that provides tools to search books, get book details, list authors, and view library statistics from a PostgreSQL database.
    5
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    A read-only MCP server for an existing Calibre ebook library, enabling metadata search, full-text search, and category browsing via the Model Context Protocol.
    MIT