google_calendar_find_free_time
Identify open time slots in Google Calendar between events for a specified period and duration. Input start and end dates, desired duration, and optional calendar IDs to find available time.
Instructions
Find available time slots between events
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| calendarIds | No | Optional: Calendar IDs to check (defaults to primary if not specified) | |
| duration | Yes | Minimum slot duration in minutes | |
| endDate | Yes | End of search period (ISO format) | |
| startDate | Yes | Start of search period (ISO format) |
Implementation Reference
- handlers/calendar.ts:185-204 (handler)The main handler function for the 'google_calendar_find_free_time' tool. Validates arguments and delegates to GoogleCalendar.findFreeTime method.export async function handleCalendarFindFreeTime( args: any, googleCalendarInstance: GoogleCalendar ) { if (!isFindFreeTimeArgs(args)) { throw new Error("Invalid arguments for google_calendar_find_free_time"); } const { startDate, endDate, duration, calendarIds } = args; const result = await googleCalendarInstance.findFreeTime( startDate, endDate, duration, calendarIds ); return { content: [{ type: "text", text: result }], isError: false, }; }
- utils/calendar.ts:250-349 (helper)Core logic implementation in GoogleCalendar class that fetches events from Google Calendar API and computes free time slots of specified duration.async findFreeTime( startDate: string, endDate: string, durationMinutes: number, calendarIds?: string[] ) { try { // If no calendar IDs specified, use the default one const targetCalendarIds = calendarIds || [this.defaultCalendarId]; // Get all events in the date range for each calendar const allEvents: any[] = []; for (const calId of targetCalendarIds) { const params: any = { calendarId: calId, timeMin: startDate, timeMax: endDate, singleEvents: true, orderBy: "startTime", }; const res = await this.calendar.events.list(params); allEvents.push(...(res.data.items || [])); } // Sort events by start time allEvents.sort((a, b) => { const aStart = new Date(a.start.dateTime || a.start.date).getTime(); const bStart = new Date(b.start.dateTime || b.start.date).getTime(); return aStart - bStart; }); // Convert duration from minutes to milliseconds const durationMs = durationMinutes * 60 * 1000; // Start from the search period start date let currentTime = new Date(startDate).getTime(); const endTime = new Date(endDate).getTime(); // Store free time slots const freeSlots = []; // Process all events to find gaps between them for (const event of allEvents) { const eventStart = new Date( event.start.dateTime || event.start.date ).getTime(); // Check if there's enough free time before this event starts if (eventStart - currentTime >= durationMs) { // We found a free slot const slotStart = new Date(currentTime).toISOString(); const slotEnd = new Date(eventStart).toISOString(); freeSlots.push({ start: slotStart, end: slotEnd }); } // Move current time to the end of this event const eventEnd = new Date( event.end.dateTime || event.end.date ).getTime(); currentTime = Math.max(currentTime, eventEnd); } // Check if there's free time after the last event if (endTime - currentTime >= durationMs) { const slotStart = new Date(currentTime).toISOString(); const slotEnd = new Date(endTime).toISOString(); freeSlots.push({ start: slotStart, end: slotEnd }); } // Format results if (freeSlots.length === 0) { return "No free time slots found that meet the criteria."; } return ( "Available time slots:\n" + freeSlots .map( (slot) => `${new Date(slot.start).toLocaleString()} - ${new Date( slot.end ).toLocaleString()} ` + `(${Math.round( (new Date(slot.end).getTime() - new Date(slot.start).getTime()) / (60 * 1000) )} minutes)` ) .join("\n") ); } catch (error) { throw new Error( `Failed to find free time: ${ error instanceof Error ? error.message : String(error) }` ); } }
- tools/calendar/index.ts:208-235 (schema)Tool schema definition with input validation schema for 'google_calendar_find_free_time'.export const FIND_FREE_TIME_TOOL: Tool = { name: "google_calendar_find_free_time", description: "Find available time slots between events", inputSchema: { type: "object", properties: { startDate: { type: "string", description: "Start of search period (ISO format)", }, endDate: { type: "string", description: "End of search period (ISO format)", }, duration: { type: "number", description: "Minimum slot duration in minutes", }, calendarIds: { type: "array", items: { type: "string" }, description: "Optional: Calendar IDs to check (defaults to primary if not specified)", }, }, required: ["startDate", "endDate", "duration"], }, };
- server-setup.ts:127-131 (registration)Registration in the main server tool dispatch switch statement, routing calls to the handler.case "google_calendar_find_free_time": return await calendarHandlers.handleCalendarFindFreeTime( args, googleCalendarInstance );
- utils/helper.ts:106-119 (helper)Type guard function for validating arguments to the 'google_calendar_find_free_time' tool.export function isFindFreeTimeArgs(args: any): args is { startDate: string; endDate: string; duration: number; calendarIds?: string[]; } { return ( args && typeof args.startDate === "string" && typeof args.endDate === "string" && typeof args.duration === "number" && (args.calendarIds === undefined || Array.isArray(args.calendarIds)) ); }