Skip to main content
Glama

find_free_slots

Find available meeting times in your Outlook calendar by specifying date range, duration, and work hours.

Instructions

Find available time slots in the calendar

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
startDateYesStart date (ISO 8601 format)
endDateNoEnd date (ISO 8601 format, optional, defaults to 7 days from start)
durationNoDuration in minutes (optional, defaults to 30)
workDayStartNoWork day start hour (0-23) (optional, defaults to 9)
workDayEndNoWork day end hour (0-23) (optional, defaults to 17)
calendarNoCalendar name (optional)

Implementation Reference

  • The primary handler function for the 'find_free_slots' tool. It constructs a PowerShell script to interact with Outlook via COM, retrieves busy events in the specified date range, calculates free slots of the desired duration during work hours (default 9-17), skips weekends, and returns an array of available {Start, End} slots.
    async findFreeSlots(options: { startDate: Date; endDate?: Date; duration?: number; workDayStart?: number; workDayEnd?: number; calendar?: string; }): Promise<any[]> { try { const endDate = options.endDate || new Date(options.startDate.getTime() + 7 * 24 * 60 * 60 * 1000); const duration = options.duration || 30; const workDayStart = options.workDayStart || 9; const workDayEnd = options.workDayEnd || 17; const calendarName = options.calendar || ''; const script = ` try { Add-Type -AssemblyName "Microsoft.Office.Interop.Outlook" -ErrorAction Stop $outlook = New-Object -ComObject Outlook.Application -ErrorAction Stop $namespace = $outlook.GetNamespace("MAPI") # Get calendar ${calendarName ? ` $calendar = $null foreach ($folder in $namespace.Folders) { if ($folder.Name -eq "${calendarName.replace(/"/g, '""')}") { $calendar = $folder.Folders("Calendar") break } } if (-not $calendar) { throw "Calendar not found: ${calendarName.replace(/"/g, '""')}" } ` : ` $calendar = $namespace.GetDefaultFolder(9) `} # Get all events in date range $startDate = [DateTime]"${options.startDate.toISOString()}" $endDate = [DateTime]"${endDate.toISOString()}" $filter = "[Start] >= '$($startDate.ToString('g'))' AND [End] <= '$($endDate.AddDays(1).ToString('g'))'" $items = $calendar.Items.Restrict($filter) # Build busy slots array $busySlots = @() foreach ($item in $items) { if ($item.BusyStatus -eq 2 -or $item.BusyStatus -eq 3) { # Busy or OutOfOffice $busySlots += [PSCustomObject]@{ Start = $item.Start End = $item.End } } } # Find free slots $freeSlots = @() $currentDate = $startDate.Date while ($currentDate -le $endDate.Date) { # Skip weekends $dayOfWeek = $currentDate.DayOfWeek if ($dayOfWeek -ne [DayOfWeek]::Saturday -and $dayOfWeek -ne [DayOfWeek]::Sunday) { $slotStart = $currentDate.AddHours(${workDayStart}) $workDayEndTime = $currentDate.AddHours(${workDayEnd}) while ($slotStart.AddMinutes(${duration}) -le $workDayEndTime) { $slotEnd = $slotStart.AddMinutes(${duration}) # Check if slot is free $isFree = $true foreach ($busy in $busySlots) { if ($slotStart -lt $busy.End -and $slotEnd -gt $busy.Start) { $isFree = $false break } } if ($isFree) { $freeSlots += [PSCustomObject]@{ Start = $slotStart.ToString("yyyy-MM-ddTHH:mm:ss") End = $slotEnd.ToString("yyyy-MM-ddTHH:mm:ss") } } $slotStart = $slotStart.AddMinutes(30) } } $currentDate = $currentDate.AddDays(1) } Write-Output ($freeSlots | ConvertTo-Json -Compress) } catch { Write-Output ([PSCustomObject]@{ Error = $_.Exception.Message } | ConvertTo-Json -Compress) } `; const result = await this.executePowerShell(script); const cleanResult = result.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, '').trim(); if (!cleanResult || cleanResult === '' || cleanResult === '[]') { return []; } const data = JSON.parse(cleanResult); if (data.Error) { throw new Error(data.Error); } return Array.isArray(data) ? data : [data]; } catch (error) { throw new Error(`Failed to find free slots: ${error instanceof Error ? error.message : String(error)}`); } }
  • The input schema and description for the 'find_free_slots' tool, defining parameters and validation as part of the MCP tools list.
    name: "find_free_slots", description: "Find available time slots in the calendar", inputSchema: { type: "object", properties: { startDate: { type: "string", description: "Start date (ISO 8601 format)" }, endDate: { type: "string", description: "End date (ISO 8601 format, optional, defaults to 7 days from start)" }, duration: { type: "number", description: "Duration in minutes (optional, defaults to 30)" }, workDayStart: { type: "number", description: "Work day start hour (0-23) (optional, defaults to 9)" }, workDayEnd: { type: "number", description: "Work day end hour (0-23) (optional, defaults to 17)" }, calendar: { type: "string", description: "Calendar name (optional)" } }, required: ["startDate"] }
  • src/index.ts:779-800 (registration)
    MCP server request handler case that dispatches 'find_free_slots' tool calls to the outlookManager implementation and formats the response.
    case 'find_free_slots': { const freeSlots = await outlookManager.findFreeSlots({ startDate: new Date((args as any)?.startDate), endDate: (args as any)?.endDate ? new Date((args as any)?.endDate) : undefined, duration: (args as any)?.duration, workDayStart: (args as any)?.workDayStart, workDayEnd: (args as any)?.workDayEnd, calendar: (args as any)?.calendar }); return { content: [ { type: 'text', text: `🆓 **Free Time Slots**\nTotal: ${freeSlots.length} slots found\n\n` + freeSlots.slice(0, 20).map((slot, index) => `${index + 1}. ${slot.Start} - ${slot.End}` ).join('\n') + (freeSlots.length > 20 ? `\n\n... and ${freeSlots.length - 20} more slots` : '') }, ], }; }

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/cqyefeng119/windows-outlook-mcp'

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