An MCP server for querying and managing an ebook library via chat.
Lyceum
An MCP server for querying and managing an ebook library via chat. Works with claude.ai and Claude Code.
Two storage backends are supported:
- Local — self-contained SQLite + file storage, no external dependencies. Books are uploaded through the web UI.
- Calibre — talks to a running Calibre content server over HTTP. No direct database access or CLI tools needed.
Setup
npm install
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
AUTH_PASSWORD |
Yes | — | Password for the OAuth authorization page |
STORAGE_MODE |
No | calibre |
Storage backend: calibre or local |
DATA_DIR |
No | /data |
Directory for local storage database and book files (local mode only) |
CONVERTER_URL |
No | — | URL of an ebook converter API for format conversion (local mode only) |
CONVERTER_API_KEY |
No | — | Bearer token for the converter API (local mode only) |
CALIBRE_SERVER_URL |
No | http://localhost:8080 |
URL of the Calibre content server (calibre mode only) |
CALIBRE_LIBRARY_ID |
No | — | Library ID for multi-library Calibre setups (calibre mode only) |
CALIBRE_USERNAME |
No | — | Username for Calibre content server Digest auth (calibre mode only) |
CALIBRE_PASSWORD |
No | — | Password for Calibre content server Digest auth (calibre mode only) |
BASE_URL |
No | http://localhost:3000 |
Public URL of this server (used for OAuth redirects and signed URLs) |
PORT |
No | 3000 |
Port to listen on |
Running
Local mode
AUTH_PASSWORD=your-secret STORAGE_MODE=local DATA_DIR=./data npm run dev
For production:
AUTH_PASSWORD=your-secret \
STORAGE_MODE=local \
DATA_DIR=/var/lib/lyceum \
BASE_URL=https://lyceum.yourdomain.com \
npm start
Calibre mode
AUTH_PASSWORD=your-secret npm run dev
For production:
AUTH_PASSWORD=your-secret \
CALIBRE_SERVER_URL=http://calibre:8080 \
BASE_URL=https://lyceum.yourdomain.com \
npm start
Importing from Calibre
To migrate an existing Calibre library into local storage, run the import script once before starting the server:
CALIBRE_SERVER_URL=http://calibre:8080 \
DATA_DIR=./data \
npm run import
This downloads all books and covers from the Calibre content server and stores them in the local SQLite database and file store.
Container
Pre-built images are available from GitHub Container Registry:
podman pull ghcr.io/matthewp/lyceum:latest
The container exposes port 3000. Mount a volume at /data to persist state across restarts:
podman run -d \
-p 3009:3000 \
-v lyceum-data:/data \
-e AUTH_PASSWORD=your-secret \
-e STORAGE_MODE=local \
-e BASE_URL=https://lyceum.yourdomain.com \
ghcr.io/matthewp/lyceum:latest
To use Calibre mode instead, swap STORAGE_MODE=local for CALIBRE_SERVER_URL=http://calibre:8080.
To build from source instead, the included Containerfile uses node:24-slim. Node 24 supports native TypeScript type stripping, so no build step is needed — the source runs directly with --experimental-strip-types.
podman build -t lyceum .
For sensitive values, use podman secrets:
printf 'your-secret' | podman secret create lyceum_auth_password -
Then reference them in a quadlet .container file:
Secret=lyceum_auth_password,type=env,target=AUTH_PASSWORD
Format Conversion
The convert_book MCP tool converts a book from one format to another (e.g. EPUB to MOBI). In local mode, this requires an external converter service:
CONVERTER_URL— base URL of the service (e.g.http://converter:8080)CONVERTER_API_KEY— optional Bearer token
The converter must accept POST /convert with a multipart form body containing a file field (the source file) and a format field (the target extension, e.g. mobi), and return the converted file as the response body.
In Calibre mode, conversion is handled by the Calibre content server directly.
MCP Tools
| Tool | Description |
|---|---|
list_books |
List books sorted by most recently added |
get_book |
Get full details for a book (authors, tags, series, formats, etc.) |
search_books |
Search books by title, author, tag, or series name |
list_authors |
List all authors with book counts |
list_tags |
List all tags with book counts |
list_series |
List all series with book counts |
list_books_by_series |
List all books in a series, ordered by series index |
get_view_link |
Get a signed URL to view a book's details page with cover and metadata (expires in 10 minutes) |
get_download_link |
Get a signed download URL for a book |
Tools (9)
list_booksList books sorted by most recently addedget_bookGet full details for a book (authors, tags, series, formats, etc.)search_booksSearch books by title, author, tag, or series namelist_authorsList all authors with book countslist_tagsList all tags with book countslist_seriesList all series with book countslist_books_by_seriesList all books in a series, ordered by series indexget_view_linkGet a signed URL to view a book's details page with cover and metadataget_download_linkGet a signed download URL for a bookEnvironment Variables
AUTH_PASSWORDrequiredPassword for the OAuth authorization pageSTORAGE_MODEStorage backend: calibre or localDATA_DIRDirectory for local storage database and book filesCALIBRE_SERVER_URLURL of the Calibre content serverBASE_URLPublic URL of this serverConfiguration
{"mcpServers": {"lyceum": {"command": "node", "args": ["/path/to/lyceum/index.js"], "env": {"AUTH_PASSWORD": "your-secret", "STORAGE_MODE": "calibre"}}}}