feat: add alarm/reminder support to create_event tool

This commit is contained in:
2026-02-18 20:19:33 +01:00
parent 668107aae6
commit 795e806673
3 changed files with 39 additions and 12 deletions

View File

@@ -71,17 +71,43 @@ class CalDAVClient:
}) })
return results return results
def create_event(self, calendar_name: str, summary: str, start_time: Union[datetime, date], end_time: Union[datetime, date], description: str = "", recurrence: Optional[Dict] = None) -> str: def create_event(self, calendar_name: str, summary: str, start_time: Union[datetime, date], end_time: Union[datetime, date], description: str = "", recurrence: Optional[Dict] = None, alarm_minutes: Optional[int] = None) -> str:
calendar = self._get_calendar(calendar_name) calendar = self._get_calendar(calendar_name)
event = calendar.save_event(
dtstart=start_time, # Build raw ical for better control
dtend=end_time, cal = icalendar.Calendar()
summary=summary, cal.add('prodid', '-//MCP CalDAV Server//EN')
description=description, cal.add('version', '2.0')
rrule=recurrence
) event = icalendar.Event()
# Re-parse to get the UID, though library might provide it event.add('summary', summary)
ical = icalendar.Calendar.from_ical(event.data) event.add('description', description)
if isinstance(start_time, datetime):
event.add('dtstart', start_time)
event.add('dtend', end_time)
else:
event.add('dtstart', start_time)
event.add('dtend', end_time)
if recurrence:
event.add('rrule', recurrence)
if alarm_minutes is not None:
alarm = icalendar.Alarm()
alarm.add('action', 'DISPLAY')
alarm.add('description', f'Reminder: {summary}')
# Use a proper timedelta or iCalendar DURATION string
from datetime import timedelta
alarm.add('trigger', timedelta(minutes=-alarm_minutes))
event.add_component(alarm)
cal.add_component(event)
saved_event = calendar.save_event(cal.to_ical())
# Re-parse to get the UID
ical = icalendar.Calendar.from_ical(saved_event.data)
for component in ical.walk(): for component in ical.walk():
if component.name == "VEVENT": if component.name == "VEVENT":
return str(component.get("uid")) return str(component.get("uid"))

View File

@@ -72,7 +72,7 @@ def parse_rrule(rrule_str: str) -> dict:
return rrule return rrule
@mcp.tool() @mcp.tool()
def create_event(calendar_name: str, summary: str, start_time: str, end_time: str, description: str = "", all_day: bool = False, recurrence: Optional[str] = None) -> str: def create_event(calendar_name: str, summary: str, start_time: str, end_time: str, description: str = "", all_day: bool = False, recurrence: Optional[str] = None, alarm_minutes: Optional[int] = None) -> str:
""" """
Creates a new event. Creates a new event.
@@ -84,6 +84,7 @@ def create_event(calendar_name: str, summary: str, start_time: str, end_time: st
description: Event description. description: Event description.
all_day: Set to True for all-day events (start/end time will be treated as dates). all_day: Set to True for all-day events (start/end time will be treated as dates).
recurrence: RRULE string, e.g., "FREQ=DAILY;COUNT=10". recurrence: RRULE string, e.g., "FREQ=DAILY;COUNT=10".
alarm_minutes: Minutes before the event to trigger an alarm/reminder.
""" """
if not client: if not client:
return "Error: CalDAV client not initialized" return "Error: CalDAV client not initialized"
@@ -98,7 +99,7 @@ def create_event(calendar_name: str, summary: str, start_time: str, end_time: st
rrule_dict = parse_rrule(recurrence) if recurrence else None rrule_dict = parse_rrule(recurrence) if recurrence else None
result = client.create_event(calendar_name, summary, dt_start, dt_end, description, rrule_dict) result = client.create_event(calendar_name, summary, dt_start, dt_end, description, rrule_dict, alarm_minutes)
return f"Event created: {result}" return f"Event created: {result}"
except Exception as e: except Exception as e:
return f"Error creating event: {str(e)}" return f"Error creating event: {str(e)}"