Skip to main content
Glama
carterlasalle

mac-messages-mcp

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
NameRequiredDescriptionDefault
recipientYes
messageYes
group_chatNo

Implementation Reference

  • 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)}"
  • 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}"
  • 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)

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/carterlasalle/mac_messages_mcp'

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