Skip to main content
Glama
monch1962
by monch1962

Calibre MCP

CI Python MCP Calibre Licence: MIT

既存の Calibre 電子書籍ライブラリのための読み取り専用 Model Context Protocol サーバーです。

Calibre MCP を使用すると、MCP 互換クライアントは書籍メタデータの検索、Calibre の全文インデックスのクエリ、書籍詳細の確認、ライブラリカテゴリの閲覧、関連書籍の発見ができます。metadata.db を直接読み取るのではなく、Calibre がサポートする calibredb コマンドラインインターフェースを使用します。

機能

  • Calibre の検索言語を使用したメタデータ検索

  • 一致するスニペット付きの全文検索

  • 個々の書籍の詳細なメタデータ

  • 最近追加された書籍

  • 著者、タグ、シリーズ、出版社、言語カテゴリ

  • 関連書籍の発見

  • 書籍、検索、ライブラリステータスのための MCP リソース

  • オプションの Calibre Content Server リンク

  • インメモリ TTL キャッシュ

  • Streamable HTTP トランスポート

  • Podman Quadlet デプロイメント

  • メタデータを変更する MCP ツールなし

Related MCP server: calibre-manager

利用可能なツール

ツール

目的

server_info

サーバー、Calibre、キャッシュ、ライブラリ設定を表示

library_status

書籍数と全文インデックス状態を表示

search_books

Calibre メタデータを検索

search_fulltext

インデックス化された電子書籍内を検索し、スニペットを返す

get_book_metadata

1冊の書籍の利用可能なすべてのメタデータを返す

list_recent_books

最近追加された書籍を一覧表示

list_categories

著者、タグ、シリーズ、出版社、言語を閲覧

find_related_books

著者、シリーズ、タグが重複する書籍を検索

clear_cache

インメモリ読み取りキャッシュをクリア

MCP リソース

URI

目的

calibre://library/status

ライブラリと全文インデックスの状態

calibre://book/{book_id}

書籍の詳細なメタデータ

calibre://search/{query}

メタデータ検索結果

要件

  • metadata.db を持つ Calibre ライブラリ

  • Calibre 9.x

  • Python 3.11 以降

  • Streamable HTTP をサポートする MCP クライアント

  • 同梱の Quadlet デプロイメント用の Podman と systemd

全文ツールを使用するには、Calibre の全文インデックスが有効で完了している必要があります。

Podman Quadlet によるクイックスタート

1. リポジトリをクローン

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

2. Calibre ライブラリを確認

提供された Quadlet は以下を前提としています:

/tank/media/Books

ライブラリデータベースが存在することを確認:

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

3. ライブラリの所有者を特定

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

quadlet/calibre-mcp.container を編集し、User= を返された数値の UID と GID に設定:

User=1000:1000

ホストのライブラリパスが異なる場合は、それも変更:

Volume=/tank/media/Books:/books

4. イメージをビルド

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

5. 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

systemctl enable calibre-mcp.service を実行しないでください。生成されたサービスは一時的なものです。Quadlet の [Install] セクションが起動時の依存関係を作成します。

6. デプロイメントを検証

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

コンテナ内の Calibre を確認:

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

デフォルトのエンドポイントは:

http://localhost:8008/mcp

MCP Inspector でテスト

npx @modelcontextprotocol/inspector

Streamable HTTP を選択し、接続先:

http://YOUR_SERVER:8008/mcp

メタデータ検索の例:

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

全文検索の例:

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

制限付き全文検索の例:

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

MCP クライアントを接続

サーバーが公開する Streamable HTTP エンドポイントを使用:

http://YOUR_SERVER:8008/mcp

クライアント設定の形式はさまざまです。クライアントの MCP ドキュメントを参照し、stdio やレガシー SSE ではなく Streamable HTTP を選択してください。

Calibre 検索の例

search_books は Calibre の検索式を受け入れます:

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

空のクエリは、結果制限の対象となるすべての書籍を返します。

オプションの Content Server リンク

既存の Calibre Content Server の URL を Quadlet に設定:

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

設定すると、メタデータ結果にブラウザとフォーマットダウンロードのリンクが含まれます。

設定

環境変数

デフォルト

説明

CALIBRE_LIBRARY_PATH

/books

コンテナ内の Calibre ライブラリ

CALIBREDB

calibredb

Calibre CLI へのパス

