Skip to main content
Glama
monch1962
by monch1962

Calibre MCP

CI Python MCP Calibre Licence: MIT

Un servidor de solo lectura del Model Context Protocol para una biblioteca de libros electrónicos Calibre existente.

Calibre MCP permite a los clientes compatibles con MCP buscar metadatos de libros, consultar el índice de texto completo de Calibre, inspeccionar los detalles de los libros, explorar las categorías de la biblioteca y descubrir libros relacionados. Utiliza la interfaz de línea de comandos calibredb compatible con Calibre en lugar de leer metadata.db directamente.

Características

  • Búsqueda de metadatos mediante el lenguaje de búsqueda de Calibre

  • Búsqueda de texto completo con fragmentos coincidentes

  • Metadatos detallados de libros individuales

  • Libros añadidos recientemente

  • Autores, etiquetas, series, editoriales y categorías de idioma

  • Descubrimiento de libros relacionados

  • Recursos MCP para libros, búsquedas y estado de la biblioteca

  • Enlaces opcionales al Calibre Content Server

  • Caché TTL en memoria

  • Transporte Streamable HTTP

  • Despliegue con Podman Quadlet

  • Sin herramientas MCP que modifiquen metadatos

Related MCP server: calibre-manager

Herramientas disponibles

Herramienta

Propósito

server_info

Muestra la configuración del servidor, Calibre, la caché y la biblioteca

library_status

Muestra el número de libros y el estado de indexación de texto completo

search_books

Busca metadatos de Calibre

search_fulltext

Busca dentro de los libros electrónicos indexados y devuelve fragmentos

get_book_metadata

Devuelve todos los metadatos disponibles de un libro

list_recent_books

Lista los libros añadidos más recientemente

list_categories

Explora autores, etiquetas, series, editoriales e idiomas

find_related_books

Encuentra libros con autores, series o etiquetas en común

clear_cache

Limpia la caché de lectura en memoria

Recursos MCP

URI

Propósito

calibre://library/status

Estado de la biblioteca y del índice de texto completo

calibre://book/{book_id}

Metadatos detallados de un libro

calibre://search/{query}

Resultados de búsqueda de metadatos

Requisitos

  • Una biblioteca de Calibre con metadata.db

  • Calibre 9.x

  • Python 3.11 o superior

  • Un cliente MCP compatible con Streamable HTTP

  • Podman y systemd para el despliegue Quadlet incluido

Las herramientas de texto completo requieren que el índice de texto completo de Calibre esté habilitado y completado.

Inicio rápido con Podman Quadlet

1. Clonar el repositorio

git clone https://github.com/monch1962/calibre-mcp.git
cd calibre-mcp

2. Confirmar tu biblioteca de Calibre

El Quadlet suministrado asume:

/tank/media/Books

Confirma que la base de datos de la biblioteca existe:

test -f /tank/media/Books/metadata.db && echo "Calibre library found"

3. Determinar el propietario de la biblioteca

stat -c 'uid=%u gid=%g owner=%U:%G' /tank/media/Books

Edita quadlet/calibre-mcp.container y establece User= con el UID y GID numéricos devueltos:

User=1000:1000

También cambia la ruta de la biblioteca del host si la tuya es diferente:

Volume=/tank/media/Books:/books

4. Construir la imagen

sudo podman build \
  --build-arg CALIBRE_VERSION=9.11.0 \
  -t localhost/calibre-mcp:1.0.0 .

5. Instalar el Quadlet

sudo mkdir -p /etc/containers/systemd

sudo cp quadlet/calibre-mcp.container \
  /etc/containers/systemd/calibre-mcp.container

sudo systemctl daemon-reload
sudo systemctl start calibre-mcp.service

No ejecutes systemctl enable calibre-mcp.service. El servicio generado es transitorio; la sección [Install] del Quadlet crea la dependencia de arranque.

6. Verificar el despliegue

