tool_send_message
Send text messages through macOS Messages app to individuals or groups using phone numbers, email addresses, or contact names.
Instructions
Send a message using the Messages app.
Args:
recipient: Phone number, email, contact name, or "contact:N" to select from matches
For example, "contact:1" selects the first contact from a previous search
message: Message text to send
group_chat: Whether to send to a group chat (uses chat ID instead of buddy)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| recipient | Yes | ||
| message | Yes | ||
| group_chat | No |
Implementation Reference
- mac_messages_mcp/server.py:57-76 (handler)The tool handler function decorated with @mcp.tool(). It logs the action, ensures recipient is string, calls the send_message helper, and handles exceptions.@mcp.tool() def tool_send_message(ctx: Context, recipient: str, message: str, group_chat: bool = False) -> str: """ Send a message using the Messages app. Args: recipient: Phone number, email, contact name, or "contact:N" to select from matches For example, "contact:1" selects the first contact from a previous search message: Message text to send group_chat: Whether to send to a group chat (uses chat ID instead of buddy) """ logger.info(f"Sending message to: {recipient}, group_chat: {group_chat}") try: # Ensure recipient is a string (handles numbers properly) recipient = str(recipient) result = send_message(recipient=recipient, message=message, group_chat=group_chat) return result except Exception as e: logger.error(f"Error in send_message: {str(e)}") return f"Error sending message: {str(e)}"
- mac_messages_mcp/messages.py:415-473 (helper)The core helper function implementing message sending logic: resolves contacts via fuzzy matching, handles 'contact:N' selection, and delegates to low-level AppleScript sender.def send_message(recipient: str, message: str, group_chat: bool = False) -> str: """ Send a message using the Messages app with improved contact resolution. Args: recipient: Phone number, email, contact name, or special format for contact selection Use "contact:N" to select the Nth contact from a previous ambiguous match message: Message text to send group_chat: Whether this is a group chat (uses chat ID instead of buddy) Returns: Success or error message """ # Convert to string to ensure phone numbers work properly recipient = str(recipient).strip() # Handle contact selection format (contact:N) if recipient.lower().startswith("contact:"): try: # Get the selected index (1-based) index = int(recipient.split(":", 1)[1].strip()) - 1 # Get the most recent contact matches from global cache if not hasattr(send_message, "recent_matches") or not send_message.recent_matches: return "No recent contact matches available. Please search for a contact first." if index < 0 or index >= len(send_message.recent_matches): return f"Invalid selection. Please choose a number between 1 and {len(send_message.recent_matches)}." # Get the selected contact contact = send_message.recent_matches[index] return _send_message_to_recipient(contact['phone'], message, contact['name'], group_chat) except (ValueError, IndexError) as e: return f"Error selecting contact: {str(e)}" # Check if recipient is directly a phone number if all(c.isdigit() or c in '+- ()' for c in recipient): # Clean the phone number clean_number = ''.join(c for c in recipient if c.isdigit()) return _send_message_to_recipient(clean_number, message, group_chat=group_chat) # Try to find the contact by name contacts = find_contact_by_name(recipient) if not contacts: return f"Error: Could not find any contact matching '{recipient}'" if len(contacts) == 1: # Single match, use it contact = contacts[0] return _send_message_to_recipient(contact['phone'], message, contact['name'], group_chat) else: # Store the matches for later selection send_message.recent_matches = contacts # Multiple matches, return them all contact_list = "\n".join([f"{i+1}. {c['name']} ({c['phone']})" for i, c in enumerate(contacts[:10])]) return f"Multiple contacts found matching '{recipient}'. Please specify which one using 'contact:N' where N is the number:\n{contact_list}"
- mac_messages_mcp/messages.py:477-523 (helper)Low-level helper that executes AppleScript to send the message via Messages app, with fallback to direct method.def _send_message_to_recipient(recipient: str, message: str, contact_name: str = None, group_chat: bool = False) -> str: """ Internal function to send a message to a specific recipient using file-based approach. Args: recipient: Phone number or email message: Message text to send contact_name: Optional contact name for the success message group_chat: Whether this is a group chat Returns: Success or error message """ try: # Create a temporary file with the message content file_path = os.path.abspath('imessage_tmp.txt') with open(file_path, 'w') as f: f.write(message) # Adjust the AppleScript command based on whether this is a group chat if not group_chat: command = f'tell application "Messages" to send (read (POSIX file "{file_path}") as «class utf8») to participant "{recipient}" of (1st service whose service type = iMessage)' else: command = f'tell application "Messages" to send (read (POSIX file "{file_path}") as «class utf8») to chat "{recipient}"' # Run the AppleScript result = run_applescript(command) # Clean up the temporary file try: os.remove(file_path) except: pass # Check result if result.startswith("Error:"): # Try fallback to direct method return _send_message_direct(recipient, message, contact_name, group_chat) # Message sent successfully display_name = contact_name if contact_name else recipient return f"Message sent successfully to {display_name}" except Exception as e: # Try fallback method return _send_message_direct(recipient, message, contact_name, group_chat)