Skip to main content
Glama
jlucaso1

WhatsApp MCP Server

by jlucaso1

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
NameRequiredDescriptionDefault
queryYesThe text content to search for within messages
chat_jidNoOptional: The JID of a specific chat to search within (e.g., '123...net' or 'group@g.us'). If omitted, searches all chats.
limitNoMax messages per page (default 10)
pageNoPage number (0-indexed, default 0)

Implementation Reference

  • 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}`,
              },
            ],
          };
        }
      },
    );
  • 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}`,
              },
            ],
          };
        }
      },
    );
  • 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 [];
      }
    }

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/jlucaso1/whatsapp-mcp-ts'

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