Skip to main content
Glama

Python Apple MCP

by jxnl
reminders.py9.27 kB
"""Reminders module for interacting with Apple Reminders.""" import logging from typing import Dict, List, Any, Optional from datetime import datetime from .applescript import ( run_applescript_async, AppleScriptError, format_applescript_value, parse_applescript_record, parse_applescript_list ) logger = logging.getLogger(__name__) class RemindersModule: """Module for interacting with Apple Reminders""" async def check_reminders_access(self) -> bool: """Check if Reminders app is accessible""" try: script = ''' try tell application "Reminders" get name return true end tell on error return false end try ''' result = await run_applescript_async(script) return result.lower() == 'true' except Exception as e: logger.error(f"Cannot access Reminders app: {e}") return False async def get_all_lists(self) -> List[Dict[str, Any]]: """Get all reminder lists""" script = ''' tell application "Reminders" set allLists to {} repeat with l in every list set end of allLists to { name:name of l, id:id of l, color:color of l, reminder_count:count of (reminders in l) } end repeat return allLists as text end tell ''' try: result = await run_applescript_async(script) lists = parse_applescript_list(result) return [parse_applescript_record(lst) for lst in lists] except AppleScriptError as e: logger.error(f"Error getting reminder lists: {e}") return [] async def get_all_reminders(self) -> List[Dict[str, Any]]: """Get all reminders""" script = ''' tell application "Reminders" set allReminders to {} repeat with r in every reminder set end of allReminders to { name:name of r, id:id of r, notes:body of r, due_date:due date of r, completed:completed of r, list:name of container of r } end repeat return allReminders as text end tell ''' try: result = await run_applescript_async(script) reminders = parse_applescript_list(result) return [parse_applescript_record(reminder) for reminder in reminders] except AppleScriptError as e: logger.error(f"Error getting all reminders: {e}") return [] async def search_reminders(self, search_text: str) -> List[Dict[str, Any]]: """Search for reminders matching text""" script = f''' tell application "Reminders" try set matchingReminders to {{}} repeat with r in every reminder if name of r contains "{search_text}" or (body of r is not missing value and body of r contains "{search_text}") then set reminderData to {{name:name of r, notes:body of r, due_date:due date of r, completed:completed of r, list:name of container of r}} copy reminderData to end of matchingReminders end if end repeat return matchingReminders on error errMsg return "ERROR:" & errMsg end try end tell ''' try: result = await run_applescript_async(script) if result.startswith("ERROR:"): logger.error(f"Error in AppleScript: {result}") return [] reminders = parse_applescript_list(result) parsed_reminders = [] for reminder in reminders: reminder_dict = parse_applescript_record(reminder) parsed_reminders.append(reminder_dict) return parsed_reminders except AppleScriptError as e: logger.error(f"Error searching reminders: {e}") return [] async def open_reminder(self, search_text: str) -> Dict[str, Any]: """Open a reminder matching text""" script = f''' tell application "Reminders" set foundReminder to missing value repeat with r in every reminder if name of r contains "{search_text}" then set foundReminder to r exit repeat end if end repeat if foundReminder is not missing value then show foundReminder return "SUCCESS:Opened reminder: " & name of foundReminder else return "ERROR:No reminder found matching '{search_text}'" end if end tell ''' try: result = await run_applescript_async(script) success = result.startswith("SUCCESS:") return { "success": success, "message": result.replace("SUCCESS:", "").replace("ERROR:", ""), "reminder": None # Note: We could parse the reminder details if needed } except AppleScriptError as e: logger.error(f"Error opening reminder: {e}") return { "success": False, "message": str(e), "reminder": None } async def create_reminder(self, name: str, list_name: str = None, notes: str = None, due_date: datetime = None) -> Dict[str, Any]: """Create a new reminder""" # Format date for AppleScript if provided due_date_str = due_date.strftime("%Y-%m-%d %H:%M:%S") if due_date else None # Build the properties string properties = [f'name:"{name}"'] if notes: properties.append(f'body:"{notes}"') if due_date_str: properties.append(f'due date:date "{due_date_str}"') properties_str = ", ".join(properties) # Use default "Reminders" list if none specified list_to_use = list_name or 'Reminders' script = f''' tell application "Reminders" try tell list "{list_to_use}" make new reminder with properties {{{properties_str}}} return "SUCCESS:Reminder created successfully in list '{list_to_use}'" end tell on error errMsg return "ERROR:" & errMsg end try end tell ''' try: result = await run_applescript_async(script) success = result.startswith("SUCCESS:") return { "success": success, "message": result.replace("SUCCESS:", "").replace("ERROR:", "") } except AppleScriptError as e: logger.error(f"Error creating reminder: {e}") return { "success": False, "message": str(e) } async def get_reminders_from_list_by_id(self, list_id: str, props: Optional[List[str]] = None) -> List[Dict[str, Any]]: """Get reminders from a specific list by ID""" if not props: props = ["name", "id", "notes", "due_date", "completed"] props_str = ", ".join(props) script = f''' tell application "Reminders" set theList to list id "{list_id}" set listReminders to {{}} repeat with r in reminders in theList set reminderProps to {{}} {" ".join([f'set end of reminderProps to {{"{prop}":{prop} of r}}' for prop in props])} set end of listReminders to reminderProps end repeat return listReminders as text end tell ''' try: result = await run_applescript_async(script) reminders = parse_applescript_list(result) # Combine properties for each reminder parsed_reminders = [] for reminder in reminders: reminder_data = {} for prop_dict in parse_applescript_list(reminder): reminder_data.update(parse_applescript_record(prop_dict)) parsed_reminders.append(reminder_data) return parsed_reminders except AppleScriptError as e: logger.error(f"Error getting reminders from list: {e}") return []

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/jxnl/python-apple-mcp'

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