Skip to main content
Glama

create_calendar_event

Create Google Calendar events directly from Obsidian notes to schedule tasks and reminders with automatic linking between your calendar and notes.

Instructions

Create a Google Calendar event linked to an Obsidian note

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
confirmNo
dateYes
descriptionNo
duration_minutesNo
note_pathYes
timeYes
titleYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • MCP tool handler for create_calendar_event. Validates input, verifies note exists, parses datetime, creates event via CalendarService, adds Obsidian link to description, updates note frontmatter with event details.
        name="create_calendar_event",
        description="Create a Google Calendar event linked to an Obsidian note",
    )
    async def create_calendar_event(
        note_path: str,
        title: str,
        date: str,
        time: str,
        duration_minutes: int = 60,
        description: str = "",
        confirm: bool = False,
    ) -> str:
        """
        Create a Google Calendar event linked to a note.
    
        Args:
            note_path: Relative path to the note
            title: Event title
            date: Event date (YYYY-MM-DD)
            time: Event time (HH:MM in 24-hour format)
            duration_minutes: Event duration in minutes (default: 60)
            description: Optional event description
            confirm: Must be set to true to confirm calendar event creation
    
        Returns:
            Success message with event details
        """
        if not confirm:
            return (
                "Error: Calendar event creation requires explicit confirmation. "
                "Please set confirm=true to proceed with creating this event."
            )
        if not note_path or not note_path.strip():
            return "Error: Note path cannot be empty"
        if not title or not title.strip():
            return "Error: Title cannot be empty"
    
        context = _get_context()
    
        try:
            # Verify note exists
            if not context.vault.note_exists(note_path):
                return f"Error: Note not found: {note_path}"
    
            # Parse date and time
            try:
                event_datetime = datetime.strptime(f"{date} {time}", "%Y-%m-%d %H:%M")
                end_datetime = event_datetime + timedelta(minutes=duration_minutes)
            except ValueError as e:
                return f"Error: Invalid date/time format: {e}. Use YYYY-MM-DD and HH:MM"
    
            # Build obsidian:// link
            obsidian_link = f"{context.config.obsidian_url_base}{note_path}"
    
            # Add link to description
            full_description = f"{description}\n\nLinked note: {obsidian_link}"
    
            # Create calendar event
            calendar = context.get_calendar()
            event = calendar.create_event(
                summary=title,
                start_datetime=event_datetime,
                end_datetime=end_datetime,
                description=full_description,
            )
    
            event_id = event.get("id")
            event_link = event.get("htmlLink")
    
            # Update note frontmatter with event info
            try:
                note = await context.vault.read_note(note_path)
                frontmatter = note.frontmatter or {}
    
                # Add calendar event info
                frontmatter["calendar_event_id"] = event_id
                frontmatter["calendar_event_link"] = event_link
                frontmatter["calendar_event_date"] = date
                frontmatter["calendar_event_time"] = time
    
                await context.vault.update_note(note_path, note.body, frontmatter)
            except Exception as e:
                logger.warning(f"Failed to update note frontmatter: {e}")
    
            return (
                f"✓ Created calendar event: {title}\n"
                f"   Date: {date} at {time}\n"
                f"   Duration: {duration_minutes} minutes\n"
                f"   Event link: {event_link}\n"
                f"   Note link added to event description"
            )
    
        except CalendarAuthError as e:
            return f"Error: Calendar not configured: {e}"
        except CalendarError as e:
            return f"Error creating event: {e}"
        except VaultSecurityError as e:
            return f"Error: Security violation: {e}"
        except Exception as e:
            logger.exception("Error creating calendar event")
            return f"Error creating calendar event: {e}"
  • Core implementation in CalendarService that interacts with Google Calendar API to insert a new event.
    def create_event(
        self,
        summary: str,
        start_datetime: datetime,
        end_datetime: datetime,
        description: str | None = None,
        location: str | None = None,
    ) -> dict[str, Any]:
        """
        Create a calendar event.
    
        Args:
            summary: Event title
            start_datetime: Event start time
            end_datetime: Event end time
            description: Optional event description
            location: Optional location
    
        Returns:
            Created event details
    
        Raises:
            CalendarError: If event creation fails
        """
        service = self.get_service()
    
        event_body: dict[str, Any] = {
            "summary": summary,
            "start": {
                "dateTime": start_datetime.isoformat(),
                "timeZone": "UTC",
            },
            "end": {
                "dateTime": end_datetime.isoformat(),
                "timeZone": "UTC",
            },
        }
    
        if description:
            event_body["description"] = description
    
        if location:
            event_body["location"] = location
    
        try:
            event = service.events().insert(calendarId=self.calendar_id, body=event_body).execute()
            logger.info(f"Created calendar event: {event.get('id')}")
            return event  # type: ignore[no-any-return]
        except HttpError as e:
            raise CalendarError(f"Failed to create event: {e}") from e
  • ServerContext method to initialize and return the CalendarService instance used by the handler.
    def get_calendar(self) -> CalendarService:
        """
        Get or create calendar service.
    
        Returns:
            Calendar service
    
        Raises:
            CalendarAuthError: If calendar not configured or auth fails
        """
        if not self.config.calendar_enabled or not self.config.calendar_credentials_path:
            raise CalendarAuthError(
                "Google Calendar not configured. Set GOOGLE_CALENDAR_CREDENTIALS_PATH"
            )
    
        if self._calendar is None:
            self._calendar = CalendarService(
                str(self.config.calendar_credentials_path),
                self.config.calendar_id,
                headless=self.config.calendar_headless,
            )
    
        return self._calendar
  • MCP tool registration decorator.
        name="create_calendar_event",
        description="Create a Google Calendar event linked to an Obsidian note",
    )
Behavior2/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 states the tool creates events but lacks details on permissions required, whether events are public/private, error handling, or what 'linked' entails (e.g., bidirectional sync). This is inadequate for a mutation tool with zero annotation coverage.

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

Conciseness5/5

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

The description is a single, efficient sentence that front-loads the core purpose without unnecessary elaboration. Every word earns its place, making it easy to parse quickly.

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

Completeness2/5

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

For a mutation tool with 7 parameters, 0% schema coverage, no annotations, and an output schema (which helps but isn't described), the description is incomplete. It lacks parameter semantics, behavioral context, and usage guidelines, leaving critical gaps for an AI agent to invoke it correctly.

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

Parameters2/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 compensate but adds no parameter information. It doesn't explain what 'note_path' expects, how 'date' and 'time' should be formatted, or the purpose of the 'confirm' parameter. With 7 parameters undocumented in both schema and description, this is a significant gap.

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

Purpose4/5

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

The description clearly states the action ('Create') and resource ('Google Calendar event linked to an Obsidian note'), making the purpose immediately understandable. It distinguishes from siblings like 'create_note' by specifying the calendar integration, though it doesn't explicitly contrast with 'update_calendar_event' or 'delete_calendar_event'.

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?

No guidance is provided on when to use this tool versus alternatives like 'create_note' for standalone notes or 'update_calendar_event' for modifying existing events. The description implies usage for creating calendar events with note links but offers no explicit context, prerequisites, or exclusions.

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/getglad/obsidian_mcp'

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