messages_search_messages
Search iMessage conversations for specific text, sender, or chat history using AppleScript automation on macOS.
Instructions
[iMessage operations] Search for messages containing specific text or from a specific sender
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| searchText | Yes | Text to search for in messages | |
| sender | No | Search for messages from a specific sender (phone number or email) | |
| chatId | No | Limit search to a specific chat ID | |
| limit | No | Maximum number of messages to retrieve | |
| daysBack | No | Limit search to messages from the last N days |
Implementation Reference
- src/categories/messages.ts:151-232 (handler)Handler function that dynamically generates AppleScript to query the Messages database (chat.db) using SQLite, building WHERE clauses based on searchText, sender, chatId, daysBack parameters, and returns formatted message results.script: (args) => ` on run -- Path to the Messages database set dbPath to (do shell script "echo ~/Library/Messages/chat.db") -- Create a temporary SQL file for our query set tempFile to (do shell script "mktemp /tmp/imessage_search.XXXXXX") -- Build WHERE clause based on provided parameters set whereClause to "" ${args.searchText ? ` -- Add search text condition if provided set whereClause to whereClause & "message.text LIKE '%${args.searchText.replace(/'/g, "''")}%' " ` : ''} ${args.sender ? ` -- Add sender condition if provided if length of whereClause > 0 then set whereClause to whereClause & "AND " end if set whereClause to whereClause & "handle.id LIKE '%${args.sender.replace(/'/g, "''")}%' " ` : ''} ${args.chatId ? ` -- Add chat ID condition if provided if length of whereClause > 0 then set whereClause to whereClause & "AND " end if set whereClause to whereClause & "chat.chat_identifier = '${args.chatId.replace(/'/g, "''")}' " ` : ''} ${args.daysBack ? ` -- Add date range condition if length of whereClause > 0 then set whereClause to whereClause & "AND " end if set whereClause to whereClause & "message.date > (strftime('%s', 'now', '-${args.daysBack} days') - strftime('%s', '2001-01-01')) * 1000000000 " ` : ''} -- If no search parameters were provided, add a default condition to avoid returning all messages if length of whereClause = 0 then set whereClause to "1=1 " end if -- Write SQL query to temp file do shell script "cat > " & quoted form of tempFile & " << 'EOF' SELECT datetime(message.date/1000000000 + strftime('%s', '2001-01-01'), 'unixepoch', 'localtime') as message_date, handle.id as sender, message.text as message_text, chat.display_name as chat_name, chat.chat_identifier as chat_id FROM message LEFT JOIN handle ON message.handle_id = handle.ROWID LEFT JOIN chat_message_join ON message.ROWID = chat_message_join.message_id LEFT JOIN chat ON chat_message_join.chat_id = chat.ROWID WHERE " & whereClause & " ORDER BY message.date DESC LIMIT ${args.limit}; EOF" -- Execute the query set queryResult to do shell script "sqlite3 " & quoted form of dbPath & " < " & quoted form of tempFile -- Clean up temp file do shell script "rm " & quoted form of tempFile -- Process and display results set resultList to paragraphs of queryResult set messageData to {} repeat with messageLine in resultList set messageData to messageData & messageLine end repeat return messageData end run `
- src/categories/messages.ts:120-149 (schema)JSON Schema defining the input parameters for the messages_search_messages tool, with searchText required.schema: { type: "object", properties: { searchText: { type: "string", description: "Text to search for in messages", default: "" }, sender: { type: "string", description: "Search for messages from a specific sender (phone number or email)", default: "" }, chatId: { type: "string", description: "Limit search to a specific chat ID", default: "" }, limit: { type: "number", description: "Maximum number of messages to retrieve", default: 50 }, daysBack: { type: "number", description: "Limit search to messages from the last N days", default: 30 } }, required: ["searchText"]
- src/framework.ts:221-232 (registration)Tool list registration: dynamically generates tool list including 'messages_search_messages' by combining category.name + '_' + script.name, with description and inputSchema from the script definition.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: this.categories.flatMap((category) => category.scripts.map((script) => ({ name: `${category.name}_${script.name}`, // Changed from dot to underscore description: `[${category.description}] ${script.description}`, inputSchema: script.schema || { type: "object", properties: {}, }, })), ), }));
- src/framework.ts:275-294 (registration)Core tool execution handler: for 'messages_search_messages', invokes the script generator function with arguments, executes the generated AppleScript via osascript, and returns the result as text content.const scriptContent = typeof script.script === "function" ? script.script(request.params.arguments) : script.script; const result = await this.executeScript(scriptContent); this.log("info", "Tool execution completed successfully", { tool: toolName, resultLength: result.length }); return { content: [ { type: "text", text: result, }, ], };
- src/index.ts:34-34 (registration)Registers the messages category (containing search_messages script) with the AppleScriptFramework, enabling the 'messages_search_messages' tool.server.addCategory(messagesCategory);