calibre-mcp
Calibre MCP
기존 Calibre 전자책 라이브러리를 위한 읽기 전용 Model Context Protocol 서버입니다.
Calibre MCP를 사용하면 MCP 호환 클라이언트가 도서 메타데이터를 검색하고, Calibre의 전문(full-text) 인덱스를 조회하고, 도서 세부 정보를 확인하고, 라이브러리 카테고리를 탐색하고, 관련 도서를 찾을 수 있습니다. metadata.db를 직접 읽는 대신 Calibre가 지원하는 calibredb 명령줄 인터페이스를 사용합니다.
기능
Calibre 검색 언어를 사용한 메타데이터 검색
일치하는 스니펫이 포함된 전문(full-text) 검색
개별 도서의 상세 메타데이터
최근 추가된 도서
저자, 태그, 시리즈, 출판사 및 언어 카테고리
관련 도서 발견
도서, 검색 및 라이브러리 상태에 대한 MCP 리소스
선택적 Calibre Content Server 링크
인메모리 TTL 캐시
Streamable HTTP 전송
Podman Quadlet 배포
메타데이터를 변경하는 MCP 도구 없음
Related MCP server: calibre-manager
사용 가능한 도구
도구 | 용도 |
| 서버, Calibre, 캐시 및 라이브러리 구성 표시 |
| 도서 수 및 전문(full-text) 인덱싱 상태 표시 |
| Calibre 메타데이터 검색 |
| 인덱싱된 전자책 내부를 검색하고 스니펫 반환 |
| 한 권의 도서에 대해 사용 가능한 모든 메타데이터 반환 |
| 가장 최근에 추가된 도서 나열 |
| 저자, 태그, 시리즈, 출판사 및 언어 탐색 |
| 저자, 시리즈 또는 태그가 겹치는 도서 찾기 |
| 인메모리 읽기 캐시 지우기 |
MCP 리소스
URI | 용도 |
| 라이브러리 및 전문(full-text) 인덱스 상태 |
| 도서의 상세 메타데이터 |
| 메타데이터 검색 결과 |
요구 사항
metadata.db가 있는 Calibre 라이브러리Calibre 9.x
Python 3.11 이상
Streamable HTTP를 지원하는 MCP 클라이언트
포함된 Quadlet 배포를 위한 Podman 및 systemd
전문(full-text) 도구를 사용하려면 Calibre의 전문(full-text) 인덱스가 활성화되고 완료되어 있어야 합니다.
Podman Quadlet 빠른 시작
1. 저장소 클론
git clone https://github.com/monch1962/calibre-mcp.git
cd calibre-mcp2. 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/Booksquadlet/calibre-mcp.container를 편집하고 User=를 반환된 숫자 UID 및 GID로 설정합니다:
User=1000:1000호스트 라이브러리 경로가 다르면 변경합니다:
Volume=/tank/media/Books:/books4. 이미지 빌드
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.servicesystemctl 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/mcpMCP Inspector로 테스트
npx @modelcontextprotocol/inspectorStreamable HTTP를 선택하고 다음에 연결합니다:
http://YOUR_SERVER:8008/mcp메타데이터 검색 예시:
{
"query": "author:asimov",
"limit": 10
}전문(full-text) 검색 예시:
{
"query": "zero trust architecture",
"limit": 10
}제한된 전문(full-text) 검색 예시:
{
"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 링크
Quadlet에서 기존 Calibre Content Server의 URL을 설정합니다:
Environment=CALIBRE_CONTENT_SERVER_URL=http://mini-nas:8083구성되면 메타데이터 결과에 브라우저 및 형식 다운로드 링크가 포함됩니다.
구성
환경 변수 | 기본값 | 설명 |
|
| 컨테이너 내부의 Calibre 라이브러리 |
|
| Calibre CLI 경로 |
|
| 명령 타임아웃(초) |
|
| 도구가 반환하는 최대 결과 수 |
|
| 캐시 수명(초); |
|
| 최대 캐시 항목 수 |
|
| 최대 동시 |
| 설정되지 않음 | 선택적 Content Server 기본 URL |
|
| MCP HTTP 바인드 주소 |
|
| 컨테이너 내부의 MCP 포트 |
|
| Calibre 구성을 위한 쓰기 가능한 위치 |
라이브러리 마운트가 쓰기 가능한 이유
Calibre는 라이브러리 루트에 프로브 파일을 잠시 생성하고 삭제하여 라이브러리 파일 시스템이 대소문자를 구분하는지 확인합니다. 결과적으로 바인드 마운트는 읽기 전용으로 마운트할 수 없습니다.
이 서버는 다음과 같은 Calibre 명령을 호출하는 도구를 노출하지 않으므로 기능적으로 읽기 전용으로 유지됩니다:
addremoveset_metadataadd_formatremove_format
라이브러리를 소유한 동일한 권한 없는 UID 및 GID로 컨테이너를 실행하십시오. 환경에서 특별히 요구하지 않는 한 root로 실행하지 마십시오.
보안
포트
8008을 신뢰할 수 있는 LAN 또는 Tailscale 클라이언트로 제한하십시오.엔드포인트를 공개 인터넷에 직접 노출하지 마십시오.
이 배포에서 Streamable HTTP는 인증을 추가하지 않습니다.
더 넓은 노출 전에 서비스 앞에 인증된 리버스 프록시를 배치하십시오.
변경되는 컨테이너 태그 대신 릴리스 버전을 고정하십시오.
취약점을 보고하기 전에 SECURITY.md를 검토하십시오.
레드팀 하드닝(1차)
10가지 적대적 공격 벡터가 실패하는 테스트로 입증된 후 수정되었습니다.
tests/attack_round1_test.py의 각 TestAttack_* 테스트는 해당 벡터에 대한 영구 회귀 픽스처입니다.
# | 공격 벡터 | 진입점 | 방어 |
1 | 무제한 캐시 키 — 캐시 항목당 수 메가바이트 크기의 쿼리가 메모리에 유지됨 |
| 512바이트를 초과하는 키는 SHA-256으로 해시됨( |
2 | 무제한 캐시 값 — 항목당 대용량 |
| 1MiB를 초과하는 값은 캐시를 우회함( |
3 |
|
| 타임아웃 적용; |
4 | 잘못된 |
|
|
5 | 숫자가 아닌 book-id 키에 대한 처리되지 않은 |
| 래핑됨 → |
6 | 라이브러리 메타데이터를 통한 검색 구문 주입 — 저자, 시리즈 또는 태그의 따옴표/백슬래시가 생성된 쿼리를 벗어남 |
|
|
7 | 무제한 쿼리 길이 — MB 단위 쿼리가 |
| 8192자를 초과하는 쿼리는 |
8 | 동시 플러드 상황에서 무제한 임시 |
| 잔여 위험 — |
9 |
| 배포 | 수용된 자세 — SECURITY.md에 문서화됨 |
10 | 정보 공개 — 라이브러리 경로, Calibre 버전 |
| 읽기 전용 지식 서버에 대해 수용됨; 문서화됨 |
이번 라운드에서 검증된 알려진 안전 표면: 셸 주입(인자 목록 사용, shell=True 없음), 옵션 값 주입(--sort-by/--categories/--restrict-to는 Calibre 파서에서 선행 대시 값을 거부함), 리소스 URI 경로 탐색(숫자가 아닌 id는 거부됨), 결과 제한 클램핑(_limit), 캐시 경쟁 조건(락으로 보호됨).
레드팀 하드닝(2차)
6가지 입력 형태 검증 벡터가 입증되고 수정되었습니다. 픽스처는 tests/attack_round2_test.py에 있습니다.
# | 공격 벡터 | 진입점 | 방어 |
11 | 무제한 |
|
|
12 | 무제한 |
| 1024자 상한 → |
13 | 무제한 |
| 2048자 상한 → |
14 | 무제한 |
| 128자 상한 → |
15 | 반복 불가능한 |
| 리스트/튜플이 아닌 formats는 무시되고 |
16 | 생성된 다운로드 링크의 형식 확장자 주입 ( |
| 확장자 허용 목록 |
레드팀 강화 (3차)
오류 경로 견고성과 관련된 세 가지 벡터가 입증되고 수정되었습니다. 픽스처는
tests/attack_round3_test.py에 있습니다.
# | 공격 벡터 | 진입점 | 방어 |
17 | 128 KiB csv 필드 크기 제한을 초과하는 대형 CSV 필드 → 원시 |
| 반복이 래핑됨 → |
18 | dict가 아닌 항목의 배열로 된 |
| dict가 아닌 배열 항목 거부 → |
19 | 예기치 않은 리스트 값 키를 가진 |
| 모든 리스트 값 키가 결과 상한으로 슬라이스됨 |
레드팀 강화 (4차)
동시성/프로세스 플러드와 관련된 두 가지 벡터가 입증되고 수정되었습니다. 픽스처는
tests/attack_round4_test.py에 있습니다.
# | 공격 벡터 | 진입점 | 방어 |
20 | 동시 |
|
|
21 |
|
| 버전 호출이 동일한 세마포어를 통해 라우팅됨 ( |
레드팀 강화 (5차 — 최종 검증)
새로운 취약점은 0건입니다. 커버리지 공백 감사를 통해 14차에서 아직 다루지 않은 모든 진입점을 검증하는 테스트 11개
(tests/attack_round5_test.py)가 추가되었습니다 — search_resource, book_resource(비숫자, 경로 탐색형,
범위 내), status_resource, library_status, list_recent_books,
clear_cache, search_fulltext 리스트 페이로드, 0/음수 제한, TTL 0 캐시
비활성화, 공백 쿼리. 모든 테스트가 즉시 통과하여 14차 방어가 전체 도구/리소스 표면에 걸쳐 유지됨을 확인했습니다.
배포 자세와 관련된 문서상 발견 사항 두 가지가
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린트 검사를 실행합니다:
ruff check .서버를 로컬에서 시작합니다:
export CALIBRE_LIBRARY_PATH="/path/to/Calibre Library"
python server.py프로젝트 상태
버전 1.0.0은 개인 및 신뢰할 수 있는 네트워크 배포에 적합합니다. 공개 API는 향후 마이너 릴리스에서 추가 도구와 리소스를 얻을 수 있으며, 기존 도구 이름과 인자 형태는 실용적인 범위에서 안정적으로 유지됩니다.
기여
이슈와 풀 리퀘스트를 환영합니다. CONTRIBUTING.md를 참조하세요.
라이선스
MIT 라이선스에 따라 배포됩니다.
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for Project Gutenberg — 75,000+ public-domain ebooks with full plain-text retrieval.
MCP server for Russian books search, details, and recommendation candidates.
Read-only MCP server exposing a user ORANO library to their own AI agent.
Read-only MCP server for verified book recommendations and reading lists.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn 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.3BSD 3-Clause
- AlicenseAqualityDmaintenanceAn MCP server to manage and organize a Calibre ebook library, enabling metadata editing, search, conversion, and more through AI assistants.175MIT
- AlicenseNot gradedqualityDmaintenanceMCP server enabling LLMs to query a local Calibre Content Server for ebook metadata, chapters, and content in HTML or Markdown.17 npmMIT
- AlicenseAqualityDmaintenanceA 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.7MIT