Schedule smarter β create, search, and manage Google Calendar events through AI.
A Model Context Protocol (MCP) server that exposes Google Calendar's API for creating, reading, updating, and deleting events and calendars.
Overview
The Google Calendar MCP Server provides full calendar management directly from AI workflows:
- List, search, and retrieve events with rich filtering by time range, text, and recurrence
- Create single, all-day, quick, and recurring events with attendees, reminders, and Meet links
- Update events and manage attendees, then get before/after state in a single response
- Query free/busy blocks across multiple calendars to find open slots without conflicts
Perfect for:
- AI assistants that schedule, reschedule, and manage meetings on behalf of users
- Workflow automation that reads calendar state to trigger time-based actions
- Agents that coordinate availability and send invitations across teams
Tools
Events β Read
list_events β List events from a calendar
Lists events from a calendar within an optional time range. Returns events in start-time order. Recurring events are expanded into individual instances. Use ISO 8601 for time_min/time_max: 'YYYY-MM-DDTHH:MM:SSZ' (e.g. '2026-01-08T00:00:00Z'). Defaults to events from now onwards if time_min is not specified.
Inputs:
- `calendar_id` (string, optional, default: "primary") β Calendar ID. Use 'primary' for the user's main calendar
- `max_results` (int, optional, default: 10) β Maximum number of events to return (1β2500)
- `time_min` (string, optional, default: "") β Start of time range in ISO 8601 format, e.g. '2026-01-08T00:00:00Z'. Defaults to now
- `time_max` (string, optional, default: "") β End of time range in ISO 8601 format, e.g. '2026-01-15T23:59:59Z'. Omit for open-ended
- `query` (string, optional, default: "") β Free-text search query to filter events by title, description, or location
- `show_deleted` (bool, optional, default: false) β Include cancelled events in results
- `page_token` (string, optional, default: "") β Pagination token from a previous response's next_page_token to fetch the next page
Output data schema:
{
count: number;
events: {
id: string;
summary: string | null;
start: { date: string | null; dateTime: string | null; timeZone: string | null; };
end: { date: string | null; dateTime: string | null; timeZone: string | null; };
status: string | null;
htmlLink: string | null;
created: string | null;
updated: string | null;
description: string | null;
location: string | null;
colorId: string | null;
creator: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
organizer: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
recurrence: string[] | null;
recurringEventId: string | null;
originalStartTime: { date: string | null; dateTime: string | null; timeZone: string | null; } | null;
transparency: string | null;
visibility: string | null;
iCalUID: string | null;
sequence: number | null;
attendees: {
email: string;
id: string | null;
displayName: string | null;
organizer: boolean | null;
self: boolean | null;
resource: boolean | null;
optional: boolean | null;
responseStatus: string | null;
comment: string | null;
additionalGuests: number | null;
}[] | null;
attendeesOmitted: boolean | null;
guestsCanInviteOthers: boolean | null;
guestsCanModify: boolean | null;
guestsCanSeeOtherGuests: boolean | null;
hangoutLink: string | null;
conferenceData: object | null;
reminders: { useDefault: boolean; overrides: { method: string; minutes: number; }[] | null; } | null;
eventType: string | null;
}[];
next_page_token: string | null;
}
get_event β Get a single event by ID
Gets full details of a specific event including attendees, RSVP statuses, recurrence rules, reminders, and conferencing info.
Inputs:
- `event_id` (string, required) β ID of the event to retrieve
- `calendar_id` (string, optional, default: "primary") β Calendar ID containing the event. Use 'primary' for the user's main calendar
Output data schema:
{
id: string;
summary: string | null;
start: { date: string | null; dateTime: string | null; timeZone: string | null; };
end: { date: string | null; dateTime: string | null; timeZone: string | null; };
status: string | null;
htmlLink: string | null;
created: string | null;
updated: string | null;
description: string | null;
location: string | null;
colorId: string | null;
creator: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
organizer: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
recurrence: string[] | null;
recurringEventId: string | null;
originalStartTime: { date: string | null; dateTime: string | null; timeZone: string | null; } | null;
transparency: string | null;
visibility: string | null;
iCalUID: string | null;
sequence: number | null;
attendees: {
email: string;
id: string | null;
displayName: string | null;
organizer: boolean | null;
self: boolean | null;
resource: boolean | null;
optional: boolean | null;
responseStatus: string | null;
comment: string | null;
additionalGuests: number | null;
}[] | null;
attendeesOmitted: boolean | null;
guestsCanInviteOthers: boolean | null;
guestsCanModify: boolean | null;
guestsCanSeeOtherGuests: boolean | null;
hangoutLink: string | null;
conferenceData: object | null;
reminders: { useDefault: boolean; overrides: { method: string; minutes: number; }[] | null; } | null;
eventType: string | null;
}
search_events β Search events by text
Searches for events by text across titles, descriptions, and locations. Optionally bound the search to a time range with time_min/time_max (ISO 8601, e.g. '2026-01-08T00:00:00Z'). Without a time range the search spans all history β always use a time range for large calendars.
Inputs:
- `query` (string, required) β Text to search for in event titles, descriptions, and locations
- `calendar_id` (string, optional, default: "primary") β Calendar ID to search in. Use 'primary' for the user's main calendar
- `max_results` (int, optional, default: 10) β Maximum number of events to return (1β2500)
- `time_min` (string, optional, default: "") β Optional start of time range in ISO 8601 format, e.g. '2026-01-01T00:00:00Z'
- `time_max` (string, optional, default: "") β Optional end of time range in ISO 8601 format, e.g. '2026-12-31T23:59:59Z'
- `page_token` (string, optional, default: "") β Pagination token from a previous response's next_page_token to fetch the next page
Output data schema:
{
count: number;
events: {
id: string;
summary: string | null;
start: { date: string | null; dateTime: string | null; timeZone: string | null; };
end: { date: string | null; dateTime: string | null; timeZone: string | null; };
status: string | null;
htmlLink: string | null;
created: string | null;
updated: string | null;
description: string | null;
location: string | null;
colorId: string | null;
creator: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
organizer: { id: string | null; email: string | null; displayName: string | null; self: boolean | null; } | null;
recurrence: string[] | null;
recurringEventId: string | null;
originalStartTime: { date: string | null; dateTime: string | null; timeZone: string | null; } | null;
transparency: string | null;
visibility: string | null;
iCalUID: string | null;
sequence: number | null;
attendees: {
email: string;
id: string | null;
displayName: string | null;
organizer: boolean | null;
self: boolean | null;
resource: boolean | null;
optional: boolean | null;
responseStatus: string | null;
comment: string | null;
additionalGuests: number | null;
}[] | null;
attendeesOmitted: boolean | null;
guestsCanInviteOthers: boolean | null;
guestsCanModify: boolean | null;
guestsCanSeeOtherGuests: boolean | null;
hangoutLink: string | null;
conferenceData: object | null;
reminders: { useDefault: boolean; overrides: { method: string; minutes: number; }[] | null; } | null;
eventType: string | null;
}[];
next_page_token: string | null;
}
get_upcoming_events β Get events in the next N days
Gets events starting from now through the next N days. Returns events in start-time order. Recurring events are expanded into individual instances.
Inputs:
- `days` (int, optional, default: 7) β Number of days to look ahead from now
- `calendar_id` (string, optional, default: "primary") β Calendar ID to query. Use 'primary' for the user's main calendar
- `max_results` (int, optional, default: 10) β Maximum number of events to return (1β2500)
Output data schema: