search_messages
Find specific WhatsApp messages by searching text content across all chats or within a specific conversation, with pagination controls for managing results.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | The text content to search for within messages | |
| chat_jid | No | Optional: The JID of a specific chat to search within (e.g., '123...net' or 'group@g.us'). If omitted, searches all chats. | |
| limit | No | Max messages per page (default 10) | |
| page | No | Page number (0-indexed, default 0) |
Implementation Reference
- src/mcp.ts:503-555 (handler)The async handler function for the MCP 'search_messages' tool. It takes query, optional chat_jid, limit, page; calls searchMessages helper; handles empty results and errors; formats and returns JSON string of messages.async ({ chat_jid, query, limit, page }) => { const searchScope = chat_jid ? `in chat ${chat_jid}` : "across all chats"; mcpLogger.info( `[MCP Tool] Executing search_messages ${searchScope}, query="${query}", limit=${limit}, page=${page}`, ); try { const messages = searchMessages(query, chat_jid, limit, page); if (!messages.length && page === 0) { return { content: [ { type: "text", text: `No messages found containing "${query}" in chat ${chat_jid}.`, }, ], }; } else if (!messages.length) { return { content: [ { type: "text", text: `No more messages found containing "${query}" on page ${page} for chat ${chat_jid}.`, }, ], }; } const formattedMessages = messages.map(formatDbMessageForJson); return { content: [ { type: "text", text: JSON.stringify(formattedMessages, null, 2), }, ], }; } catch (error: any) { mcpLogger.error( `[MCP Tool Error] search_messages_in_chat failed for ${chat_jid} / "${query}": ${error.message}`, ); return { isError: true, content: [ { type: "text", text: `Error searching messages in chat ${chat_jid}: ${error.message}`, }, ], }; } }, );
- src/mcp.ts:477-502 (schema)Zod input schema definition for the 'search_messages' tool parameters: query (required string), optional chat_jid, limit, page.{ query: z .string() .min(1) .describe("The text content to search for within messages"), chat_jid: z .string() .optional() .describe( "Optional: The JID of a specific chat to search within (e.g., '123...net' or 'group@g.us'). If omitted, searches all chats.", ), limit: z .number() .int() .positive() .optional() .default(10) .describe("Max messages per page (default 10)"), page: z .number() .int() .nonnegative() .optional() .default(0) .describe("Page number (0-indexed, default 0)"), },
- src/mcp.ts:475-555 (registration)MCP server tool registration: server.tool('search_messages', inputSchema, handlerFunction).server.tool( "search_messages", { query: z .string() .min(1) .describe("The text content to search for within messages"), chat_jid: z .string() .optional() .describe( "Optional: The JID of a specific chat to search within (e.g., '123...net' or 'group@g.us'). If omitted, searches all chats.", ), limit: z .number() .int() .positive() .optional() .default(10) .describe("Max messages per page (default 10)"), page: z .number() .int() .nonnegative() .optional() .default(0) .describe("Page number (0-indexed, default 0)"), }, async ({ chat_jid, query, limit, page }) => { const searchScope = chat_jid ? `in chat ${chat_jid}` : "across all chats"; mcpLogger.info( `[MCP Tool] Executing search_messages ${searchScope}, query="${query}", limit=${limit}, page=${page}`, ); try { const messages = searchMessages(query, chat_jid, limit, page); if (!messages.length && page === 0) { return { content: [ { type: "text", text: `No messages found containing "${query}" in chat ${chat_jid}.`, }, ], }; } else if (!messages.length) { return { content: [ { type: "text", text: `No more messages found containing "${query}" on page ${page} for chat ${chat_jid}.`, }, ], }; } const formattedMessages = messages.map(formatDbMessageForJson); return { content: [ { type: "text", text: JSON.stringify(formattedMessages, null, 2), }, ], }; } catch (error: any) { mcpLogger.error( `[MCP Tool Error] search_messages_in_chat failed for ${chat_jid} / "${query}": ${error.message}`, ); return { isError: true, content: [ { type: "text", text: `Error searching messages in chat ${chat_jid}: ${error.message}`, }, ], }; } }, );
- src/database.ts:386-422 (helper)Helper function that executes the SQL query to search for messages containing the query string (case-insensitive LIKE), optionally filtered by chat_jid, ordered by timestamp DESC, with limit/offset pagination. Maps rows to Message objects.export function searchMessages( searchQuery: string, chatJid?: string | null, limit: number = 10, page: number = 0, ): Message[] { const db = getDb(); try { const offset = page * limit; const searchPattern = `%${searchQuery}%`; let sql = ` SELECT m.*, c.name as chat_name FROM messages m JOIN chats c ON m.chat_jid = c.jid WHERE LOWER(m.content) LIKE LOWER(?) -- Param 1: searchPattern `; const params: (string | number | null)[] = [searchPattern]; if (chatJid) { sql += ` AND m.chat_jid = ?`; params.push(chatJid); } sql += ` ORDER BY m.timestamp DESC`; sql += ` LIMIT ?`; params.push(limit); sql += ` OFFSET ?`; params.push(offset); const stmt = db.prepare(sql); const rows = stmt.all(...params) as any[]; return rows.map(rowToMessage); } catch (error) { console.error("Error searching messages:", error); return []; } }