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 server