Skip to main content
Glama

readwise_topic_search

Search documents in Readwise Reader by topic using regex matching on titles, summaries, notes, and tags to find relevant content.

Instructions

Search documents in Readwise Reader by topic using regex matching on title, summary, notes, and tags

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
searchTermsYesList of search terms to match against document content (case-insensitive regex matching)

Implementation Reference

  • The main handler function that executes the readwise_topic_search tool. It extracts searchTerms from input args, calls the client's searchDocumentsByTopic method, formats the matching documents into a structured JSON response with full metadata, appends any API messages, and returns as MCP text content.
    export async function handleTopicSearch(args: any) { const client = initializeClient(); const { searchTerms } = args as { searchTerms: string[] }; const response = await client.searchDocumentsByTopic(searchTerms); const searchResults = { searchTerms, totalMatches: response.data.length, documents: response.data.map((doc: any) => ({ id: doc.id, url: doc.url, title: doc.title, author: doc.author, source: doc.source, category: doc.category, location: doc.location, tags: doc.tags, site_name: doc.site_name, word_count: doc.word_count, created_at: doc.created_at, updated_at: doc.updated_at, published_date: doc.published_date, summary: doc.summary, image_url: doc.image_url, source_url: doc.source_url, notes: doc.notes, reading_progress: doc.reading_progress, first_opened_at: doc.first_opened_at, last_opened_at: doc.last_opened_at, saved_at: doc.saved_at, last_moved_at: doc.last_moved_at, })) }; let responseText = JSON.stringify(searchResults, null, 2); if (response.messages && response.messages.length > 0) { responseText += '\n\nMessages:\n' + response.messages.map(msg => `${msg.type.toUpperCase()}: ${msg.content}`).join('\n'); } return { content: [ { type: 'text', text: responseText, }, ], }; }
  • Supporting utility in ReadwiseClient that implements the topic search logic: paginates to fetch all documents, builds case-insensitive regex from each searchTerm, concatenates title/summary/notes/tags for matching, filters documents matching any term, handles rate limiting.
    async searchDocumentsByTopic(searchTerms: string[]): Promise<APIResponse<ReadwiseDocument[]>> { try { // Fetch all documents without full content for performance const allDocuments: ReadwiseDocument[] = []; let nextPageCursor: string | undefined; do { const params: ListDocumentsParams = { withFullContent: false, withHtmlContent: false, }; if (nextPageCursor) { params.pageCursor = nextPageCursor; } const response = await this.listDocuments(params); allDocuments.push(...response.data.results); nextPageCursor = response.data.nextPageCursor; } while (nextPageCursor); // Create regex patterns from search terms (case-insensitive) const regexPatterns = searchTerms.map(term => new RegExp(term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'i') ); // Filter documents that match any of the search terms const matchingDocuments = allDocuments.filter(doc => { // Extract searchable text fields const searchableFields = [ doc.title || '', doc.summary || '', doc.notes || '', // Handle tags - they can be string array or object Array.isArray(doc.tags) ? doc.tags.join(' ') : '', ]; const searchableText = searchableFields.join(' ').toLowerCase(); // Check if any regex pattern matches return regexPatterns.some(pattern => pattern.test(searchableText)); }); return this.createResponse(matchingDocuments); } catch (error) { if (error instanceof Error && error.message.startsWith('RATE_LIMIT:')) { const seconds = parseInt(error.message.split(':')[1], 10); throw new Error(`Rate limit exceeded. Too many requests. Please retry after ${seconds} seconds.`); } throw error; } }
  • Tool schema definition including name, description, and inputSchema specifying an array of searchTerms (min 1 item) for regex-based topic search.
    { name: 'readwise_topic_search', description: 'Search documents in Readwise Reader by topic using regex matching on title, summary, notes, and tags', inputSchema: { type: 'object', properties: { searchTerms: { type: 'array', items: { type: 'string' }, description: 'List of search terms to match against document content (case-insensitive regex matching)', minItems: 1, }, }, required: ['searchTerms'], additionalProperties: false, }, },
  • Tool dispatch registration in the central handleToolCall switch statement, mapping 'readwise_topic_search' name to the handleTopicSearch function.
    case 'readwise_topic_search': return handleTopicSearch(args);
  • Import statement registering the handleTopicSearch handler into the dispatch module.
    import { handleListTags, handleTopicSearch } from './tag-search-handlers.js';

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/arnaldo-delisio/readwise-mcp-enhanced'

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