All checks were successful
Build And Test / publish (push) Successful in 48s
152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
from typing import Optional
|
|
from fastmcp import FastMCP
|
|
|
|
from services.calendar_service import CalendarService
|
|
|
|
|
|
def register_calendar_tools(mcp: FastMCP, service: CalendarService):
|
|
"""Register all calendar-related MCP tools."""
|
|
|
|
@mcp.tool(description="List all available calendars from CalDAV and configured ICS feeds. Returns calendar ID, name, and properties.")
|
|
def list_calendars() -> list[dict]:
|
|
"""List all calendars."""
|
|
calendars = service.list_calendars()
|
|
return [c.model_dump() for c in calendars]
|
|
|
|
@mcp.tool(description="List events within a date range. If no calendar is specified, lists events from all calendars.")
|
|
def list_events(
|
|
start_date: str,
|
|
end_date: str,
|
|
calendar_id: Optional[str] = None,
|
|
include_recurring: bool = True,
|
|
) -> dict:
|
|
"""
|
|
List events in a date range.
|
|
|
|
Args:
|
|
start_date: Start of date range (ISO format: YYYY-MM-DD)
|
|
end_date: End of date range (ISO format: YYYY-MM-DD)
|
|
calendar_id: The calendar ID (CalDAV URL or ICS ID) to query. If not provided, lists from all calendars.
|
|
include_recurring: Whether to expand recurring events (default: True)
|
|
"""
|
|
if calendar_id:
|
|
# Single calendar
|
|
result = service.list_events(calendar_id, start_date, end_date, include_recurring)
|
|
return result.model_dump()
|
|
else:
|
|
# All calendars
|
|
calendars = service.list_calendars()
|
|
all_events = []
|
|
for cal in calendars:
|
|
try:
|
|
result = service.list_events(cal.id, start_date, end_date, include_recurring)
|
|
for event in result.events:
|
|
event_dict = event.model_dump()
|
|
event_dict["calendar_name"] = cal.name
|
|
all_events.append(event_dict)
|
|
except Exception:
|
|
continue # Skip calendars that fail
|
|
|
|
# Sort by start time
|
|
all_events.sort(key=lambda e: e.get("start", ""))
|
|
|
|
return {
|
|
"events": all_events,
|
|
"total": len(all_events),
|
|
"calendar_id": "all",
|
|
"start_date": start_date,
|
|
"end_date": end_date,
|
|
}
|
|
|
|
@mcp.tool(description="Get detailed information about a specific calendar event including attendees and recurrence.")
|
|
def get_event(
|
|
calendar_id: str,
|
|
event_id: str,
|
|
) -> Optional[dict]:
|
|
"""
|
|
Get a specific event.
|
|
|
|
Args:
|
|
calendar_id: The calendar ID (CalDAV URL or ICS ID) containing the event
|
|
event_id: The unique ID (UID) of the event
|
|
"""
|
|
result = service.get_event(calendar_id, event_id)
|
|
return result.model_dump() if result else None
|
|
|
|
@mcp.tool(description="Create a new calendar event with title, time, location, attendees, and optional recurrence.")
|
|
def create_event(
|
|
calendar_id: str,
|
|
title: str,
|
|
start: str,
|
|
end: str,
|
|
description: Optional[str] = None,
|
|
location: Optional[str] = None,
|
|
attendees: Optional[list[str]] = None,
|
|
reminders: Optional[list[int]] = None,
|
|
recurrence: Optional[str] = None,
|
|
) -> dict:
|
|
"""
|
|
Create a new calendar event.
|
|
|
|
Args:
|
|
calendar_id: The calendar ID to create the event in (CalDAV only)
|
|
title: Event title/summary
|
|
start: Start datetime (ISO format: YYYY-MM-DDTHH:MM:SS)
|
|
end: End datetime (ISO format: YYYY-MM-DDTHH:MM:SS)
|
|
description: Event description (optional)
|
|
location: Event location (optional)
|
|
attendees: List of attendee email addresses (optional)
|
|
reminders: List of reminder times in minutes before event (optional)
|
|
recurrence: iCalendar RRULE string for recurring events (optional)
|
|
"""
|
|
result = service.create_event(
|
|
calendar_id, title, start, end, description, location, attendees, reminders, recurrence
|
|
)
|
|
return result.model_dump()
|
|
|
|
@mcp.tool(description="Update an existing calendar event. Only provided fields will be modified.")
|
|
def update_event(
|
|
calendar_id: str,
|
|
event_id: str,
|
|
title: Optional[str] = None,
|
|
start: Optional[str] = None,
|
|
end: Optional[str] = None,
|
|
description: Optional[str] = None,
|
|
location: Optional[str] = None,
|
|
attendees: Optional[list[str]] = None,
|
|
) -> Optional[dict]:
|
|
"""
|
|
Update an existing event.
|
|
|
|
Args:
|
|
calendar_id: The calendar ID containing the event (CalDAV only)
|
|
event_id: The unique ID of the event to update
|
|
title: New event title (optional)
|
|
start: New start datetime (optional)
|
|
end: New end datetime (optional)
|
|
description: New description (optional)
|
|
location: New location (optional)
|
|
attendees: New list of attendee emails (optional)
|
|
"""
|
|
result = service.update_event(
|
|
calendar_id, event_id, title, start, end, description, location, attendees
|
|
)
|
|
return result.model_dump() if result else None
|
|
|
|
@mcp.tool(description="Delete a calendar event by ID.")
|
|
def delete_event(
|
|
calendar_id: str,
|
|
event_id: str,
|
|
notify_attendees: bool = True,
|
|
) -> dict:
|
|
"""
|
|
Delete a calendar event.
|
|
|
|
Args:
|
|
calendar_id: The calendar ID containing the event (CalDAV only)
|
|
event_id: The unique ID of the event to delete
|
|
notify_attendees: Whether to notify attendees of cancellation (default: True)
|
|
"""
|
|
result = service.delete_event(calendar_id, event_id, notify_attendees)
|
|
return result.model_dump()
|