sqlite-explorer-fastmcp-mcp-server
by hannesrudolph
Verified
- src
- mcp_gsuite
from googleapiclient.discovery import build
from . import gauth
import logging
import traceback
from datetime import datetime
import pytz
class CalendarService():
def __init__(self, user_id: str):
credentials = gauth.get_stored_credentials(user_id=user_id)
if not credentials:
raise RuntimeError("No Oauth2 credentials stored")
self.service = build('calendar', 'v3', credentials=credentials) # Note: using v3 for Calendar API
def list_calendars(self) -> list:
"""
Lists all calendars accessible by the user.
Returns:
list: List of calendar objects with their metadata
"""
try:
calendar_list = self.service.calendarList().list().execute()
calendars = []
for calendar in calendar_list.get('items', []):
if calendar.get('kind') == 'calendar#calendarListEntry':
calendars.append({
'id': calendar.get('id'),
'summary': calendar.get('summary'),
'primary': calendar.get('primary', False),
'time_zone': calendar.get('timeZone'),
'etag': calendar.get('etag'),
'access_role': calendar.get('accessRole')
})
return calendars
except Exception as e:
logging.error(f"Error retrieving calendars: {str(e)}")
logging.error(traceback.format_exc())
return []
def get_events(self, time_min=None, time_max=None, max_results=250, show_deleted=False, calendar_id: str ='primary'):
"""
Retrieve calendar events within a specified time range.
Args:
time_min (str, optional): Start time in RFC3339 format. Defaults to current time.
time_max (str, optional): End time in RFC3339 format
max_results (int): Maximum number of events to return (1-2500)
show_deleted (bool): Whether to include deleted events
Returns:
list: List of calendar events
"""
try:
# If no time_min specified, use current time
if not time_min:
time_min = datetime.now(pytz.UTC).isoformat()
# Ensure max_results is within limits
max_results = min(max(1, max_results), 2500)
# Prepare parameters
params = {
'calendarId': calendar_id,
'timeMin': time_min,
'maxResults': max_results,
'singleEvents': True,
'orderBy': 'startTime',
'showDeleted': show_deleted
}
# Add optional time_max if specified
if time_max:
params['timeMax'] = time_max
# Execute the events().list() method
events_result = self.service.events().list(**params).execute()
# Extract the events
events = events_result.get('items', [])
# Process and return the events
processed_events = []
for event in events:
processed_event = {
'id': event.get('id'),
'summary': event.get('summary'),
'description': event.get('description'),
'start': event.get('start'),
'end': event.get('end'),
'status': event.get('status'),
'creator': event.get('creator'),
'organizer': event.get('organizer'),
'attendees': event.get('attendees'),
'location': event.get('location'),
'hangoutLink': event.get('hangoutLink'),
'conferenceData': event.get('conferenceData'),
'recurringEventId': event.get('recurringEventId')
}
processed_events.append(processed_event)
return processed_events
except Exception as e:
logging.error(f"Error retrieving calendar events: {str(e)}")
logging.error(traceback.format_exc())
return []
def create_event(self, summary: str, start_time: str, end_time: str,
location: str | None = None, description: str | None = None,
attendees: list | None = None, send_notifications: bool = True,
timezone: str | None = None,
calendar_id : str = 'primary') -> dict | None:
"""
Create a new calendar event.
Args:
summary (str): Title of the event
start_time (str): Start time in RFC3339 format
end_time (str): End time in RFC3339 format
location (str, optional): Location of the event
description (str, optional): Description of the event
attendees (list, optional): List of attendee email addresses
send_notifications (bool): Whether to send notifications to attendees
timezone (str, optional): Timezone for the event (e.g. 'America/New_York')
Returns:
dict: Created event data or None if creation fails
"""
try:
# Prepare event data
event = {
'summary': summary,
'start': {
'dateTime': start_time,
'timeZone': timezone or 'UTC',
},
'end': {
'dateTime': end_time,
'timeZone': timezone or 'UTC',
}
}
# Add optional fields if provided
if location:
event['location'] = location
if description:
event['description'] = description
if attendees:
event['attendees'] = [{'email': email} for email in attendees]
# Create the event
created_event = self.service.events().insert(
calendarId=calendar_id,
body=event,
sendNotifications=send_notifications
).execute()
return created_event
except Exception as e:
logging.error(f"Error creating calendar event: {str(e)}")
logging.error(traceback.format_exc())
return None
def delete_event(self, event_id: str, send_notifications: bool = True, calendar_id: str = 'primary') -> bool:
"""
Delete a calendar event by its ID.
Args:
event_id (str): The ID of the event to delete
send_notifications (bool): Whether to send cancellation notifications to attendees
Returns:
bool: True if deletion was successful, False otherwise
"""
try:
self.service.events().delete(
calendarId=calendar_id,
eventId=event_id,
sendNotifications=send_notifications
).execute()
return True
except Exception as e:
logging.error(f"Error deleting calendar event {event_id}: {str(e)}")
logging.error(traceback.format_exc())
return False