Skip to main content
Glama
ZatesloFL

Google Workspace MCP Server

by ZatesloFL

create_event

Schedule events in Google Calendar by specifying details like time, location, and attendees. Optionally include Google Meet, reminders, attachments, and custom timezones.

Instructions

Creates a new event.

Args: user_google_email (str): The user's Google email address. Required. summary (str): Event title. start_time (str): Start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day). end_time (str): End time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day). calendar_id (str): Calendar ID (default: 'primary'). description (Optional[str]): Event description. location (Optional[str]): Event location. attendees (Optional[List[str]]): Attendee email addresses. timezone (Optional[str]): Timezone (e.g., "America/New_York"). attachments (Optional[List[str]]): List of Google Drive file URLs or IDs to attach to the event. add_google_meet (bool): Whether to add a Google Meet video conference to the event. Defaults to False. reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects. 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 (bool): Whether to use calendar's default reminders. If False, uses custom reminders. Defaults to True.

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

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
add_google_meetNo
attachmentsNo
attendeesNo
calendar_idNoprimary
descriptionNo
end_timeYes
locationNo
remindersNo
start_timeYes
summaryYes
timezoneNo
use_default_remindersNo
user_google_emailYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function that executes the create_event tool logic. It constructs the event body from parameters, handles special features like attachments, Google Meet conference, custom reminders, and inserts the event into the specified Google Calendar using the Google API.
    async def create_event(
        service,
        user_google_email: str,
        summary: str,
        start_time: str,
        end_time: str,
        calendar_id: str = "primary",
        description: Optional[str] = None,
        location: Optional[str] = None,
        attendees: Optional[List[str]] = None,
        timezone: Optional[str] = None,
        attachments: Optional[List[str]] = None,
        add_google_meet: bool = False,
        reminders: Optional[Union[str, List[Dict[str, Any]]]] = None,
        use_default_reminders: bool = True,
    ) -> str:
        """
        Creates a new event.
    
        Args:
            user_google_email (str): The user's Google email address. Required.
            summary (str): Event title.
            start_time (str): Start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
            end_time (str): End time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
            calendar_id (str): Calendar ID (default: 'primary').
            description (Optional[str]): Event description.
            location (Optional[str]): Event location.
            attendees (Optional[List[str]]): Attendee email addresses.
            timezone (Optional[str]): Timezone (e.g., "America/New_York").
            attachments (Optional[List[str]]): List of Google Drive file URLs or IDs to attach to the event.
            add_google_meet (bool): Whether to add a Google Meet video conference to the event. Defaults to False.
            reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects. 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 (bool): Whether to use calendar's default reminders. If False, uses custom reminders. Defaults to True.
    
        Returns:
            str: Confirmation message of the successful event creation with event link.
        """
        logger.info(
            f"[create_event] Invoked. Email: '{user_google_email}', Summary: {summary}"
        )
        logger.info(f"[create_event] Incoming attachments param: {attachments}")
        # If attachments value is a string, split by comma and strip whitespace
        if attachments and isinstance(attachments, str):
            attachments = [a.strip() for a in attachments.split(',') if a.strip()]
            logger.info(f"[create_event] Parsed attachments list from string: {attachments}")
        event_body: Dict[str, Any] = {
            "summary": summary,
            "start": (
                {"date": start_time}
                if "T" not in start_time
                else {"dateTime": start_time}
            ),
            "end": (
                {"date": end_time} if "T" not in end_time else {"dateTime": end_time}
            ),
        }
        if location:
            event_body["location"] = location
        if description:
            event_body["description"] = description
        if timezone:
            if "dateTime" in event_body["start"]:
                event_body["start"]["timeZone"] = timezone
            if "dateTime" in event_body["end"]:
                event_body["end"]["timeZone"] = timezone
        if attendees:
            event_body["attendees"] = [{"email": email} for email in attendees]
    
        # Handle reminders
        if reminders is not None or not use_default_reminders:
            # If custom reminders are provided, automatically disable default reminders
            effective_use_default = use_default_reminders and reminders is None
            
            reminder_data = {
                "useDefault": effective_use_default
            }
            if reminders is not None:
                validated_reminders = _parse_reminders_json(reminders, "create_event")
                if validated_reminders:
                    reminder_data["overrides"] = validated_reminders
                    logger.info(f"[create_event] Added {len(validated_reminders)} custom reminders")
                    if use_default_reminders:
                        logger.info("[create_event] Custom reminders provided - disabling default reminders")
            
            event_body["reminders"] = reminder_data
    
        if add_google_meet:
            request_id = str(uuid.uuid4())
            event_body["conferenceData"] = {
                "createRequest": {
                    "requestId": request_id,
                    "conferenceSolutionKey": {
                        "type": "hangoutsMeet"
                    }
                }
            }
            logger.info(f"[create_event] Adding Google Meet conference with request ID: {request_id}")
    
        if attachments:
            # Accept both file URLs and file IDs. If a URL, extract the fileId.
            event_body["attachments"] = []
            drive_service = None
            try:
                drive_service = service._http and build("drive", "v3", http=service._http)
            except Exception as e:
                logger.warning(f"Could not build Drive service for MIME type lookup: {e}")
            for att in attachments:
                file_id = None
                if att.startswith("https://"):
                    # Match /d/<id>, /file/d/<id>, ?id=<id>
                    match = re.search(r"(?:/d/|/file/d/|id=)([\w-]+)", att)
                    file_id = match.group(1) if match else None
                    logger.info(f"[create_event] Extracted file_id '{file_id}' from attachment URL '{att}'")
                else:
                    file_id = att
                    logger.info(f"[create_event] Using direct file_id '{file_id}' for attachment")
                if file_id:
                    file_url = f"https://drive.google.com/open?id={file_id}"
                    mime_type = "application/vnd.google-apps.drive-sdk"
                    title = "Drive Attachment"
                    # Try to get the actual MIME type and filename from Drive
                    if drive_service:
                        try:
                            file_metadata = await asyncio.to_thread(
                                lambda: drive_service.files().get(fileId=file_id, fields="mimeType,name").execute()
                            )
                            mime_type = file_metadata.get("mimeType", mime_type)
                            filename = file_metadata.get("name")
                            if filename:
                                title = filename
                                logger.info(f"[create_event] Using filename '{filename}' as attachment title")
                            else:
                                logger.info("[create_event] No filename found, using generic title")
                        except Exception as e:
                            logger.warning(f"Could not fetch metadata for file {file_id}: {e}")
                    event_body["attachments"].append({
                        "fileUrl": file_url,
                        "title": title,
                        "mimeType": mime_type,
                    })
            created_event = await asyncio.to_thread(
                lambda: service.events().insert(
                    calendarId=calendar_id, body=event_body, supportsAttachments=True,
                    conferenceDataVersion=1 if add_google_meet else 0
                ).execute()
            )
        else:
            created_event = await asyncio.to_thread(
                lambda: service.events().insert(
                    calendarId=calendar_id, body=event_body,
                    conferenceDataVersion=1 if add_google_meet else 0
                ).execute()
            )
        link = created_event.get("htmlLink", "No link available")
        confirmation_message = f"Successfully created event '{created_event.get('summary', summary)}' for {user_google_email}. Link: {link}"
    
        # Add Google Meet information if conference was created
        if add_google_meet and "conferenceData" in created_event:
            conference_data = created_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
    
        logger.info(
                f"Event created successfully for {user_google_email}. ID: {created_event.get('id')}, Link: {link}"
            )
        return confirmation_message
  • The @server.tool() decorator registers the create_event function as an MCP tool, with additional decorators for error handling and authentication.
    @server.tool()
  • Helper utility to parse and validate custom reminders input (JSON string or list) used in create_event for setting event reminders.
    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
  • The docstring provides the input schema and descriptions for the create_event tool parameters.
    """
    Creates a new event.
    
    Args:
        user_google_email (str): The user's Google email address. Required.
        summary (str): Event title.
        start_time (str): Start time (RFC3339, e.g., "2023-10-27T10:00:00-07:00" or "2023-10-27" for all-day).
        end_time (str): End time (RFC3339, e.g., "2023-10-27T11:00:00-07:00" or "2023-10-28" for all-day).
        calendar_id (str): Calendar ID (default: 'primary').
        description (Optional[str]): Event description.
        location (Optional[str]): Event location.
        attendees (Optional[List[str]]): Attendee email addresses.
        timezone (Optional[str]): Timezone (e.g., "America/New_York").
        attachments (Optional[List[str]]): List of Google Drive file URLs or IDs to attach to the event.
        add_google_meet (bool): Whether to add a Google Meet video conference to the event. Defaults to False.
        reminders (Optional[Union[str, List[Dict[str, Any]]]]): JSON string or list of reminder objects. 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 (bool): Whether to use calendar's default reminders. If False, uses custom reminders. Defaults to True.
    
    Returns:
        str: Confirmation message of the successful event creation with event link.
    """
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It partially succeeds by describing the return value (confirmation message with event link) and some behavioral aspects like default values for 'calendar_id', 'add_google_meet', and 'use_default_reminders'. However, it lacks critical details such as error handling, rate limits, authentication requirements, or what happens with invalid inputs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (Args, Returns) and efficiently documents each parameter without redundancy. However, the 'Args' section is lengthy due to the high parameter count, and the opening line 'Creates a new event.' is somewhat redundant with the tool name, though it serves as a brief summary.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (13 parameters, no annotations, but with output schema), the description is largely complete. It thoroughly documents parameters and return values, though it could improve by adding usage context (e.g., authentication needs, error cases). The output schema exists, so the description appropriately focuses on input semantics and high-level behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully compensate. It does so comprehensively by documenting all 13 parameters with clear semantics, data types, examples (e.g., RFC3339 format for times), constraints (e.g., max 5 reminders), and default values. This adds significant value beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb ('Creates') and resource ('new event'), making it immediately understandable. It distinguishes from sibling tools like 'modify_event' and 'delete_event' by focusing on creation rather than modification or deletion.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., authentication), when to choose 'create_event' over 'modify_event', or any limitations (e.g., calendar permissions). The agent must infer usage from the tool name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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

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