Skip to main content
Glama
taylorwilsdon

Google Workspace MCP Server - Control Gmail, Calendar, Docs, Sheets, Slides, Chat, Forms & Drive

get_events

Retrieve a formatted list of events from a specified Google Calendar within a defined time range using user email and calendar ID. Supports custom queries with optional start, end, and result limits.

Instructions

Retrieves a list of events from a specified Google Calendar within a given time range. Args: user_google_email (str): The user's Google email address. Required. calendar_id (str): The ID of the calendar to query. Use 'primary' for the user's primary calendar. Defaults to 'primary'. Calendar IDs can be obtained using `list_calendars`. time_min (Optional[str]): The start of the time range (inclusive) in RFC3339 format (e.g., '2024-05-12T10:00:00Z' or '2024-05-12'). If omitted, defaults to the current time. time_max (Optional[str]): The end of the time range (exclusive) in RFC3339 format. If omitted, events starting from `time_min` onwards are considered (up to `max_results`). max_results (int): The maximum number of events to return. Defaults to 25. Returns: str: A formatted list of events (summary, start time, link) within the specified range.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
calendar_idNoprimary
max_resultsNo
serviceYes
time_maxNo
time_minNo
user_google_emailYes

Implementation Reference

  • Registration of the 'get_events' tool via @server.tool() decorator, with error handling and auth decorators.
    @server.tool() @handle_http_errors("get_events", is_read_only=True, service_type="calendar") @require_google_service("calendar", "calendar_read")
  • The core handler function implementing the logic to retrieve events from Google Calendar using the provided parameters, including API calls, time formatting, and detailed output formatting.
    async def get_events( service, user_google_email: str, calendar_id: str = "primary", event_id: Optional[str] = None, time_min: Optional[str] = None, time_max: Optional[str] = None, max_results: int = 25, query: Optional[str] = None, detailed: bool = False, include_attachments: bool = False, ) -> str: """ Retrieves events from a specified Google Calendar. Can retrieve a single event by ID or multiple events within a time range. You can also search for events by keyword by supplying the optional "query" param. Args: user_google_email (str): The user's Google email address. Required. calendar_id (str): The ID of the calendar to query. Use 'primary' for the user's primary calendar. Defaults to 'primary'. Calendar IDs can be obtained using `list_calendars`. event_id (Optional[str]): The ID of a specific event to retrieve. If provided, retrieves only this event and ignores time filtering parameters. time_min (Optional[str]): The start of the time range (inclusive) in RFC3339 format (e.g., '2024-05-12T10:00:00Z' or '2024-05-12'). If omitted, defaults to the current time. Ignored if event_id is provided. time_max (Optional[str]): The end of the time range (exclusive) in RFC3339 format. If omitted, events starting from `time_min` onwards are considered (up to `max_results`). Ignored if event_id is provided. max_results (int): The maximum number of events to return. Defaults to 25. Ignored if event_id is provided. query (Optional[str]): A keyword to search for within event fields (summary, description, location). Ignored if event_id is provided. detailed (bool): Whether to return detailed event information including description, location, attendees, and attendee details (response status, organizer, optional flags). Defaults to False. include_attachments (bool): Whether to include attachment information in detailed event output. When True, shows attachment details (fileId, fileUrl, mimeType, title) for events that have attachments. Only applies when detailed=True. Set this to True when you need to view or access files that have been attached to calendar events, such as meeting documents, presentations, or other shared files. Defaults to False. Returns: str: A formatted list of events (summary, start and end times, link) within the specified range, or detailed information for a single event if event_id is provided. """ logger.info( f"[get_events] Raw parameters - event_id: '{event_id}', time_min: '{time_min}', time_max: '{time_max}', query: '{query}', detailed: {detailed}, include_attachments: {include_attachments}" ) # Handle single event retrieval if event_id: logger.info(f"[get_events] Retrieving single event with ID: {event_id}") event = await asyncio.to_thread( lambda: service.events().get(calendarId=calendar_id, eventId=event_id).execute() ) items = [event] else: # Handle multiple events retrieval with time filtering # Ensure time_min and time_max are correctly formatted for the API formatted_time_min = _correct_time_format_for_api(time_min, "time_min") if formatted_time_min: effective_time_min = formatted_time_min else: utc_now = datetime.datetime.now(datetime.timezone.utc) effective_time_min = utc_now.isoformat().replace("+00:00", "Z") if time_min is None: logger.info( f"time_min not provided, defaulting to current UTC time: {effective_time_min}" ) else: logger.info( f"time_min processing: original='{time_min}', formatted='{formatted_time_min}', effective='{effective_time_min}'" ) effective_time_max = _correct_time_format_for_api(time_max, "time_max") if time_max: logger.info( f"time_max processing: original='{time_max}', formatted='{effective_time_max}'" ) logger.info( f"[get_events] Final API parameters - calendarId: '{calendar_id}', timeMin: '{effective_time_min}', timeMax: '{effective_time_max}', maxResults: {max_results}, query: '{query}'" ) # Build the request parameters dynamically request_params = { "calendarId": calendar_id, "timeMin": effective_time_min, "timeMax": effective_time_max, "maxResults": max_results, "singleEvents": True, "orderBy": "startTime", } if query: request_params["q"] = query events_result = await asyncio.to_thread( lambda: service.events() .list(**request_params) .execute() ) items = events_result.get("items", []) if not items: if event_id: return f"Event with ID '{event_id}' not found in calendar '{calendar_id}' for {user_google_email}." else: return f"No events found in calendar '{calendar_id}' for {user_google_email} for the specified time range." # Handle returning detailed output for a single event when requested if event_id and detailed: item = items[0] summary = item.get("summary", "No Title") start = item["start"].get("dateTime", item["start"].get("date")) end = item["end"].get("dateTime", item["end"].get("date")) link = item.get("htmlLink", "No Link") description = item.get("description", "No Description") location = item.get("location", "No Location") attendees = item.get("attendees", []) attendee_emails = ", ".join([a.get("email", "") for a in attendees]) if attendees else "None" attendee_details_str = _format_attendee_details(attendees, indent=" ") event_details = ( f'Event Details:\n' f'- Title: {summary}\n' f'- Starts: {start}\n' f'- Ends: {end}\n' f'- Description: {description}\n' f'- Location: {location}\n' f'- Attendees: {attendee_emails}\n' f'- Attendee Details: {attendee_details_str}\n' ) if include_attachments: attachments = item.get("attachments", []) attachment_details_str = _format_attachment_details(attachments, indent=" ") event_details += f'- Attachments: {attachment_details_str}\n' event_details += ( f'- Event ID: {event_id}\n' f'- Link: {link}' ) logger.info(f"[get_events] Successfully retrieved detailed event {event_id} for {user_google_email}.") return event_details # Handle multiple events or single event with basic output event_details_list = [] for item in items: summary = item.get("summary", "No Title") start_time = item["start"].get("dateTime", item["start"].get("date")) end_time = item["end"].get("dateTime", item["end"].get("date")) link = item.get("htmlLink", "No Link") item_event_id = item.get("id", "No ID") if detailed: # Add detailed information for multiple events description = item.get("description", "No Description") location = item.get("location", "No Location") attendees = item.get("attendees", []) attendee_emails = ", ".join([a.get("email", "") for a in attendees]) if attendees else "None" attendee_details_str = _format_attendee_details(attendees, indent=" ") event_detail_parts = ( f'- "{summary}" (Starts: {start_time}, Ends: {end_time})\n' f' Description: {description}\n' f' Location: {location}\n' f' Attendees: {attendee_emails}\n' f' Attendee Details: {attendee_details_str}\n' ) if include_attachments: attachments = item.get("attachments", []) attachment_details_str = _format_attachment_details(attachments, indent=" ") event_detail_parts += f' Attachments: {attachment_details_str}\n' event_detail_parts += f' ID: {item_event_id} | Link: {link}' event_details_list.append(event_detail_parts) else: # Basic output format event_details_list.append( f'- "{summary}" (Starts: {start_time}, Ends: {end_time}) ID: {item_event_id} | Link: {link}' ) if event_id: # Single event basic output text_output = f"Successfully retrieved event from calendar '{calendar_id}' for {user_google_email}:\n" + "\n".join(event_details_list) else: # Multiple events output text_output = ( f"Successfully retrieved {len(items)} events from calendar '{calendar_id}' for {user_google_email}:\n" + "\n".join(event_details_list) ) logger.info(f"Successfully retrieved {len(items)} events for {user_google_email}.") return text_output
  • Helper function used by get_events to correctly format time_min and time_max parameters for the Google Calendar API.
    def _correct_time_format_for_api( time_str: Optional[str], param_name: str ) -> Optional[str]: if not time_str: return None logger.info( f"_correct_time_format_for_api: Processing {param_name} with value '{time_str}'" ) # Handle date-only format (YYYY-MM-DD) if len(time_str) == 10 and time_str.count("-") == 2: try: # Validate it's a proper date datetime.datetime.strptime(time_str, "%Y-%m-%d") # For date-only, append T00:00:00Z to make it RFC3339 compliant formatted = f"{time_str}T00:00:00Z" logger.info( f"Formatting date-only {param_name} '{time_str}' to RFC3339: '{formatted}'" ) return formatted except ValueError: logger.warning( f"{param_name} '{time_str}' looks like a date but is not valid YYYY-MM-DD. Using as is." ) return time_str # Specifically address YYYY-MM-DDTHH:MM:SS by appending 'Z' if ( len(time_str) == 19 and time_str[10] == "T" and time_str.count(":") == 2 and not ( time_str.endswith("Z") or ("+" in time_str[10:]) or ("-" in time_str[10:]) ) ): try: # Validate the format before appending 'Z' datetime.datetime.strptime(time_str, "%Y-%m-%dT%H:%M:%S") logger.info( f"Formatting {param_name} '{time_str}' by appending 'Z' for UTC." ) return time_str + "Z" except ValueError: logger.warning( f"{param_name} '{time_str}' looks like it needs 'Z' but is not valid YYYY-MM-DDTHH:MM:SS. Using as is." ) return time_str # If it already has timezone info or doesn't match our patterns, return as is logger.info(f"{param_name} '{time_str}' doesn't need formatting, using as is.") return time_str
  • Helper for formatting attendee information in detailed event output.
    def _format_attendee_details(attendees: List[Dict[str, Any]], indent: str = " ") -> str: """ Format attendee details including response status, organizer, and optional flags. Example output format: " user@example.com: accepted manager@example.com: declined (organizer) optional-person@example.com: tentative (optional)" Args: attendees: List of attendee dictionaries from Google Calendar API indent: Indentation to use for newline-separated attendees (default: " ") Returns: Formatted string with attendee details, or "None" if no attendees """ if not attendees: return "None" attendee_details_list = [] for a in attendees: email = a.get("email", "unknown") response_status = a.get("responseStatus", "unknown") optional = a.get("optional", False) organizer = a.get("organizer", False) detail_parts = [f"{email}: {response_status}"] if organizer: detail_parts.append("(organizer)") if optional: detail_parts.append("(optional)") attendee_details_list.append(" ".join(detail_parts)) return f"\n{indent}".join(attendee_details_list)
  • Helper for formatting attachment information in detailed event output.
    def _format_attachment_details(attachments: List[Dict[str, Any]], indent: str = " ") -> str: """ Format attachment details including file information. Args: attachments: List of attachment dictionaries from Google Calendar API indent: Indentation to use for newline-separated attachments (default: " ") Returns: Formatted string with attachment details, or "None" if no attachments """ if not attachments: return "None" attachment_details_list = [] for att in attachments: title = att.get("title", "Untitled") file_url = att.get("fileUrl", "No URL") file_id = att.get("fileId", "No ID") mime_type = att.get("mimeType", "Unknown") attachment_info = ( f"{title}\n" f"{indent}File URL: {file_url}\n" f"{indent}File ID: {file_id}\n" f"{indent}MIME Type: {mime_type}" ) attachment_details_list.append(attachment_info) return f"\n{indent}".join(attachment_details_list)

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/taylorwilsdon/google_workspace_mcp'

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