applescript-mcp

import { ScriptCategory } from "../types/index.js"; /** * iMessage related scripts */ export const messagesCategory: ScriptCategory = { name: "messages", description: "iMessage operations", scripts: [ { name: "list_chats", description: "List available iMessage and SMS chats", schema: { type: "object", properties: { includeParticipantDetails: { type: "boolean", description: "Include detailed participant information", default: false } } }, script: (args) => ` tell application "Messages" set chatList to {} repeat with aChat in chats set chatName to name of aChat if chatName is missing value then set chatName to "" -- Try to get the contact name for individual chats try set theParticipants to participants of aChat if (count of theParticipants) is 1 then set theParticipant to item 1 of theParticipants set chatName to name of theParticipant end if end try end if set chatInfo to {id:id of aChat, name:chatName, isGroupChat:(id of aChat contains "+")} ${args.includeParticipantDetails ? ` -- Add participant details if requested set participantList to {} repeat with aParticipant in participants of aChat set participantInfo to {id:id of aParticipant, handle:handle of aParticipant} try set participantInfo to participantInfo & {name:name of aParticipant} end try copy participantInfo to end of participantList end repeat set chatInfo to chatInfo & {participant:participantList} ` : ''} copy chatInfo to end of chatList end repeat return chatList end tell ` }, { name: "get_messages", description: "Get messages from the Messages app", schema: { type: "object", properties: { limit: { type: "number", description: "Maximum number of messages to retrieve", default: 100 } } }, 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_query.XXXXXX") -- 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 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 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 ` }, { name: "search_messages", description: "Search for messages containing specific text or from a specific sender", 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"] }, 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 ` }, { name: "compose_message", description: "Open Messages app with a pre-filled message to a recipient or automatically send a message", schema: { type: "object", properties: { recipient: { type: "string", description: "Phone number or email of the recipient" }, body: { type: "string", description: "Message body text", default: "" }, auto: { type: "boolean", description: "Automatically send the message without user confirmation", default: false } }, required: ["recipient"] }, script: (args) => ` on run -- Get the recipient and message body set recipient to "${args.recipient}" set messageBody to "${args.body || ''}" set autoSend to ${args.auto === true ? "true" : "false"} if autoSend then -- Automatically send the message using AppleScript tell application "Messages" -- Get the service (iMessage or SMS) set targetService to 1st service whose service type = iMessage -- Send the message set targetBuddy to buddy "${args.recipient}" of targetService send "${args.body || ''}" to targetBuddy return "Message sent to " & "${args.recipient}" end tell else -- Just open Messages app with pre-filled content -- Create the SMS URL with proper URL encoding set smsURL to "sms:" & recipient if messageBody is not equal to "" then -- Use percent encoding for spaces instead of plus signs set encodedBody to "" repeat with i from 1 to count of characters of messageBody set c to character i of messageBody if c is space then set encodedBody to encodedBody & "%20" else set encodedBody to encodedBody & c end if end repeat set smsURL to smsURL & "&body=" & encodedBody end if -- Open the URL with the default handler (Messages app) do shell script "open " & quoted form of smsURL return "Opening Messages app with recipient: " & recipient end if end run ` } ] };
ID: 0t5gydjcqw