Skip to main content
Glama
ispyridis

Calibre MCP Server

by ispyridis

fetch

Retrieve specific content from Calibre ebooks using epub URLs to access book sections directly from search results.

Instructions

Fetch specific content from a book using epub:// URL

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesepub:// URL from search results

Implementation Reference

  • Core handler function that implements the 'fetch' tool logic: parses epub URL, retrieves book metadata using calibredb, finds text file, extracts specified line range or default context, and returns structured content.
    async fetchByEpubUrl(url) { try { const { bookId, startLine, endLine } = this.parseEpubUrl(url); // Get book metadata const listResult = await this.runCalibreCommand([ 'list', '--fields', 'id,title,authors,formats', '--for-machine', '--search', `id:${bookId}` ]); const books = JSON.parse(listResult || '[]'); if (books.length === 0) { throw new Error('Book not found'); } const book = books[0]; const txtPath = book.formats?.find(f => f.endsWith('.txt')); if (!txtPath || !fs.existsSync(txtPath)) { throw new Error('No text format available for this book'); } // Extract content let content; if (startLine && endLine) { content = this.extractLineRange(txtPath, parseInt(startLine), parseInt(endLine)); } else { content = this.extractParagraphContext(txtPath, 1, 5); } return { book_id: book.id, title: book.title, authors: book.authors, content: content, url: url, line_range: { start: startLine ? parseInt(startLine) : null, end: endLine ? parseInt(endLine) : null } }; } catch (error) { throw error; } }
  • server.js:547-560 (registration)
    Registration of the 'fetch' tool in the tools/list response, including name, description, and input schema definition.
    { name: 'fetch', description: 'Fetch specific content from a book using epub:// URL', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'epub:// URL from search results' } }, required: ['url'] } }
  • Tool dispatch handler in tools/call method that validates input, calls fetchByEpubUrl, formats MCP-compliant response, and handles errors.
    case 'fetch': const url = args.url; if (!url) { this.sendError(id, -32602, 'Missing required parameter: url'); return; } try { const fetchResult = await this.fetchByEpubUrl(url); const contentText = `Content from '${fetchResult.title}' by ${fetchResult.authors}:\n\n${fetchResult.content}`; const mcpResult = { content: [{ type: 'text', text: contentText }], book_id: fetchResult.book_id, title: fetchResult.title, authors: fetchResult.authors, url: fetchResult.url }; this.sendSuccess(id, mcpResult); } catch (error) { this.sendError(id, -32603, error.message); } break;
  • Helper function to parse epub:// URLs into bookId and optional line range.
    parseEpubUrl(url) { // Remove epub:// prefix url = url.replace(/^epub:\/\//, ''); // Extract book ID const idMatch = url.match(/@(\d+)/); if (!idMatch) { throw new Error('Invalid epub URL format'); } const bookId = idMatch[1]; // Extract line range (optional) let startLine = ''; let endLine = ''; const rangeMatch = url.match(/#(\d+):(\d+)$/); if (rangeMatch) { startLine = rangeMatch[1]; endLine = rangeMatch[2]; } return { bookId, startLine, endLine }; }
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ispyridis/calibre-mcp-nodejs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server