sudo systemctl status calibre-mcp.service --no-pager
sudo journalctl -u calibre-mcp.service -n 100 --no-pager
sudo podman ps --filter name=calibre-mcp

Verifica Calibre dentro del contenedor:

sudo podman exec calibre-mcp \
  calibredb list \
  --with-library /books \
  --for-machine \
  --fields title \
  --limit 1

sudo podman exec calibre-mcp \
  calibredb fts_index status \
  --with-library /books

El endpoint predeterminado es:

http://localhost:8008/mcp

Probar con MCP Inspector

npx @modelcontextprotocol/inspector

Selecciona Streamable HTTP y conéctate a:

http://YOUR_SERVER:8008/mcp

Ejemplo de búsqueda de metadatos:

{
  "query": "author:asimov",
  "limit": 10
}

Ejemplo de búsqueda de texto completo:

{
  "query": "zero trust architecture",
  "limit": 10
}

Ejemplo de búsqueda de texto completo restringida:

{
  "query": "encryption",
  "limit": 10,
  "restrict_to": "search:tags:security"
}

Conectar un cliente MCP

Usa el endpoint Streamable HTTP expuesto por el servidor:

http://YOUR_SERVER:8008/mcp

Los formatos de configuración del cliente varían. Consulta la documentación MCP de tu cliente y selecciona Streamable HTTP en lugar de stdio o SSE heredado.

Ejemplos de búsqueda en Calibre

search_books acepta expresiones de búsqueda de Calibre:

author:asimov
title:"i robot"
tags:history
series:"Discworld"
publisher:penguin
languages:eng
rating:>=4

Una consulta vacía devuelve todos los libros, sujeto al límite de resultados.

Enlaces opcionales al Content Server

Establece la URL de tu Calibre Content Server existente en el Quadlet:

Environment=CALIBRE_CONTENT_SERVER_URL=http://mini-nas:8083

Cuando está configurado, los resultados de metadatos incluyen enlaces de navegador y de descarga de formatos.

Configuración

Variable de entorno

Predeterminado

Descripción

CALIBRE_LIBRARY_PATH

/books

Biblioteca de Calibre dentro del contenedor

CALIBREDB

calibredb

Ruta al CLI de Calibre

CALIBRE_COMMAND_TIMEOUT

120

Tiempo de espera del comando en segundos

CALIBRE_MAX_RESULTS

100

Máximo de resultados devueltos por una herramienta

CALIBRE_CACHE_TTL

300

Duración de la caché en segundos; establece 0 para desactivarla

CALIBRE_CACHE_SIZE

256

Máximo de entradas en caché

CALIBRE_MAX_CONCURRENT_COMMANDS

4

Máximo de subprocesos calibredb concurrentes

CALIBRE_CONTENT_SERVER_URL

unset

URL base opcional del Content Server

MCP_HOST

0.0.0.0

Dirección de enlace HTTP de MCP

MCP_PORT

8000

Puerto MCP dentro del contenedor

HOME

/tmp/calibre-home

Ubicación escribible para la configuración de Calibre

Por qué el montaje de la biblioteca es escribible

Calibre comprueba si el sistema de archivos de la biblioteca distingue entre mayúsculas y minúsculas creando y eliminando brevemente un archivo de prueba en la raíz de la biblioteca. En consecuencia, el montaje bind no puede montarse como solo lectura.

Este servidor sigue siendo funcionalmente de solo lectura porque no expone herramientas que llamen a comandos de Calibre como:

  • add

  • remove

  • set_metadata

  • add_format

  • remove_format

Ejecuta el contenedor con el mismo UID y GID sin privilegios que poseen la biblioteca. No lo ejecutes como root a menos que tu entorno lo requiera específicamente.

