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

NameRequiredDescriptionDefault
confirmNo
dateYes
descriptionNo
duration_minutesNo
note_pathYes
timeYes
titleYes

Input Schema (JSON Schema)

{ "properties": { "confirm": { "default": false, "title": "Confirm", "type": "boolean" }, "date": { "title": "Date", "type": "string" }, "description": { "default": "", "title": "Description", "type": "string" }, "duration_minutes": { "default": 60, "title": "Duration Minutes", "type": "integer" }, "note_path": { "title": "Note Path", "type": "string" }, "time": { "title": "Time", "type": "string" }, "title": { "title": "Title", "type": "string" } }, "required": [ "note_path", "title", "date", "time" ], "type": "object" }

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", )

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