search
Search your Calibre ebook library using natural language queries or field-specific metadata syntax to find books by content or attributes.
Instructions
Search the Calibre ebook library. Supports both full-text content search (default) and metadata search using field syntax.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search query. For full-text: use natural language. For metadata: use field syntax (author:Name, title:"Title"). | |
| limit | No | Maximum number of results (default: 50) | |
| fuzzy_fallback | No | Alternative search terms if exact query fails |
Implementation Reference
- server.js:823-864 (handler)Core handler function that executes the book search using Calibre's 'calibredb search' and 'list' commands, fetches metadata, and formats results with epub URLs.async searchBooksMetadata(query, limit = 50) { try { const searchResult = await this.runCalibreCommand(['search', '--limit', limit.toString(), query]); if (!searchResult.trim()) { return []; } const bookIds = searchResult.trim(); const idQuery = `id:${bookIds.replace(/,/g, ' OR id:')}`; const listResult = await this.runCalibreCommand([ 'list', '--fields', 'id,title,authors,series,tags,publisher,pubdate,formats,identifiers,comments', '--for-machine', '--search', idQuery ]); const books = JSON.parse(listResult || '[]'); return books.map(book => ({ id: book.id, title: book.title, authors: book.authors, series: book.series, tags: book.tags, publisher: book.publisher, published: book.pubdate, epub_url: this.createEpubUrl(book.authors, book.title, book.id), formats: book.formats ? book.formats.map(f => path.basename(f)) : [], full_formats: book.formats || [], has_text: book.formats ? book.formats.some(f => f.endsWith('.txt')) : false, description: book.comments ? book.comments.replace(/<[^>]+>/g, '').split('\n').slice(0, 2).join(' ').substring(0, 200) + '...' : null })); } catch (error) { this.log(`Metadata search failed: ${error.message}`); return []; } }
- server.js:968-986 (schema)Input schema defining parameters for the 'search' tool: query (required), limit, fuzzy_fallback.inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query. For full-text: use natural language. For metadata: use field syntax (author:Name, title:"Title").' }, limit: { type: 'integer', description: 'Maximum number of results (default: 50)', default: 50 }, fuzzy_fallback: { type: 'string', description: 'Alternative search terms if exact query fails' } }, required: ['query'] }
- server.js:966-987 (registration)Registration of the 'search' tool in the static tools array returned by 'tools/list' method.name: 'search', description: 'Search the Calibre ebook library. Supports both full-text content search (default) and metadata search using field syntax.', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search query. For full-text: use natural language. For metadata: use field syntax (author:Name, title:"Title").' }, limit: { type: 'integer', description: 'Maximum number of results (default: 50)', default: 50 }, fuzzy_fallback: { type: 'string', description: 'Alternative search terms if exact query fails' } }, required: ['query'] } },
- server.js:1094-1106 (handler)Tool dispatch handler in 'tools/call' that validates input, calls searchBooksMetadata, formats response, and sends MCP success response.case 'search': const query = args.query; const limit = args.limit || 50; if (!query) { this.sendError(id, -32602, 'Missing required parameter: query'); return; } const results = await this.searchBooksMetadata(query, limit); const mcpResult = this.formatResponse(results, query, 'search'); this.sendSuccess(id, mcpResult); break;
- server.js:864-866 (helper)Helper function to format search results into MCP-compatible response structure with text summary and structured results.} formatResponse(searchResults, query, searchType = 'search') {