Skip to main content
Glama
carterlasalle

mac-messages-mcp

tool_check_addressbook

Identify and resolve AddressBook access problems on macOS Messages app through the MCP server. Helps diagnose connectivity and permission issues efficiently.

Instructions

Diagnose AddressBook access issues.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The MCP tool handler function for 'tool_check_addressbook'. It logs the action and delegates to the helper function check_addressbook_access(), handling exceptions.
    @mcp.tool() def tool_check_addressbook(ctx: Context) -> str: """ Diagnose AddressBook access issues. """ logger.info("Checking AddressBook access") try: return check_addressbook_access() except Exception as e: logger.error(f"Error checking AddressBook: {str(e)}") return f"Error checking AddressBook: {str(e)}"
  • The helper function implementing the core logic: checks AddressBook directory/databases accessibility, permissions, table presence, contact count, and retrieves sample contacts.
    def check_addressbook_access() -> str: """Check if the AddressBook database is accessible and return detailed information.""" try: home_dir = os.path.expanduser("~") sources_path = os.path.join(home_dir, "Library/Application Support/AddressBook/Sources") status = [] # Check if the directory exists if not os.path.exists(sources_path): return f"ERROR: AddressBook Sources directory not found at {sources_path} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE." status.append(f"AddressBook Sources directory exists at: {sources_path}") # Find database files db_paths = glob.glob(os.path.join(sources_path, "*/AddressBook-v22.abcddb")) if not db_paths: return f"ERROR: No AddressBook database files found in {sources_path} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE." status.append(f"Found {len(db_paths)} AddressBook database files:") for path in db_paths: status.append(f" - {path}") # Check file permissions for each database for db_path in db_paths: try: with open(db_path, 'rb') as f: # Just try to read a byte to confirm access f.read(1) status.append(f"File is readable: {db_path}") except PermissionError: status.append(f"ERROR: Permission denied when trying to read {db_path} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE.") continue except Exception as e: status.append(f"ERROR: Unknown error reading file {db_path}: {str(e)} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE.") continue # Try to connect to the database try: conn = sqlite3.connect(db_path) status.append(f"Successfully connected to database: {db_path}") # Test a simple query cursor = conn.cursor() cursor.execute("SELECT count(*) FROM sqlite_master") count = cursor.fetchone()[0] status.append(f"Database contains {count} tables") # Check if the necessary tables exist cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name IN ('ZABCDRECORD', 'ZABCDPHONENUMBER')") tables = [row[0] for row in cursor.fetchall()] if 'ZABCDRECORD' in tables and 'ZABCDPHONENUMBER' in tables: status.append("Required tables (ZABCDRECORD, ZABCDPHONENUMBER) are present") else: status.append(f"WARNING: Some required tables are missing. Found: {', '.join(tables)}") # Get a count of contacts try: cursor.execute("SELECT COUNT(*) FROM ZABCDRECORD") contact_count = cursor.fetchone()[0] status.append(f"Database contains {contact_count} contacts") except sqlite3.OperationalError: status.append("Could not query contact count PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE.") conn.close() except sqlite3.OperationalError as e: status.append(f"ERROR: Database connection error for {db_path}: {str(e)} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE.") # Try to get actual contacts contacts = get_addressbook_contacts() if contacts: status.append(f"Successfully retrieved {len(contacts)} contacts with phone numbers") else: status.append("WARNING: No contacts with phone numbers found. PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE.") return "\n".join(status) except Exception as e: return f"ERROR: Unexpected error during database access check: {str(e)} PLEASE TELL THE USER TO GRANT FULL DISK ACCESS TO THE TERMINAL APPLICATION(CURSOR, TERMINAL, CLAUDE, ETC.) AND RESTART THE APPLICATION. DO NOT RETRY UNTIL NEXT MESSAGE."

Other Tools

Related Tools

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