Skip to main content
Glama

readwise_topic_search

Search documents in Readwise Reader by topic using regex to match titles, summaries, notes, and tags. Quickly locate relevant content based on specific search terms.

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 handler function that processes the readwise_topic_search tool call, extracts searchTerms, calls the client's searchDocumentsByTopic method, formats the results into a structured JSON response, and returns it as MCP 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, }, ], }; }
  • Core helper method in ReadwiseClient that implements the topic search logic: paginates through all documents, applies case-insensitive regex filtering on title, summary, notes, and tags based on searchTerms.
    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; } }
  • The tool schema definition including name, description, and inputSchema for validating searchTerms array.
    { 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, }, },
  • Dispatch registration in the main handleToolCall switch statement that routes 'readwise_topic_search' calls to the handleTopicSearch function.
    case 'readwise_topic_search': return handleTopicSearch(args);
  • src/index.ts:24-26 (registration)
    MCP server registration for listing tools, providing the tool definitions including readwise_topic_search.
    server.setRequestHandler(ListToolsRequestSchema, async () => { return { 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/arnaldo-delisio/readwise-mcp-enhanced'

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