Skip to main content

Google Calendar

Google Calendar · OAuth 2.0

Calendar Adapter Architecture

GoogleCalendarService → GoogleCalendarAdapter → Google Calendar API v3

GoogleCalendarService
service.py · @service_method
list_calendars
list_events
create_event
get_free_busy
+ 8 more
calls
GoogleCalendarAdapter
adapter.py · httpx
Authorization: Bearer <token>
RFC 3339 datetimes
Recurring events / RRULE
REST
Google Calendar API v3
calendar.googleapis.com
calendar.readonly
calendar.events
calendar.events.readonly
Auto-generated from @service_method decorators
🌐
HTTP Routes
GET / POST / PUT / DELETE
⌨️
CLI Commands
constellation google-calendar …
🤖
MCP Tools
googlecalendar:list_events …

What & Why

Google Calendar integration gives your agents and workflows direct access to schedule and availability data. Key use cases:

  • Availability checking — call get_free_busy before booking any meeting; supports querying multiple users in one request
  • Meeting creation — create events with attendees, location, description, and recurrence rules
  • Calendar sync — list all calendars for a user, enumerate events across a date range, and keep downstream systems in sync
  • Recurring event management — full RRULE support; create, update, or delete recurring series

Auth uses Google OAuth 2.0. The adapter attaches the access token in the Authorization: Bearer header on every request. All datetimes follow RFC 3339 (e.g. 2026-05-13T09:00:00+00:00). All-day events use a plain date value instead of dateTime.


Event Data Model

Google Calendar Event Structure
Timed Event (dateTime)
summary: "Team standup"
description: "Daily sync"
location: "Zoom link"
start:
dateTime: "2026-05-13T09:00:00Z"
timeZone: "Europe/London"
end:
dateTime: "2026-05-13T09:30:00Z"
attendees: [
]
recurrence: [
"RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"
]
reminders:
useDefault: false
overrides: [{method: email, minutes: 10}]

dateTime — includes time + timezone. RFC 3339 format required.

All-Day Event (date)
summary: "Company offsite"
start:
date: "2026-06-01"
end:
date: "2026-06-03"

date only — no time, no timezone. End date is exclusive (non-inclusive).

Free/Busy Query
timeMin: "2026-05-13T00:00:00Z"
timeMax: "2026-05-14T00:00:00Z"
items: [
{id: "a@co.com"},
{id: "b@co.com"},
]

Returns busy blocks per email. Use to check availability before booking.


Methods Reference

MethodDescriptionKey Parameters
list_calendarsList all calendars accessible by the authenticated user
get_calendarGet metadata for a specific calendarcalendar_id
create_calendarCreate a new calendarsummary, time_zone
delete_calendarDelete a calendar permanentlycalendar_id
list_eventsList events in a calendar, optionally filtered by date rangecalendar_id, time_min, time_max, max_results, single_events, order_by
get_eventGet a single event by IDcalendar_id, event_id
create_eventCreate a new event with attendees, recurrence, and reminderscalendar_id, summary, start, end, attendees, recurrence, description, location, reminders
update_eventUpdate an existing event (full or partial update)calendar_id, event_id, plus any fields to update
delete_eventDelete an eventcalendar_id, event_id
move_eventMove an event to a different calendarcalendar_id, event_id, destination_calendar_id
get_free_busyQuery free/busy blocks for one or more users over a time rangeemails, time_min, time_max, time_zone
list_colorsList all available colors for calendars and events

CLI Examples

# List all calendars for the authenticated user
constellation google-calendar list-calendars

# List events in the primary calendar from May 1st onwards
constellation google-calendar list-events \
--calendar-id primary \
--time-min 2026-05-01

# Get a specific event
constellation google-calendar get-event \
--calendar-id primary \
--event-id abc123xyz

# Create a recurring daily standup with attendees
constellation google-calendar create-event \
--summary "Team standup" \
--start "2026-05-13T09:00:00" \
--end "2026-05-13T09:30:00" \
--attendees "a@co.com,b@co.com" \
--recurrence "RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"

# Update an existing event summary
constellation google-calendar update-event \
--calendar-id primary \
--event-id abc123xyz \
--summary "Team standup (updated)"

# Move an event to a different calendar
constellation google-calendar move-event \
--calendar-id primary \
--event-id abc123xyz \
--destination-calendar-id work@group.calendar.google.com

# Delete an event
constellation google-calendar delete-event \
--calendar-id primary \
--event-id abc123xyz

# Check availability for two users over a full day
constellation google-calendar get-free-busy \
--emails "a@co.com,b@co.com" \
--time-min "2026-05-13T00:00:00Z" \
--time-max "2026-05-14T00:00:00Z"

# List all available colors for calendars and events
constellation google-calendar list-colors

Auth Scopes

ScopePurpose
calendar.readonlyRead-only access to all calendars and events
calendar.eventsFull read/write access to events (create, update, delete)
calendar.events.readonlyRead-only access to events only

The adapter requests the minimum scopes needed for the operations being performed. For full CRUD access, calendar.events is required. For availability-only workflows, calendar.readonly is sufficient.


Notes

  • RFC 3339 datetimes — all start/end fields must use RFC 3339 format. The adapter handles timezone normalization automatically.
  • All-day events — use date (e.g. "2026-06-01") instead of dateTime. The end date is exclusive (a one-day event ends the following day).
  • Recurring events — use RRULE strings in the recurrence field. The Google Calendar API expands recurring instances; set single_events=true in list_events to retrieve expanded instances rather than the master event.
  • Primary calendar — use the string "primary" as the calendar_id to refer to the authenticated user's default calendar without needing the full calendar ID.
  • get_free_busy — accepts a list of email addresses and returns per-user busy blocks. This is the recommended way to check scheduling conflicts before creating events with attendees.