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);