Skip to main content
Glama
chepetime

Calibre Librarian MCP Server

by chepetime
README.md
# Calibre Librarian MCP Server

[![MCP](https://github.com/chepetime/calibre-librarian-mcp/actions/workflows/mcp.yml/badge.svg)](https://github.com/chepetime/calibre-librarian-mcp/actions/workflows/mcp.yml)

Model Context Protocol (MCP) server that surfaces your Calibre catalog to Claude via xmcp.

<!-- markdownlint-disable MD033 -->
<p align="center">
  <img src="assets/mcp-calibre.png" alt="Claude MCP view of Calibre Librarian" width="420" />
</p>
<!-- markdownlint-enable MD033 -->

## Requirements

- **Node.js**: `v24.13.0` (auto-managed if you use `nvm use`).
- **pnpm**: version `10.28.0` or newer.
- **Calibre CLI tools**: `calibredb` and `ebook-convert` must be installable on your PATH.
- **Environment variables**:
  - `CALIBRE_LIBRARY_PATH` – absolute path to your Calibre library directory.
  - `CALIBRE_DB_COMMAND` – location of the `calibredb` executable (e.g., `/opt/homebrew/bin/calibredb`).
  - `FAVORITE_SEARCH_ENGINE_URL` – base URL used when the server offers external book lookups (defaults to DuckDuckGo: `https://duckduckgo.com/?q=`).

## Setup

1. Clone and enter the repo:

   ```bash
   git clone https://github.com/chepetime/calibre-librarian-mcp.git
   cd calibre-librarian-mcp
   ```

2. Install dependencies with pnpm:

   ```bash
   pnpm install
   ```

3. Copy the sample environment file and fill in your paths:

   ```bash
   cp .env.example .env
   ```

Update the variables so the server can reach your Calibre library.

> The env is just for local development. For Claude Desktop, you'll need to configure the server in the Claude Desktop settings.

### Local development workflow

Use these scripts while iterating locally:

- `pnpm run dev` – watches files and serves the MCP server over stdio.
- `pnpm run lint` – type-checks and lints the project.
- `pnpm test` – runs the full unit test suite once.
- `pnpm test:watch` – reruns tests whenever source files change.

### Build for Claude Desktop (no Docker)

Follow this flow when you want Claude Desktop (or any MCP client) to run the compiled server directly:

1. Build the project so `dist/stdio.js` exists:

   ```bash
   pnpm run build
   ```

2. (Optional) Run the built output locally for a quick smoke test:

   ```bash
   pnpm start  # equivalent to: node dist/stdio.js
   ```

3. Configure Claude Desktop by editing `~/Library/Application Support/Claude/claude_desktop_config.json` (or via the in-app UI). Set `command` to `node`, include the absolute path to `dist/stdio.js` as the first `args` entry, and provide the required environment variables:

```json
{
  "globalShortcut": "",
  "mcpServers": {
    "calibre-librarian": {
      "command": "node",
      "args": ["/Users/you/path/to/calibre-librarian-mcp/dist/stdio.js"],
      "env": {
        "CALIBRE_LIBRARY_PATH": "<Absolute path to your>/Calibre",
        "CALIBRE_DB_COMMAND": "/opt/homebrew/bin/calibredb",
        "FAVORITE_SEARCH_ENGINE_URL": "https://duckduckgo.com/?q="
      }
    }
  },
  "preferences": {
    "quickEntryShortcut": "off",
    "menuBarEnabled": false
  }
}
```

After Claude Desktop reloads, it will list **calibre-librarian** as an available MCP server whenever MCP-enabled conversations start.

### Docker deployment

Run the server in a container with Calibre pre-installed when you prefer an isolated environment.

#### Quick start

```bash
# Build the image
docker build -t calibre-librarian-mcp .

# Run with your Calibre library mounted
docker run -it \
  -v /path/to/your/calibre/library:/library:ro \
  -e CALIBRE_LIBRARY_PATH=/library \
  calibre-librarian-mcp
```

#### Docker Compose

1. Copy and customize `docker-compose.yml`.
2. Set your library path and launch the stack:

   ```bash
   export CALIBRE_LIBRARY_PATH=/path/to/your/calibre/library
   docker compose up --build
   ```

#### Claude Desktop with Docker

To let Claude Desktop run the container directly, point it at `docker run`:

```json
{
  "mcpServers": {
    "calibre-librarian": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-v",
        "/path/to/your/calibre/library:/library:ro",
        "-e",
        "CALIBRE_LIBRARY_PATH=/library",
        "calibre-librarian-mcp"
      ]
    }
  }
}
```

**Note:** Remove `:ro` from the volume mount and add `-e CALIBRE_ENABLE_WRITE_OPERATIONS=true` to enable write operations.

## Tool Catalog & Examples

### Installing the MCP CLI

The examples below use the `mcp` CLI published by Anthropic. Install (or run) it with any of the following options:

- Global install (recommended if you call MCP tools frequently):

  ```bash
  npm install -g @anthropic-ai/mcp-cli
  # now `mcp --help` should work
  ```

- One-off execution without a global install:

  ```bash
  npx @anthropic-ai/mcp-cli --help
  # or
  pnpm dlx @anthropic-ai/mcp-cli --help
  ```

### CLI usage

All tools can be invoked from MCP Inspector or the CLI:

```bash
mcp call calibre-librarian <toolName> '<json payload>'
```

Prompts (e.g., `merge_duplicates`, `library_cleanup`, `search_library`) use the companion command:

```bash
mcp prompt calibre-librarian library_cleanup '{"focus":"missing covers"}'
```

Swap `library_cleanup` for any prompt listed below, and replace `calibre-librarian` with the server name you configured in `mcp.json`.

### Library Overview & Metadata

| Tool                 | Example                                                                     |
| -------------------- | --------------------------------------------------------------------------- |
| `list_sample_books`  | `mcp call calibre-librarian list_sample_books '{"limit":5}'`                |
| `get_book_details`   | `mcp call calibre-librarian get_book_details '{"bookId":42}'`               |
| `get_library_stats`  | `mcp call calibre-librarian get_library_stats '{}'`                         |
| `get_all_tags`       | `mcp call calibre-librarian get_all_tags '{"sortBy":"count","minCount":5}'` |
| `get_custom_columns` | `mcp call calibre-librarian get_custom_columns '{"includeDisplay":true}'`   |

### Search & Discovery

| Tool                          | Example                                                                                                       |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `search_books`                | `mcp call calibre-librarian search_books '{"query":"author:Sanderson and tag:fantasy","limit":10}'`           |
| `search_books_by_title`       | `mcp call calibre-librarian search_books_by_title '{"title":"stormlight","exact":false}'`                     |
| `search_authors_by_name`      | `mcp call calibre-librarian search_authors_by_name '{"name":"ng","sortBy":"count"}'`                          |
| `get_books_by_author`         | `mcp call calibre-librarian get_books_by_author '{"author":"Robin Hobb","sortBy":"series","ascending":true}'` |
| `get_books_by_author_id`      | `mcp call calibre-librarian get_books_by_author_id '{"authorId":17}'`                                         |
| `get_books_by_series`         | `mcp call calibre-librarian get_books_by_series '{"series":"The Expanse","exact":true}'`                      |
| `get_books_by_tag`            | `mcp call calibre-librarian get_books_by_tag '{"tag":"cozy mystery","limit":25}'`                             |
| `search_books_by_tag_pattern` | `mcp call calibre-librarian search_books_by_tag_pattern '{"pattern":"*punk","limit":10}'`                     |

### Full-Text & Content Access

| Tool                  | Example                                                                                               |
| --------------------- | ----------------------------------------------------------------------------------------------------- |
| `full_text_search`    | `mcp call calibre-librarian full_text_search '{"query":"\"winter is coming\"","matchAll":false}'`     |
| `search_book_content` | `mcp call calibre-librarian search_book_content '{"bookId":12,"query":"quantum","contextChars":120}'` |
| `fetch_excerpt`       | `mcp call calibre-librarian fetch_excerpt '{"bookId":8,"maxChars":1500}'`                             |

### Cleanup & Duplicate Workbench

| Tool                      | Example                                                                                                  |
| ------------------------- | -------------------------------------------------------------------------------------------------------- |
| `find_duplicates`         | `mcp call calibre-librarian find_duplicates '{"mode":"author_title","threshold":0.85}'`                  |
| `compare_books`           | `mcp call calibre-librarian compare_books '{"bookIds":[101,205],"fields":["title","series","formats"]}'` |
| `quality_report`          | `mcp call calibre-librarian quality_report '{"checks":["missing_cover","missing_tags"],"limit":20}'`     |
| `merge_duplicates` prompt | `mcp prompt calibre-librarian merge_duplicates '{"bookIds":[101,205]}'`                                  |
| `library_cleanup` prompt  | `mcp prompt calibre-librarian library_cleanup '{"focus":"missing covers"}'`                              |
| `search_library` prompt   | `mcp prompt calibre-librarian search_library '{"query":"hopepunk","searchType":"tag"}'`                  |

### Smart Maintenance Recipes

| Tool                    | Example                                                                                                                   |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `normalize_author_sort` | `mcp call calibre-librarian normalize_author_sort '{"preview":true,"limit":25}'`                                          |
| `bulk_retag`            | `mcp call calibre-librarian bulk_retag '{"query":"author:Sanderson","action":"add","tags":"cosmere","preview":true}'`     |
| `library_maintenance`   | `mcp call calibre-librarian library_maintenance '{"operation":"check"}'`                                                  |
| `missing_book_scout`    | `mcp call calibre-librarian missing_book_scout '{"readingList":"Dune\n1984\nThe Hobbit","searchEngine":"annas_archive"}'` |

### Metadata Editing & Custom Columns

> Requires `CALIBRE_ENABLE_WRITE_OPERATIONS=true`

| Tool                | Example                                                                                                                      |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `set_custom_column` | `mcp call calibre-librarian set_custom_column '{"bookId":42,"column":"#reading_status","value":"Started"}'`                  |
| `set_metadata`      | `mcp call calibre-librarian set_metadata '{"bookId":42,"title":"The Final Empire (Revised)","tags":["cosmere","favorite"]}'` |

### Setup & Configuration Tools

| Tool                     | Example                                                                      |
| ------------------------ | ---------------------------------------------------------------------------- |
| `generate_claude_config` | `mcp call calibre-librarian generate_claude_config '{"enableWrites":false}'` |

## Environment Variables

| Variable                          | Required | Default                      | Description                                          |
| --------------------------------- | -------- | ---------------------------- | ---------------------------------------------------- |
| `CALIBRE_LIBRARY_PATH`            | Yes      | —                            | Absolute path to your Calibre library directory      |
| `CALIBRE_DB_COMMAND`              | No       | `calibredb`                  | Path to the `calibredb` executable                   |
| `CALIBRE_COMMAND_TIMEOUT_MS`      | No       | `15000`                      | Timeout for calibredb commands in milliseconds       |
| `CALIBRE_ENABLE_WRITE_OPERATIONS` | No       | `false`                      | Enable metadata editing tools (`set_metadata`, etc.) |
| `FAVORITE_SEARCH_ENGINE_URL`      | No       | `https://duckduckgo.com/?q=` | Base URL for external book search links              |
| `MCP_SERVER_NAME`                 | No       | `Calibre Librarian MCP`      | Server name shown in MCP clients                     |

## Resources

The server exposes these MCP resources:

| URI                                | Description                          |
| ---------------------------------- | ------------------------------------ |
| `calibre://library/info`           | Library configuration and statistics |
| `calibre://library/custom-columns` | Custom column definitions            |
| `calibre://docs/inspector-guide`   | MCP Inspector verification guide     |

## Troubleshooting

### "calibredb: command not found"

The server can't find the Calibre CLI tools. Solutions:

- **macOS (Homebrew)**: `brew install calibre` or set `CALIBRE_DB_COMMAND=/Applications/calibre.app/Contents/MacOS/calibredb`
- **macOS (App)**: `CALIBRE_DB_COMMAND=/Applications/calibre.app/Contents/MacOS/calibredb`
- **Windows**: `CALIBRE_DB_COMMAND=C:\Program Files\Calibre2\calibredb.exe`
- **Linux**: Install Calibre via package manager, usually adds `calibredb` to PATH

### "Library path does not exist"

Verify your `CALIBRE_LIBRARY_PATH`:

```bash
# Check the path contains metadata.db
ls "$CALIBRE_LIBRARY_PATH/metadata.db"
```

### "Write operations are disabled"

Write tools (`set_metadata`, `set_custom_column`, `bulk_retag` with `preview:false`, etc.) require:

```bash
CALIBRE_ENABLE_WRITE_OPERATIONS=true
```

Add this to your `.env` file or Claude Desktop config.

### "Command timed out"

For large libraries, increase the timeout:

```bash
CALIBRE_COMMAND_TIMEOUT_MS=60000  # 60 seconds
```

### "Full-text search returns no results"

Calibre FTS must be enabled:

1. Open Calibre
2. Go to **Preferences → Searching**
3. Enable **Full text searching**
4. Click **Re-index all books**

### Server not appearing in Claude Desktop

1. Verify the config file path:
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
   - Linux: `~/.config/Claude/claude_desktop_config.json`

2. Check JSON syntax is valid

3. Restart Claude Desktop completely

4. Check Claude Desktop logs for errors

### Testing with MCP Inspector

Use the built-in verification guide:

```bash
# Start dev server
npm run dev

# In another terminal, run inspector
npx @anthropic/mcp-inspector
```

Or use the `generate_claude_config` tool to get your configuration.

## License

MIT

TDQS

A3.8/5.0

Scored across 26 tools

Disambiguation4/5

Most tools have distinct purposes, but there is some overlap between several search variants (search_books, search_books_by_title, search_books_by_tag_pattern) and between get_books_by_author and get_books_by_author_id. Descriptions help differentiate, but an agent might occasionally misselect when looking for a simple book lookup.

Naming Consistency5/5

All tools use a consistent snake_case verb_noun pattern (e.g., bulk_retag, compare_books, fetch_excerpt). The naming is predictable and makes the action-object relationship clear across the entire set.

Tool Count3/5

With 26 tools, the server is on the heavy side. While the scope of a Calibre library manager can justify many operations, some tools feel redundant (e.g., multiple search variants), and the count exceeds the typical well-scoped range of 3-15.

Completeness4/5

The tool surface covers most core library operations: search, retrieval, updates, duplicates, quality reports, and maintenance. Minor gaps include lack of direct CRUD for series or publishers, but these can be managed via metadata updates.

Maintenance

ActivityInactive
ResponsivenessNo issues