Skip to main content
Glama
taylorwilsdon

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

modify_event

Edit existing calendar events by updating details such as title, time, location, attendees, and description. Designed for Google Workspace users to manage events efficiently.

Instructions

Modifies an existing event.

Args:
    user_google_email (str): The user's Google email address. Required.
    event_id (str): The ID of the event to modify.
    calendar_id (str): Calendar ID (default: 'primary').
    summary (Optional[str]): New event title.
    start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
    end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
    description (Optional[str]): New event description.
    location (Optional[str]): New event location.
    attendees (Optional[List[str]]): New attendee email addresses.
    timezone (Optional[str]): New timezone (e.g., "America/New_York").

Returns:
    str: Confirmation message of the successful event modification with event link.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
attendeesNo
calendar_idNoprimary
descriptionNo
end_timeNo
event_idYes
locationNo
serviceYes
start_timeNo
summaryNo
timezoneNo
user_google_emailYes

Implementation Reference

  • Registers the 'modify_event' function as a server tool using the @server.tool() decorator from core.server.
    @server.tool()
  • The function signature and comprehensive docstring define the schema for the 'modify_event' tool inputs, including optional parameters for event fields, reminders, transparency, and Google Meet.
    async def modify_event(
        service,
        user_google_email: str,
        event_id: str,
        calendar_id: str = "primary",
        summary: Optional[str] = None,
        start_time: Optional[str] = None,
        end_time: Optional[str] = None,
        description: Optional[str] = None,
        location: Optional[str] = None,
        attendees: Optional[List[str]] = None,
        timezone: Optional[str] = None,
        add_google_meet: Optional[bool] = None,
        reminders: Optional[Union[str, List[Dict[str, Any]]]] = None,
        use_default_reminders: Optional[bool] = None,
        transparency: Optional[str] = None,
    ) -> str:
        """
        Modifies an existing event.
    
        Args:
            user_google_email (str): The user's Google email address. Required.
            event_id (str): The ID of the event to modify.
            calendar_id (str): Calendar ID (default: 'primary').
            summary (Optional[str]): New event title.
            start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
            end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
            description (Optional[str]): New event description.
            location (Optional[str]): New event location.
            attendees (Optional[List[str]]): New attendee email addresses.
            timezone (Optional[str]): New timezone (e.g., "America/New_York").
            add_google_meet (Optional[bool]): Whether to add or remove Google Meet video conference. If True, adds Google Meet; if False, removes it; if None, leaves unchanged.
            reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects to replace existing reminders. Each should have 'method' ("popup" or "email") and 'minutes' (0-40320). Max 5 reminders. Example: '[{"method": "popup", "minutes": 15}]' or [{"method": "popup", "minutes": 15}]
            use_default_reminders (Optional[bool]): Whether to use calendar's default reminders. If specified, overrides current reminder settings.
            transparency (Optional[str]): Event transparency for busy/free status. "opaque" shows as Busy, "transparent" shows as Available/Free. If None, preserves existing transparency setting.
    
        Returns:
            str: Confirmation message of the successful event modification with event link.
        """
  • Core handler logic for modifying Google Calendar events. Constructs update payload from optional parameters, preserves existing data, handles special features like reminders, transparency, and Google Meet, then executes the Google Calendar API update.
    async def modify_event(
        service,
        user_google_email: str,
        event_id: str,
        calendar_id: str = "primary",
        summary: Optional[str] = None,
        start_time: Optional[str] = None,
        end_time: Optional[str] = None,
        description: Optional[str] = None,
        location: Optional[str] = None,
        attendees: Optional[List[str]] = None,
        timezone: Optional[str] = None,
        add_google_meet: Optional[bool] = None,
        reminders: Optional[Union[str, List[Dict[str, Any]]]] = None,
        use_default_reminders: Optional[bool] = None,
        transparency: Optional[str] = None,
    ) -> str:
        """
        Modifies an existing event.
    
        Args:
            user_google_email (str): The user's Google email address. Required.
            event_id (str): The ID of the event to modify.
            calendar_id (str): Calendar ID (default: 'primary').
            summary (Optional[str]): New event title.
            start_time (Optional[str]): New start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
            end_time (Optional[str]): New end time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
            description (Optional[str]): New event description.
            location (Optional[str]): New event location.
            attendees (Optional[List[str]]): New attendee email addresses.
            timezone (Optional[str]): New timezone (e.g., "America/New_York").
            add_google_meet (Optional[bool]): Whether to add or remove Google Meet video conference. If True, adds Google Meet; if False, removes it; if None, leaves unchanged.
            reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects to replace existing reminders. Each should have 'method' ("popup" or "email") and 'minutes' (0-40320). Max 5 reminders. Example: '[{"method": "popup", "minutes": 15}]' or [{"method": "popup", "minutes": 15}]
            use_default_reminders (Optional[bool]): Whether to use calendar's default reminders. If specified, overrides current reminder settings.
            transparency (Optional[str]): Event transparency for busy/free status. "opaque" shows as Busy, "transparent" shows as Available/Free. If None, preserves existing transparency setting.
    
        Returns:
            str: Confirmation message of the successful event modification with event link.
        """
        logger.info(
            f"[modify_event] Invoked. Email: '{user_google_email}', Event ID: {event_id}"
        )
    
        # Build the event body with only the fields that are provided
        event_body: Dict[str, Any] = {}
        if summary is not None:
            event_body["summary"] = summary
        if start_time is not None:
            event_body["start"] = (
                {"date": start_time}
                if "T" not in start_time
                else {"dateTime": start_time}
            )
            if timezone is not None and "dateTime" in event_body["start"]:
                event_body["start"]["timeZone"] = timezone
        if end_time is not None:
            event_body["end"] = (
                {"date": end_time} if "T" not in end_time else {"dateTime": end_time}
            )
            if timezone is not None and "dateTime" in event_body["end"]:
                event_body["end"]["timeZone"] = timezone
        if description is not None:
            event_body["description"] = description
        if location is not None:
            event_body["location"] = location
        if attendees is not None:
            event_body["attendees"] = [{"email": email} for email in attendees]
        
        # Handle reminders
        if reminders is not None or use_default_reminders is not None:
            reminder_data = {}
            if use_default_reminders is not None:
                reminder_data["useDefault"] = use_default_reminders
            else:
                # Preserve existing event's useDefault value if not explicitly specified
                try:
                    existing_event = service.events().get(calendarId=calendar_id, eventId=event_id).execute()
                    reminder_data["useDefault"] = existing_event.get("reminders", {}).get("useDefault", True)
                except Exception as e:
                    logger.warning(f"[modify_event] Could not fetch existing event for reminders: {e}")
                    reminder_data["useDefault"] = True  # Fallback to True if unable to fetch
            
            # If custom reminders are provided, automatically disable default reminders
            if reminders is not None:
                if reminder_data.get("useDefault", False):
                    reminder_data["useDefault"] = False
                    logger.info("[modify_event] Custom reminders provided - disabling default reminders")
                
                validated_reminders = _parse_reminders_json(reminders, "modify_event")
                if reminders and not validated_reminders:
                    logger.warning("[modify_event] Reminders provided but failed validation. No custom reminders will be set.")
                elif validated_reminders:
                    reminder_data["overrides"] = validated_reminders
                    logger.info(f"[modify_event] Updated reminders with {len(validated_reminders)} custom reminders")
            
            event_body["reminders"] = reminder_data
    
        # Handle transparency validation
        _apply_transparency_if_valid(event_body, transparency, "modify_event")
    
        if (
            timezone is not None
            and "start" not in event_body
            and "end" not in event_body
        ):
            # If timezone is provided but start/end times are not, we need to fetch the existing event
            # to apply the timezone correctly. This is a simplification; a full implementation
            # might handle this more robustly or require start/end with timezone.
            # For now, we'll log a warning and skip applying timezone if start/end are missing.
            logger.warning(
                "[modify_event] Timezone provided but start_time and end_time are missing. Timezone will not be applied unless start/end times are also provided."
            )
    
        if not event_body:
            message = "No fields provided to modify the event."
            logger.warning(f"[modify_event] {message}")
            raise Exception(message)
    
        # Log the event ID for debugging
        logger.info(
            f"[modify_event] Attempting to update event with ID: '{event_id}' in calendar '{calendar_id}'"
        )
    
        # Get the existing event to preserve fields that aren't being updated
        try:
            existing_event = await asyncio.to_thread(
                lambda: service.events().get(calendarId=calendar_id, eventId=event_id).execute()
            )
            logger.info(
                "[modify_event] Successfully retrieved existing event before update"
            )
    
            # Preserve existing fields if not provided in the update
            _preserve_existing_fields(event_body, existing_event, {
                "summary": summary,
                "description": description,
                "location": location,
                "attendees": attendees
            })
    
            # Handle Google Meet conference data
            if add_google_meet is not None:
                if add_google_meet:
                    # Add Google Meet
                    request_id = str(uuid.uuid4())
                    event_body["conferenceData"] = {
                        "createRequest": {
                            "requestId": request_id,
                            "conferenceSolutionKey": {
                                "type": "hangoutsMeet"
                            }
                        }
                    }
                    logger.info(f"[modify_event] Adding Google Meet conference with request ID: {request_id}")
                else:
                    # Remove Google Meet by setting conferenceData to empty
                    event_body["conferenceData"] = {}
                    logger.info("[modify_event] Removing Google Meet conference")
            elif 'conferenceData' in existing_event:
                # Preserve existing conference data if not specified
                event_body["conferenceData"] = existing_event["conferenceData"]
                logger.info("[modify_event] Preserving existing conference data")
    
        except HttpError as get_error:
            if get_error.resp.status == 404:
                logger.error(
                    f"[modify_event] Event not found during pre-update verification: {get_error}"
                )
                message = f"Event not found during verification. The event with ID '{event_id}' could not be found in calendar '{calendar_id}'. This may be due to incorrect ID format or the event no longer exists."
                raise Exception(message)
            else:
                logger.warning(
                    f"[modify_event] Error during pre-update verification, but proceeding with update: {get_error}"
                )
    
        # Proceed with the update
        updated_event = await asyncio.to_thread(
            lambda: service.events()
            .update(calendarId=calendar_id, eventId=event_id, body=event_body, conferenceDataVersion=1)
            .execute()
        )
    
        link = updated_event.get("htmlLink", "No link available")
        confirmation_message = f"Successfully modified event '{updated_event.get('summary', summary)}' (ID: {event_id}) for {user_google_email}. Link: {link}"
    
        # Add Google Meet information if conference was added
        if add_google_meet is True and "conferenceData" in updated_event:
            conference_data = updated_event["conferenceData"]
            if "entryPoints" in conference_data:
                for entry_point in conference_data["entryPoints"]:
                    if entry_point.get("entryPointType") == "video":
                        meet_link = entry_point.get("uri", "")
                        if meet_link:
                            confirmation_message += f" Google Meet: {meet_link}"
                            break
        elif add_google_meet is False:
            confirmation_message += " (Google Meet removed)"
    
        logger.info(
            f"Event modified successfully for {user_google_email}. ID: {updated_event.get('id')}, Link: {link}"
        )
        return confirmation_message
  • Helper to parse and validate custom reminders JSON/list input. Used in modify_event for the 'reminders' parameter.
    def _parse_reminders_json(reminders_input: Optional[Union[str, List[Dict[str, Any]]]], function_name: str) -> List[Dict[str, Any]]:
        """
        Parse reminders from JSON string or list object and validate them.
        
        Args:
            reminders_input: JSON string containing reminder objects or list of reminder objects
            function_name: Name of calling function for logging
            
        Returns:
            List of validated reminder objects
        """
        if not reminders_input:
            return []
        
        # Handle both string (JSON) and list inputs
        if isinstance(reminders_input, str):
            try:
                reminders = json.loads(reminders_input)
                if not isinstance(reminders, list):
                    logger.warning(f"[{function_name}] Reminders must be a JSON array, got {type(reminders).__name__}")
                    return []
            except json.JSONDecodeError as e:
                logger.warning(f"[{function_name}] Invalid JSON for reminders: {e}")
                return []
        elif isinstance(reminders_input, list):
            reminders = reminders_input
        else:
            logger.warning(f"[{function_name}] Reminders must be a JSON string or list, got {type(reminders_input).__name__}")
            return []
        
        # Validate reminders
        if len(reminders) > 5:
            logger.warning(f"[{function_name}] More than 5 reminders provided, truncating to first 5")
            reminders = reminders[:5]
        
        validated_reminders = []
        for reminder in reminders:
            if not isinstance(reminder, dict) or "method" not in reminder or "minutes" not in reminder:
                logger.warning(f"[{function_name}] Invalid reminder format: {reminder}, skipping")
                continue
            
            method = reminder["method"].lower()
            if method not in ["popup", "email"]:
                logger.warning(f"[{function_name}] Invalid reminder method '{method}', must be 'popup' or 'email', skipping")
                continue
            
            minutes = reminder["minutes"]
            if not isinstance(minutes, int) or minutes < 0 or minutes > 40320:
                logger.warning(f"[{function_name}] Invalid reminder minutes '{minutes}', must be integer 0-40320, skipping")
                continue
            
            validated_reminders.append({
                "method": method,
                "minutes": minutes
            })
        
        return validated_reminders
  • Helper to preserve existing event fields (summary, description, location, attendees) when not explicitly updated in modify_event.
    def _preserve_existing_fields(event_body: Dict[str, Any], existing_event: Dict[str, Any], field_mappings: Dict[str, Any]) -> None:
        """
        Helper function to preserve existing event fields when not explicitly provided.
    
        Args:
            event_body: The event body being built for the API call
            existing_event: The existing event data from the API
            field_mappings: Dict mapping field names to their new values (None means preserve existing)
        """
        for field_name, new_value in field_mappings.items():
            if new_value is None and field_name in existing_event:
                event_body[field_name] = existing_event[field_name]
                logger.info(f"[modify_event] Preserving existing {field_name}")
            elif new_value is not None:
                event_body[field_name] = new_value

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