CALIBRE_COMMAND_TIMEOUT

120

コマンドのタイムアウト(秒)

CALIBRE_MAX_RESULTS

100

ツールが返す最大結果数

CALIBRE_CACHE_TTL

300

キャッシュの有効期間(秒)。0 に設定すると無効

CALIBRE_CACHE_SIZE

256

キャッシュされる最大エントリ数

CALIBRE_MAX_CONCURRENT_COMMANDS

4

同時実行される calibredb サブプロセスの最大数

CALIBRE_CONTENT_SERVER_URL

未設定

オプションの Content Server ベース URL

MCP_HOST

0.0.0.0

MCP HTTP バインドアドレス

MCP_PORT

8000

コンテナ内の MCP ポート

HOME

/tmp/calibre-home

Calibre 設定用の書き込み可能な場所

ライブラリマウントが書き込み可能な理由

Calibre は、ライブラリファイルシステムが大文字小文字を区別するかどうかを、ライブラリのルートにプローブファイルを一時的に作成して削除することで確認します。そのため、バインドマウントを読み取り専用にすることはできません。

このサーバーは、以下のような Calibre コマンドを呼び出すツールを公開しないため、機能的には読み取り専用のままです:

  • add

  • remove

  • set_metadata

  • add_format

  • remove_format

ライブラリを所有する同じ非特権 UID と GID でコンテナを実行してください。環境が特に必要としない限り、root として実行しないでください。

セキュリティ

  • ポート 8008 は、信頼できる LAN または Tailscale クライアントに限定してください。

  • エンドポイントをパブリックインターネットに直接公開しないでください。

  • このデプロイメントでは、Streamable HTTP は認証を追加しません。

  • より広範囲に公開する前に、認証付きリバースプロキシをサービスの前に配置してください。

  • 移動するコンテナタグではなく、リリースバージョンを固定してください。

  • 脆弱性を報告する前に SECURITY.md を確認してください。

レッドチーム強化(ラウンド1)

10 の敵対的攻撃ベクトルが失敗するテストで証明され、修正されました。 tests/attack_round1_test.py の各 TestAttack_* テストは、そのベクトルに対する恒久的な回帰フィクスチャです。

#

攻撃ベクトル

エントリポイント

防御

1

無制限のキャッシュキー — 数メガバイトのクエリがキャッシュエントリごとにメモリに保持される

search_books / search_fulltext

