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.
{
"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:
- Calculate tomorrow’s date range (00:00 to 23:59)
- 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"
}
}
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
The user whose availability was checked
Time blocks where the user has existing calendar events
start: ISO 8601 timestamp
end: ISO 8601 timestamp
Time blocks where the user is available
start: ISO 8601 timestamp
end: ISO 8601 timestamp
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()}`);