Skip to main content

Overview

The check_availability tool checks when a single person is free or busy. Useful for:
  • Viewing someone’s schedule before proposing times
  • Finding gaps in a busy calendar
  • Understanding availability patterns
For finding mutual availability between 2 people, use find_mutual_availability instead.

Tool Schema

{
  "name": "check_availability",
  "description": "Check a single user's calendar to see when they're free or busy. Returns busy blocks and free time windows.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "email": {
        "type": "string",
        "format": "email",
        "description": "Email address of the user to check"
      },
      "date_range": {
        "type": "object",
        "description": "Date range to check availability within",
        "properties": {
          "start": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 start date-time (e.g., '2025-01-20T00:00:00Z')"
          },
          "end": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 end date-time (e.g., '2025-01-27T00:00:00Z')"
          }
        },
        "required": ["start", "end"]
      }
    },
    "required": ["email", "date_range"]
  }
}

Usage in Claude Desktop

User: “What does alice@example.com’s schedule look like tomorrow?” Claude will:
  1. Calculate tomorrow’s date range (00:00 to 23:59)
  2. Call check_availability:
{
  "email": "alice@example.com",
  "date_range": {
    "start": "2025-01-21T00:00:00-08:00",
    "end": "2025-01-21T23:59:59-08:00"
  }
}

Response Format

Success Response

{
  "email": "alice@example.com",
  "busy_slots": [
    {
      "start": "2025-01-21T09:00:00Z",
      "end": "2025-01-21T10:00:00Z"
    },
    {
      "start": "2025-01-21T14:00:00Z",
      "end": "2025-01-21T15:30:00Z"
    },
    {
      "start": "2025-01-21T16:00:00Z",
      "end": "2025-01-21T17:00:00Z"
    }
  ],
  "free_slots": [
    {
      "start": "2025-01-21T08:00:00Z",
      "end": "2025-01-21T09:00:00Z"
    },
    {
      "start": "2025-01-21T10:00:00Z",
      "end": "2025-01-21T14:00:00Z"
    },
    {
      "start": "2025-01-21T15:30:00Z",
      "end": "2025-01-21T16:00:00Z"
    }
  ],
  "preferences": {
    "work_hours": {
      "monday": { "enabled": true, "start": "09:00", "end": "17:00" },
      "tuesday": { "enabled": true, "start": "09:00", "end": "17:00" }
    },
    "timezone": "America/Los_Angeles",
    "buffer_minutes": 15,
    "energy_pattern": "morning_person"
  }
}

Response Fields

email
string
The user whose availability was checked
busy_slots
array
Time blocks where the user has existing calendar events
  • start: ISO 8601 timestamp
  • end: ISO 8601 timestamp
free_slots
array
Time blocks where the user is available
  • start: ISO 8601 timestamp
  • end: ISO 8601 timestamp
preferences
object
User’s scheduling preferences including work hours, timezone, and energy patterns

Example Workflows

Workflow 1: Check Before Proposing

// User: "I want to meet with bob@example.com sometime this week"

// Step 1: Check Bob's availability
const bobSchedule = await mcpClient.callTool('check_availability', {
  email: 'bob@example.com',
  date_range: {
    start: '2025-01-20T00:00:00Z',
    end: '2025-01-27T00:00:00Z'
  }
});

// Step 2: Analyze free slots
console.log(`Bob has ${bobSchedule.free_slots.length} free time blocks`);

// Step 3: Find slots longer than 30 minutes
const viableSlots = bobSchedule.free_slots.filter(slot => {
  const duration = new Date(slot.end) - new Date(slot.start);
  return duration >= 30 * 60 * 1000; // 30 minutes in ms
});

console.log(`${viableSlots.length} slots work for a 30-minute meeting`);

// Step 4: Now check mutual availability
const mutualAvailability = await mcpClient.callTool('find_mutual_availability', {
  attendees: ['alice@example.com', 'bob@example.com'],
  duration_minutes: 30
});

Workflow 2: Understanding Busy Patterns

// Analyze someone's meeting load
const schedule = await mcpClient.callTool('check_availability', {
  email: 'alice@example.com',
  date_range: {
    start: '2025-01-20T00:00:00Z',
    end: '2025-01-27T00:00:00Z'
  }
});

// Calculate total meeting hours
const totalBusyMinutes = schedule.busy_slots.reduce((sum, slot) => {
  const duration = (new Date(slot.end) - new Date(slot.start)) / (1000 * 60);
  return sum + duration;
}, 0);

console.log(`Alice has ${totalBusyMinutes / 60} hours of meetings this week`);

// Find longest free block
const longestFree = schedule.free_slots.reduce((max, slot) => {
  const duration = (new Date(slot.end) - new Date(slot.start)) / (1000 * 60);
  return duration > max ? duration : max;
}, 0);

console.log(`Longest continuous free time: ${longestFree} minutes`);

Workflow 3: Respect Work Hours

const schedule = await mcpClient.callTool('check_availability', {
  email: 'bob@example.com',
  date_range: {
    start: '2025-01-21T00:00:00Z',
    end: '2025-01-21T23:59:59Z'
  }
});