512 バイトを超えるキーは SHA-256 でハッシュ化される(_cache_key

2

無制限のキャッシュ値 — 大きな calibredb 出力(コメント、スニペット)がエントリごとに保持される

_run

1 MiB を超える値はキャッシュをバイパスする(_cache_put

3

server_info サブプロセスのハング — calibredb --version がタイムアウトなしで実行された

server_info

タイムアウトが適用され、TimeoutExpiredToolError

4

無効な calibredb 出力での未処理の JSONDecodeError → 生の内部エラー

_list_books / search_fulltext

_loads_json ラッパー → ToolError

5

数値以外の book-id キーでの未処理の ValueError → 生の内部エラー

_normalise_books

ラップ → ToolError

6

ライブラリメタデータを介した検索構文インジェクション — 著者、シリーズ、タグ内の引用符/バックスラッシュが生成されたクエリから抜け出す

find_related_books

_exact_match_clause は句の値から "\ を除去する

7

無制限のクエリ長 — MB 規模のクエリが calibredb とキャッシュに到達

search_books / search_fulltext

8192 文字を超えるクエリは ToolError で拒否される

8

同時フラッド下での無制限の一時的な calibredb stdout キャプチャ

_run

残存リスク — CALIBRE_COMMAND_TIMEOUT によって制限される。文書化済み

9

0.0.0.0 での認証なしエンドポイント

デプロイメント

受け入れられた姿勢 — SECURITY.md に文書化

10

情報開示 — ライブラリパス、Calibre バージョン

server_info / library_status

読み取り専用の知識サーバーとして受け入れ。文書化済み

このラウンドで検証された既知の安全な表面: シェルインジェクション(リスト argv、shell=True なし)、オプション値インジェクション(--sort-by/--categories/--restrict-to は Calibre のパーサーで先頭ダッシュの値を拒否)、リソース URI パストラバーサル(数値以外の ID は拒否)、結果制限のクランプ(_limit)、キャッシュの競合状態(ロックで保護)。

レッドチーム強化(ラウンド2)

6 つの入力形状検証ベクトルが証明され、修正されました。フィクスチャは tests/attack_round2_test.py にあります。

#

攻撃ベクトル

エントリーポイント

防御

11

無制限の book_id の大きさ — 内部で構築された id:{huge} クエリがラウンド1のクエリ上限を迂回し、MB規模のargvエントリとして calibredb に到達する

get_book_metadata / book_resource / find_related_books

_validate_book_id はIDを1..2³¹−1に制限する (_book)

12

無制限の categories 文字列 → MB規模のargv

list_categories

1024文字の上限 → ToolError

13

無制限の restrict_to 文字列 → MB規模のargv

search_fulltext

2048文字の上限 → ToolError

14

無制限の sort_by 文字列 → MB規模のargv

search_books

128文字の上限 → ToolError

15

反復不可能な formats メタデータ → TypeError → 生の500

_content_links

リスト/タプル以外のフォーマットは無視される。details リンクは引き続き返される

16

生成されたダウンロードリンクにおけるフォーマット拡張子のインジェクション (.., x;rm -rf)

_content_links

拡張子ホワイトリスト [a-z0-9]{1,10} — 一致しないフォーマットはスキップされる

レッドチーム強化(ラウンド3)

3つのエラーパス堅牢性ベクトルが実証され、修正された。フィクスチャは tests/attack_round3_test.py にある。

#

攻撃ベクトル

エントリーポイント

防御

17

過大なCSVフィールド(128 KiBのCSVフィールドサイズ上限を超過)→ 生の csv.Error → 500

list_categories

反復処理をラップ → ToolError

18

calibredb のリスト出力が非dictアイテムの配列 → search_books 内で AttributeError → 500

_normalise_books

非dictの配列アイテムを拒否 → ToolError

19

fts_search のdictペイロードに予期しないリスト値キーが含まれ、上限なしで通過 → レスポンス増幅

search_fulltext

すべてのリスト値キーを結果上限にスライスする

レッドチーム強化(ラウンド4)

2つの並行性/プロセスフラッドベクトルが実証され、修正された。フィクスチャは tests/attack_round4_test.py にある。

#

攻撃ベクトル

エントリーポイント

防御

20

並行する calibredb プロセスフラッド — N個の並列ツール呼び出しがN個のサブプロセスを生成(CPU/メモリ枯渇、Calibre DB競合)

_run

threading.Semaphore は実行中のコマンドを CALIBRE_MAX_CONCURRENT_COMMANDS(デフォルト4)に制限する。過剰申し込みの呼び出し → ToolError

21

server_info バージョンサブプロセスのフラッド — 呼び出しごとにキャッシュされないサブプロセスが1つ生成される

server_info

バージョン呼び出しは同じセマフォ経由でルーティングされる (_run_version)

レッドチーム強化(ラウンド5 — 最終検証)

新たな脆弱性はゼロ。カバレッジギャップ監査により、ラウンド1〜4でまだカバーされていないすべてのエントリーポイントを対象とする11件の検証テスト(tests/attack_round5_test.py)が追加された — search_resourcebook_resource(非数値、トラバーサル類似、範囲内)、status_resourcelibrary_statuslist_recent_booksclear_cachesearch_fulltext のリストペイロード、ゼロ/負のリミット、TTLゼロのキャッシュ無効化、空白クエリ。すべて即座に合格し、ラウンド1〜4の防御がツール/リソース全体の表面で有効であることが確認された。

2件のデプロイ姿勢に関するドキュメント指摘が SECURITY.md に記録された(コード変更なし):Containerfile には USER ディレクティブがない(Quadlet の外でビルドすると root として実行される。Quadlet は User=1000:1000 を設定する)、また Quadlet は SecurityLabelDisable=true を設定する(SELinux ラベル分離はオフ)。

ローカル開発

仮想環境を作成する:

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

テストを実行する:

pytest

lintチェックを実行する:

ruff check .

サーバーをローカルで起動する:

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

プロジェクトの状態

バージョン 1.0.0 は、個人および信頼できるネットワークへのデプロイに適している。公開APIは将来のマイナーリリースで追加のツールやリソースが増える可能性があるが、既存のツール名と引数の形状は、実用的な範囲で安定に保たれる。

コントリビューション

Issue とプルリクエストを歓迎します。CONTRIBUTING.md を参照してください。

ライセンス

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