MCP server to sync a Calibre / Calibre-Web-Automated library to BookFusion
BookFusion MCP has 8 tools with consistent naming (verb_noun pattern: list_, get_, check_, sync_) and complete input schemas. All tools have descriptions (avg 85 chars, within 10-1024 range). However, descriptions are minimal and lack context about when to use each tool or what happens on failure. Parameters are typed but lack detailed constraints (e.g., no enum for search filters, no explicit range validation for limit/offset). Output schemas are partially documented in code but not formally declared in tool metadata. Error handling returns dict with 'error' key but lacks recovery guidance. No tool annotations (readOnlyHint/destructiveHint) despite clear read/write distinction.
Look up a local book on BookFusion by bookfusion id, ISBN, or file digest.
Return full details about a single book in the local library.
Fetch upload limits (max filesize, etc.) from BookFusion.
Return basic info about the configured Calibre library.
List books from the local Calibre library.
Sync every book that matches the same filters as ``list_books``.
Upload (or update) a single book on BookFusion.
No tool annotations (readOnlyHint/destructiveHint/idempotentHint) despite clear semantic distinction between read-only tools (list_books, get_book, library_status, get_bookfusion_limits, check_book_in_bookfusion) and write tools (sync_book_to_bookfusion, sync_books_to_bookfusion, sync_all_books). LLMs cannot infer safety properties without explicit hints.
Error responses return {'error': str, 'status_code': int} but lack recovery guidance. When check_book_in_bookfusion returns {'error': 'no identifier and no file to digest'}, the LLM has no hint about what to do next (e.g., 'Ensure the book has an ISBN or a valid file format').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2026-07-28+ | v2 |
Sync several books, running up to ``BOOKFUSION_UPLOAD_THREADS`` in parallel.
Parameter descriptions lack constraint details. 'limit' accepts 1-500 but description only says 'default 50, max 500', no mention of minimum. 'search' is free-form string with no guidance on case sensitivity, partial matching, or field scope (title vs author).
Output schemas not formally documented in tool metadata. Code shows return types (dict[str, Any]) but LLMs cannot parse Python type hints from tool definitions. Responses include fields like 'metadata_digest', 'file_digest', 'upstream' without schema declaration.
Descriptions are minimal (50-75 chars avg) and lack context about when to use each tool. 'Look up a local book on BookFusion by bookfusion id, ISBN, or file digest' does not explain the lookup strategy selection logic or when each method is preferred.