Seguridad

  • Mantén el puerto 8008 restringido a clientes de LAN o Tailscale de confianza.

  • No expongas el endpoint directamente a Internet público.

  • Streamable HTTP no añade autenticación en este despliegue.

  • Coloca un proxy inverso autenticado delante del servicio antes de una exposición más amplia.

  • Fija versiones de lanzamiento en lugar de usar una etiqueta de contenedor móvil.

  • Revisa SECURITY.md antes de informar de una vulnerabilidad.

Endurecimiento del equipo rojo (ronda 1)

Se demostraron diez vectores de ataque adversarios con pruebas fallidas y luego se corrigieron. Cada prueba TestAttack_* en tests/attack_round1_test.py es un dispositivo de regresión permanente para su vector.

#

Vector de ataque

Punto de entrada

Defensa

1

Clave de caché sin límite: una consulta de varios megabytes se retiene en memoria por entrada de caché

search_books / search_fulltext

Las claves de más de 512 bytes se codifican con SHA-256 (_cache_key)

2

Valor de caché sin límite: la salida grande de calibredb (comentarios, fragmentos) se retiene por entrada

_run

Los valores de más de 1 MiB omiten la caché (_cache_put)

3

Bloqueo del subproceso server_info: calibredb --version se ejecutó sin tiempo de espera

server_info

Se aplica tiempo de espera; TimeoutExpiredToolError

4

JSONDecodeError no controlado en la salida no válida de calibredb → error interno sin procesar

_list_books / search_fulltext

Envoltorio _loads_jsonToolError

5

ValueError no controlado en una clave de ID de libro no numérica → error interno sin procesar

_normalise_books

Envuelto → ToolError

6

Inyección de sintaxis de búsqueda mediante metadatos de la biblioteca: las comillas o barras invertidas en autores, series o etiquetas escapan de la consulta generada

find_related_books

_exact_match_clause elimina " y \ de los valores de la cláusula

7

Longitud de consulta sin límite: las consultas de escala MB llegan a calibredb y a la caché

search_books / search_fulltext

Las consultas de más de 8192 caracteres se rechazan con ToolError

8

Captura transitoria sin límite de stdout de calibredb bajo inundaciones concurrentes

_run

Riesgo residual: limitado por CALIBRE_COMMAND_TIMEOUT; documentado

9

Endpoint no autenticado en 0.0.0.0

despliegue

Postura aceptada: documentada en SECURITY.md

10

Divulgación de información: ruta de la biblioteca, versión de Calibre

server_info / library_status

Aceptada para un servidor de conocimiento de solo lectura; documentada

Superficies conocidas como seguras verificadas en esta ronda: inyección de shell (lista argv, sin shell=True), inyección de valores de opción (--sort-by/--categories/--restrict-to rechazan valores con guion inicial en el analizador de Calibre), traversal de rutas en URI de recursos (los IDs no numéricos se rechazan), limitación de resultados (_limit) y condiciones de carrera en la caché (protegida con bloqueo).

Endurecimiento del equipo rojo (ronda 2)

Se demostraron y corrigieron seis vectores de validación de forma de entrada; dispositivos en tests/attack_round2_test.py.

#

Vector de ataque

Punto de entrada

Defensa

11

Magnitud no acotada de book_id — la consulta id:{huge} construida internamente evita el límite de consultas de la ronda 1 y llega a calibredb como una entrada argv de escala MB

get_book_metadata / book_resource / find_related_books

_validate_book_id acota los ids a 1..2³¹−1 (_book)

12

Cadena categories no acotada → argv de escala MB

list_categories

Límite de 1024 caracteres → ToolError

13

Cadena restrict_to no acotada → argv de escala MB

search_fulltext

Límite de 2048 caracteres → ToolError

14

Cadena sort_by no acotada → argv de escala MB

search_books

Límite de 128 caracteres → ToolError

15

Metadatos formats no iterables → TypeError → 500 en bruto

_content_links

Los formatos que no son listas/tuplas se ignoran; el enlace details se sigue devolviendo

16

Inyección de extensión de formato en los enlaces de descarga generados (.., x;rm -rf)

_content_links

