Comprehensive reference for all MCP tools and endpoints
CalibreMCP uses FastMCP 2.13+ with portmanteau tools - consolidated tools that handle multiple related operations through an operation parameter. This reduces tool count while maintaining full functionality.
Portmanteau tool that consolidates all book querying operations: search, list, find, get books by various criteria.
IMPORTANT: Users may use different verbs (search, list, find, query, get) but they all map to the same operation.
ALL of these user requests should use operation="search":
- "search books by [author]" →
query_books(operation="search", author="...") - "list books by [author]" →
query_books(operation="search", author="...") - "find books by [author]" →
query_books(operation="search", author="...") - "query books by [author]" →
query_books(operation="search", author="...") - "get books by [author]" →
query_books(operation="search", author="...") - "show me books by [author]" →
query_books(operation="search", author="...")
Rule: If the user wants to access/retrieve/discover books with filters (author, tag, publisher, etc.), use operation="search" regardless of which verb they use.
async def query_books(
operation: str, # "search", "list", "by_author", "by_series"
# Search parameters (for operation="search")
author: Optional[str] = None,
authors: Optional[List[str]] = None,
exclude_authors: Optional[List[str]] = None,
text: Optional[str] = None,
query: Optional[str] = None, # Alias for text
tag: Optional[str] = None,
tags: Optional[List[str]] = None,
exclude_tags: Optional[List[str]] = None,
series: Optional[str] = None,
exclude_series: Optional[List[str]] = None,
publisher: Optional[str] = None,
publishers: Optional[List[str]] = None,
has_publisher: Optional[bool] = None,
rating: Optional[int] = None,
min_rating: Optional[int] = None,
max_rating: Optional[int] = None,
unrated: Optional[bool] = None,
pubdate_start: Optional[str] = None,
pubdate_end: Optional[str] = None,
added_after: Optional[str] = None,
added_before: Optional[str] = None,
min_size: Optional[int] = None,
max_size: Optional[int] = None,
formats: Optional[List[str]] = None,
comment: Optional[str] = None,
has_empty_comments: Optional[bool] = None,
format_table: bool = False,
limit: int = 50,
offset: int = 0,
# For operation="by_author"
author_id: Optional[int] = None,
# For operation="by_series"
series_id: Optional[int] = None,
# For operation="list"
sort: str = "title",
) -> Dict[str, Any]-
operation="search"⭐ PRIMARY OPERATION- Use for ALL user requests to access books with filters
- Works with ANY verb: "search", "list", "find", "query", "get", "show me"
- Supports comprehensive filtering (author, publisher, year, tags, rating, etc.)
- Example:
query_books(operation="search", author="Conan Doyle")
-
operation="list"- Only use when user explicitly wants ALL books without filters
- Simple pagination with minimal filtering
- Example:
query_books(operation="list", limit=20)
-
operation="by_author"- Get books by numeric author_id (requires
author_idparameter) - For author names, use
operation="search"withauthorparameter instead - Example:
query_books(operation="by_author", author_id=42)
- Get books by numeric author_id (requires
-
operation="by_series"- Get books in a series by numeric series_id (requires
series_idparameter) - For series names, use
operation="search"withseriesparameter instead - Example:
query_books(operation="by_series", series_id=15)
- Get books in a series by numeric series_id (requires
Author Filters:
author: Filter by author name (case-insensitive partial match)authors: Filter by multiple authors (OR logic)exclude_authors: Exclude books by these authors
Text & Tags:
text/query: Search in title, author, tags, series, commentstag: Filter by single tagtags: Filter by multiple tags (OR logic)exclude_tags: Exclude books with these tags
Series:
series: Filter by series nameexclude_series: Exclude books in these series
Rating:
rating: Exact rating (1-5)min_rating: Minimum rating (1-5)max_rating: Maximum rating (1-5)unrated: Filter for unrated books only
Publisher:
publisher: Filter by publisher namepublishers: Filter by multiple publishershas_publisher: Filter books with/without publisher
Date Filters:
pubdate_start: Publication date start (YYYY-MM-DD)pubdate_end: Publication date end (YYYY-MM-DD)added_after: Date added after (YYYY-MM-DD)added_before: Date added before (YYYY-MM-DD)
File Filters:
min_size: Minimum file size in bytesmax_size: Maximum file size in bytesformats: List of formats to include (e.g., ["EPUB", "PDF"])
Other:
comment: Search in book comments onlyhas_empty_comments: Filter books with empty/non-empty commentsformat_table: Format results as pretty text table (boolean)
Pagination:
limit: Maximum results to return (default: 50)offset: Results offset for pagination (default: 0)
# User says: "list books by conan doyle"
result = await query_books(
operation="search",
author="Conan Doyle",
format_table=True
)
# Advanced search: author + publisher + year
result = await query_books(
operation="search",
author="Conan Doyle",
publisher="Penguin",
pubdate_start="1900-01-01",
pubdate_end="1930-12-31"
)
# Search with multiple filters (AND logic)
result = await query_books(
operation="search",
author="Agatha Christie",
tags=["mystery", "crime"],
min_rating=4,
exclude_tags=["horror"]
)
# Search by publisher with year range
result = await query_books(
operation="search",
publishers=["O'Reilly Media", "No Starch Press"],
pubdate_start="2023-01-01",
pubdate_end="2024-12-31"
)
# Search recently added books with rating
result = await query_books(
operation="search",
added_after="2024-01-01",
min_rating=4,
format_table=True
)
# List all books (simple operation)
result = await query_books(operation="list", limit=20)
# Get books by author ID
result = await query_books(
operation="by_author",
author_id=42,
limit=10
)
# Get books in a series
result = await query_books(
operation="by_series",
series_id=15
)Dictionary containing operation-specific results:
- For
operation="search": Paginated search results with total count, books list, optional table - For
operation="list": Simple book list with pagination - For
operation="by_author": List of books by author ID - For
operation="by_series": List of books in series order
Portmanteau tool that consolidates book management operations: add, get, update, delete.
async def manage_books(
operation: str, # "add", "get", "update", "delete"
book_id: Optional[str] = None,
file_path: Optional[str] = None,
metadata: Optional[Dict[str, Any]] = None,
# ... additional parameters based on operation
) -> Dict[str, Any]operation="add": Add a new book to the library (requiresfile_path)operation="get": Retrieve detailed book information (requiresbook_id)operation="update": Update book metadata and properties (requiresbook_id)operation="delete": Delete a book from the library (requiresbook_id)
# Add a book
result = await manage_books(
operation="add",
file_path="/path/to/book.epub",
metadata={"title": "My Book", "authors": ["Author Name"]}
)
# Get book details
result = await manage_books(
operation="get",
book_id="123",
include_metadata=True,
include_formats=True
)
# Update book metadata
result = await manage_books(
operation="update",
book_id="123",
metadata={"rating": 5, "tags": ["favorite"]}
)
# Delete a book
result = await manage_books(
operation="delete",
book_id="123",
delete_files=True
)Portmanteau tool for managing multiple Calibre libraries.
operation="list": List all available librariesoperation="switch": Switch to a different library (requireslibrary_name)operation="stats": Get statistics for a libraryoperation="search": Search across multiple libraries
# List all libraries
result = await manage_libraries(operation="list")
# Switch library
result = await manage_libraries(
operation="switch",
library_name="Main Library"
)
# Get library statistics
result = await manage_libraries(
operation="stats",
library_name="Main Library"
)
# Search across libraries
result = await manage_libraries(
operation="search",
query="python programming",
libraries=["Main Library", "IT Library"]
)Get complete metadata and file information for a specific book (standalone tool, not portmanteau).
async def get_book_details(book_id: int) -> BookDetailResponsebook_id(int): Calibre book ID to fetch details for
BookDetailResponse with complete book information:
- Basic metadata: title, authors, series, rating, tags
- Publication info: published date, languages, comments
- File information: available formats, download links
- System data: identifiers, last modified, cover URL
Test connection to Calibre server and get diagnostics.
async def test_calibre_connection() -> ConnectionTestResponseConnectionTestResponse with:
connected: Boolean connection statusserver_version: Calibre server versionlibrary_name: Primary library nametotal_books: Number of books in libraryresponse_time_ms: Connection response timeerror_message: Error details if connection failedserver_capabilities: List of supported features
Portmanteau tool for book viewer and file opening operations.
operation="open": Open a book in the viewer (requiresbook_id,file_path)operation="get_page": Get a specific page from a book (requiresbook_id,file_path,page_number)operation="get_metadata": Get comprehensive metadata for a book (requiresbook_id,file_path)operation="get_state": Get current viewer state (requiresbook_id,file_path)operation="update_state": Update viewer state (requiresbook_id,file_path)operation="close": Close a viewer session (requiresbook_id)operation="open_file": Open book file with system's default application (requiresbook_id,file_path)operation="open_random"⭐ NEW: Search for books matching criteria, randomly select one, and open it
Searches for books matching author/tag/series filters, randomly selects one, and opens it with the system's default application.
Parameters:
author(optional): Author name filter (e.g., "John Dickson Carr")tag(optional): Tag name filter (e.g., "mystery")series(optional): Series name filter (e.g., "Sherlock Holmes")format_preference(default: "EPUB"): Preferred file format
Note: At least one search filter (author, tag, or series) is required.
Returns:
{
"success": bool,
"book_id": int,
"title": str,
"author": str,
"file_path": str,
"format": str,
"message": str
}Usage Examples:
# Open a random book by author
result = await manage_viewer(
operation="open_random",
author="Dickson Carr"
)
# Open random mystery book
result = await manage_viewer(
operation="open_random",
tag="mystery"
)
# Open random book in series with PDF preference
result = await manage_viewer(
operation="open_random",
series="Sherlock Holmes",
format_preference="PDF"
)Portmanteau tool for metadata management and display.
operation="update": Update metadata for single or multiple books (requiresupdates)operation="organize_tags": AI-powered tag organization and cleanup suggestionsoperation="fix_issues": Automatically fix common metadata problemsoperation="show"⭐ NEW: Display comprehensive book metadata in formatted popup/modal
Searches for a book by title or author, retrieves comprehensive metadata, and displays it in a formatted HTML popup (optional).
Parameters:
query(required): Search query (title or partial title) - e.g., "Gormenghast"author(optional): Author name filter - e.g., "Mervyn Peake"open_browser(default: True): Whether to open metadata in browser popup
Returns:
{
"success": bool,
"book_id": int,
"title": str,
"author": str,
"metadata": dict, # Complete metadata dictionary
"html_path": Optional[str], # Path to HTML file if open_browser=True
"formatted_text": str # Formatted text representation
}Usage Examples:
# Show metadata for a book (opens HTML popup)
result = await manage_metadata(
operation="show",
query="Gormenghast"
)
# Show metadata by author
result = await manage_metadata(
operation="show",
author="Peake"
)
# Show metadata without browser popup
result = await manage_metadata(
operation="show",
query="Gormenghast",
open_browser=False
)
# Display formatted text
if result["success"]:
print(result["formatted_text"])manage_smart_collections: Create, update, delete, query smart collectionsmanage_users: User management and authentication operations- Export tools:
export_books_csv,export_books_json,export_books_html,export_books_pandoc
Individual book result from search operations.
class BookSearchResult(BaseModel):
book_id: int
title: str
authors: List[str]
series: Optional[str] = None
series_index: Optional[float] = None
rating: Optional[int] = None # 1-5 scale
tags: List[str] = []
languages: List[str] = ["en"]
formats: List[str] = [] # ["EPUB", "PDF", "MOBI", etc.]
last_modified: Optional[str] = None
cover_url: Optional[str] = NoneResponse from query_books search operations.
class LibrarySearchResponse(BaseModel):
results: List[BookSearchResult]
total_found: int
query_used: Optional[str] = None
search_time_ms: intComplete book information from get_book_details.
class BookDetailResponse(BaseModel):
book_id: int
title: str
authors: List[str]
series: Optional[str] = None
series_index: Optional[float] = None
rating: Optional[int] = None
tags: List[str] = []
comments: Optional[str] = None
published: Optional[str] = None
languages: List[str] = []
formats: List[str] = []
identifiers: Dict[str, str] = {} # ISBN, Goodreads, etc.
last_modified: Optional[str] = None
cover_url: Optional[str] = None
download_links: Dict[str, str] = {} # Format -> URL mappingServer connection test results.
class ConnectionTestResponse(BaseModel):
connected: bool
server_version: Optional[str] = None
library_name: Optional[str] = None
total_books: Optional[int] = None
response_time_ms: int
error_message: Optional[str] = None
server_capabilities: List[str] = []IMPORTANT: The default library is automatically loaded on server startup. Users don't need to manually load or switch libraries before querying books.
Priority order for auto-loading:
- Persisted library (from FastMCP 2.13 storage)
config.local_library_path(if set)- Active library from Calibre's config files
- First discovered library (fallback)
CalibreMCP communicates with Calibre's built-in REST API server.
http://localhost:8080/ajax/...
GET /ajax/interface-data/init- Server initialization and library infoGET /ajax/search- Library search with query parametersGET /ajax/books- Bulk book metadata retrievalGET /ajax/book/{id}- Individual book details
GET /get/cover/{id}- Book cover imageGET /get/{format}/{id}- Download book in specific formatGET /get/thumb/{id}- Thumbnail cover image
Supports HTTP Basic Authentication when enabled in Calibre server:
# Configuration
username: "your_username"
password: "your_password"CalibreMCP supports Calibre's native search syntax through the query_books tool.
# Use query_books with operation="search"
query_books(operation="search", author="Conan Doyle") # Author filter
query_books(operation="search", tag="science") # Tag filter
query_books(operation="search", series="Foundation") # Series filter
query_books(operation="search", publisher="O'Reilly") # Publisher filter
query_books(operation="search", min_rating=4) # Rating filterFilters in query_books use AND logic when combined:
author="X"ANDtag="Y"ANDmin_rating=4= All conditions must matchtags=["X", "Y"]= Books with tag X OR tag Y
# Date range filtering
query_books(
operation="search",
pubdate_start="2020-01-01",
pubdate_end="2024-12-31"
)
# File size filtering
query_books(
operation="search",
min_size=1048576, # 1 MB
max_size=10485760 # 10 MB
)
# Format filtering
query_books(
operation="search",
formats=["EPUB", "PDF"]
)title- Alphabetical by titleauthors- Alphabetical by author surnamerating- Highest rated firstdate- Most recently added firstpubdate- Most recently published firstseries- Series order
- Use specific filters (author, tag) instead of broad text searches
- Limit results to 50 or fewer for responsive UI
- Use
format_table=Truefor human-readable output - Cache frequent queries on client side
- Default: 60 requests per minute
- Burst limit: 10 concurrent requests
- Timeout: 30 seconds per request
- Cover images: ~100KB each
- Book metadata: ~2KB each
- Search results: Cache for 5 minutes
- Total cache: Limited to 50MB
- 200 - Success
- 401 - Authentication failed
- 404 - Calibre server not found / Book not found
- 500 - Calibre server internal error
- timeout - Request timeout (>30s)
Connection failed- Network connectivity issueAuthentication failed- Invalid username/passwordServer not found- Wrong URL or server not runningRequest timeout- Server overloaded or slow responseJSON decode error- Malformed server response
All MCP tools return valid responses even on errors:
- Empty result lists for search failures
- Error dictionaries with
success: falseand actionable error messages - Detailed suggestions for fixing issues
The Calibre webapp backend exposes REST endpoints (reservoir port 10720). See webapp/README.md.
| Endpoint | Method | Description |
|---|---|---|
/api/llm/models |
GET | List models (Ollama/LM Studio/OpenAI). Query: provider, base_url |
/api/llm/chat |
POST | Chat completion. Body: messages, model, stream, provider, base_url |
Config (backend .env): LLM_PROVIDER, LLM_BASE_URL, LLM_API_KEY
/api/books/- List, add books/api/authors/,/api/series/,/api/tags/- List with pagination/api/libraries/list,/api/libraries/switch,/api/libraries/stats/api/search/- Search books/api/viewer/open-file- Open book in system default app/api/export/csv,/api/export/json- Export books
# Start MCP Inspector for interactive testing
python -m calibre_mcp.server
# Navigate to: http://127.0.0.1:6274from calibre_mcp.calibre_api import quick_library_test
import asyncio
# Quick connection test
result = asyncio.run(quick_library_test("http://localhost:8080"))
print(f"Connection successful: {result}")from calibre_mcp.config import CalibreConfig
config = CalibreConfig.load_config()
print(f"Server: {config.server_url}")
print(f"Auth configured: {config.has_auth}")Built with Austrian efficiency for comprehensive e-book library management. Uses FastMCP 2.13+ portmanteau tool pattern for optimal Claude Desktop integration.