// Filter free slots to only work hours
const workHours = schedule.preferences.work_hours.tuesday; // Tuesday
const workStart = new Date(`2025-01-21T${workHours.start}:00`);
const workEnd = new Date(`2025-01-21T${workHours.end}:00`);

const workHourFreeSlots = schedule.free_slots.filter(slot => {
  const slotStart = new Date(slot.start);
  const slotEnd = new Date(slot.end);
  return slotStart >= workStart && slotEnd <= workEnd;
});

console.log(`${workHourFreeSlots.length} free slots during work hours`);

Use Cases

1. Executive Assistant Workflow

// "When can the CEO meet this week?"
const ceoSchedule = await mcpClient.callTool('check_availability', {
  email: 'ceo@company.com',
  date_range: {
    start: '2025-01-20T00:00:00Z',
    end: '2025-01-27T00:00:00Z'
  }
});

// Find gaps of at least 1 hour
const hourLongSlots = ceoSchedule.free_slots.filter(slot => {
  const minutes = (new Date(slot.end) - new Date(slot.start)) / (60000);
  return minutes >= 60;
});

// Present options
hourLongSlots.forEach(slot => {
  console.log(`Available: ${new Date(slot.start).toLocaleString()}`);
});

2. Smart Scheduling Assistant

// "Find a good time to talk with bob@example.com"

// First, understand Bob's patterns
const bobWeek = await mcpClient.callTool('check_availability', {
  email: 'bob@example.com',
  date_range: {
    start: '2025-01-20T00:00:00Z',
    end: '2025-01-27T00:00:00Z'
  }
});

// Respect energy patterns
if (bobWeek.preferences.energy_pattern === 'morning_person') {
  console.log("Bob prefers mornings - let's prioritize AM slots");
}

// Now find mutual availability with this context
const options = await mcpClient.callTool('find_mutual_availability', {
  attendees: ['alice@example.com', 'bob@example.com'],
  duration_minutes: 30
});

// Boost morning slots for morning people
const boosted = options.slots.map(slot => {
  if (slot.time_of_day === 'morning' && bobWeek.preferences.energy_pattern === 'morning_person') {
    return { ...slot, ai_recommendation: 'Optimal - matches energy pattern' };
  }
  return slot;
});

3. Meeting Conflict Detection

// Before scheduling, check if time is actually free
const proposedTime = '2025-01-21T14:00:00Z';

const schedule = await mcpClient.callTool('check_availability', {
  email: 'alice@example.com',
  date_range: {
    start: '2025-01-21T00:00:00Z',
    end: '2025-01-21T23:59:59Z'
  }
});

// Check if proposed time conflicts
const hasConflict = schedule.busy_slots.some(slot => {
  const slotStart = new Date(slot.start);
  const slotEnd = new Date(slot.end);
  const proposed = new Date(proposedTime);
  return proposed >= slotStart && proposed < slotEnd;
});

if (hasConflict) {
  console.log('Conflict detected! Proposing alternative times...');
  // Show free_slots instead
}

Privacy & Permissions

What You Can See

  • Free/Busy blocks: When the user is occupied vs available
  • Preferences: Work hours, timezone, buffer settings
  • Energy patterns: Morning/afternoon/evening preferences

What You CANNOT See

  • Event titles or descriptions
  • Meeting attendees
  • Event locations
  • Private event details
This respects user privacy while providing enough context for intelligent scheduling.

Error Handling

User Not Found

{
  "error": "user not found",
  "code": "USER_NOT_FOUND"
}
Solution: User needs to connect their calendar to Syncline.

Invalid Date Range

{
  "error": "invalid start time",
  "code": "INVALID_DATE_FORMAT"
}
Solution: Use ISO 8601 format for dates.

Unauthorized Access

{
  "error": "not authorized to access this user's calendar",
  "code": "UNAUTHORIZED"
}
Solution: User must be connected to your platform.

Best Practices

1. Request Reasonable Date Ranges

// Good: Check next 7 days
date_range: {
  start: '2025-01-20T00:00:00Z',
  end: '2025-01-27T00:00:00Z'
}

// Bad: Checking 6 months (slow, unnecessary)
date_range: {
  start: '2025-01-20T00:00:00Z',
  end: '2025-07-20T00:00:00Z'
}

2. Respect User Preferences

const schedule = await mcpClient.callTool('check_availability', {
  email: 'alice@example.com',
  date_range: { start: '...', end: '...' }
});

// Don't propose times outside work hours
const prefs = schedule.preferences.work_hours;
console.log(`Alice works ${prefs.monday.start} to ${prefs.monday.end}`);

3. Consider Buffer Time

// User has buffer_minutes: 15
// Don't schedule back-to-back meetings

const lastMeetingEnd = schedule.busy_slots[schedule.busy_slots.length - 1].end;
const bufferMinutes = schedule.preferences.buffer_minutes;
const earliestNext = new Date(lastMeetingEnd);
earliestNext.setMinutes(earliestNext.getMinutes() + bufferMinutes);

console.log(`Next meeting earliest start: ${earliestNext.toISOString()}`);