Lista blanca de extensiones [a-z0-9]{1,10} — los formatos que no coinciden se omiten

Endurecimiento del red team (ronda 3)

Tres vectores de robustez en rutas de error probados y corregidos; fixtures en tests/attack_round3_test.py.

#

Vector de ataque

Punto de entrada

Defensa

17

Campo CSV sobredimensionado (supera el límite de 128 KiB de tamaño de campo csv) → csv.Error en bruto → 500

list_categories

Iteración envuelta → ToolError

18

Salida de lista de calibredb como un array de elementos que no son dict → AttributeError en search_books → 500

_normalise_books

Elementos de array que no son dict rechazados → ToolError

19

El payload dict de fts_search con una clave inesperada con valor de lista pasa sin límite → amplificación de la respuesta

search_fulltext

Cada clave con valor de lista se recorta al límite de resultados

Endurecimiento del red team (ronda 4)

Dos vectores de concurrencia/inundación de procesos probados y corregidos; fixtures en tests/attack_round4_test.py.

#

Vector de ataque

Punto de entrada

Defensa

20

Inundación de procesos calibredb concurrentes — N llamadas de herramienta paralelas generan N subprocesos (agotamiento de CPU/memoria, contención de la base de datos de Calibre)

_run

threading.Semaphore limita los comandos en curso a CALIBRE_MAX_CONCURRENT_COMMANDS (por defecto 4); las llamadas sobresuscritas → ToolError

21

Inundación de subprocesos de versión de server_info — un subproceso no cacheado por llamada

server_info

La llamada de versión se enruta a través del mismo semáforo (_run_version)

Endurecimiento del red team (ronda 5 — verificación final)

Cero vulnerabilidades nuevas. Una auditoría de brechas de cobertura añadió 11 pruebas de verificación (tests/attack_round5_test.py) que ejercitan todos los puntos de entrada aún no cubiertos por las rondas 1–4 — search_resource, book_resource (no numérico, tipo traversal, dentro de rango), status_resource, library_status, list_recent_books, clear_cache, payloads de lista de search_fulltext, límites cero/negativos, TTL cero desactivación de caché y consultas de solo espacios en blanco. Todas pasaron de inmediato, confirmando que las defensas de las rondas 1–4 se mantienen en toda la superficie de herramientas/recursos.

Se registraron dos hallazgos de documentación sobre la postura de despliegue en SECURITY.md (sin cambios de código): el Containerfile no tiene directiva USER (se ejecuta como root cuando se construye fuera del Quadlet, que establece User=1000:1000), y el Quadlet establece SecurityLabelDisable=true (la separación de etiquetas SELinux está desactivada).

Desarrollo local

Crea un entorno virtual:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install pytest ruff

Ejecuta las pruebas:

pytest

Ejecuta las comprobaciones de lint:

ruff check .

Inicia el servidor localmente:

export CALIBRE_LIBRARY_PATH="/path/to/Calibre Library"
python server.py

Estado del proyecto

La versión 1.0.0 es adecuada para despliegues personales y en redes de confianza. La API pública puede incorporar herramientas y recursos adicionales en futuras versiones menores, mientras que los nombres de herramientas y las formas de los argumentos existentes se mantendrán estables siempre que sea práctico.

Contribuciones

Las issues y las pull requests son bienvenidas. Consulta CONTRIBUTING.md.

Licencia

Publicado bajo la Licencia MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enables querying and managing Calibre libraries via chat by interacting with the Calibre content server over HTTP. It allows users to search for books, update metadata, manage authors and tags, and handle book file uploads or conversions.
    3
    BSD 3-Clause
  • A
    license
    A
    quality
    D
    maintenance
    An MCP server to manage and organize a Calibre ebook library, enabling metadata editing, search, conversion, and more through AI assistants.
    17
    5
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    A local stdio MCP server that enables AI tools to search a self-hosted Calibre library over SSH, supporting metadata queries, full-text search, and book details.
    7
    MIT