Skip to main content
Glama

calendar

Manage Apple Calendar events by searching, creating, listing, or opening them directly through the MCP server. Streamline scheduling with customizable search ranges, event details, and calendar assignments.

Instructions

Search, create, and open calendar events in Apple Calendar app

Input Schema

NameRequiredDescriptionDefault
calendarNameNoName of the calendar to create the event in (optional for create operation, uses default calendar if not specified)
endDateNoEnd date/time of the event in ISO format (required for create operation)
eventIdNoID of the event to open (required for open operation)
fromDateNoStart date for search range in ISO format (optional, default is today)
isAllDayNoWhether the event is an all-day event (optional for create operation, default is false)
limitNoNumber of events to retrieve (optional, default 10)
locationNoLocation of the event (optional for create operation)
notesNoAdditional notes for the event (optional for create operation)
operationYesOperation to perform: 'search', 'open', 'list', or 'create'
searchTextNoText to search for in event titles, locations, and notes (required for search operation)
startDateNoStart date/time of the event in ISO format (required for create operation)
titleNoTitle of the event to create (required for create operation)
toDateNoEnd date for search range in ISO format (optional, default is 30 days from now for search, 7 days for list)

Input Schema (JSON Schema)

{ "properties": { "calendarName": { "description": "Name of the calendar to create the event in (optional for create operation, uses default calendar if not specified)", "type": "string" }, "endDate": { "description": "End date/time of the event in ISO format (required for create operation)", "type": "string" }, "eventId": { "description": "ID of the event to open (required for open operation)", "type": "string" }, "fromDate": { "description": "Start date for search range in ISO format (optional, default is today)", "type": "string" }, "isAllDay": { "description": "Whether the event is an all-day event (optional for create operation, default is false)", "type": "boolean" }, "limit": { "description": "Number of events to retrieve (optional, default 10)", "type": "number" }, "location": { "description": "Location of the event (optional for create operation)", "type": "string" }, "notes": { "description": "Additional notes for the event (optional for create operation)", "type": "string" }, "operation": { "description": "Operation to perform: 'search', 'open', 'list', or 'create'", "enum": [ "search", "open", "list", "create" ], "type": "string" }, "searchText": { "description": "Text to search for in event titles, locations, and notes (required for search operation)", "type": "string" }, "startDate": { "description": "Start date/time of the event in ISO format (required for create operation)", "type": "string" }, "title": { "description": "Title of the event to create (required for create operation)", "type": "string" }, "toDate": { "description": "End date for search range in ISO format (optional, default is 30 days from now for search, 7 days for list)", "type": "string" } }, "required": [ "operation" ], "type": "object" }

Implementation Reference

  • tools.ts:181-243 (registration)
    MCP tool registration for 'calendar' tool, defining name, description, and detailed input schema for various operations.
    const CALENDAR_TOOL: Tool = { name: "calendar", description: "Search, create, and open calendar events in Apple Calendar app", inputSchema: { type: "object", properties: { operation: { type: "string", description: "Operation to perform: 'search', 'open', 'list', or 'create'", enum: ["search", "open", "list", "create"] }, searchText: { type: "string", description: "Text to search for in event titles, locations, and notes (required for search operation)" }, eventId: { type: "string", description: "ID of the event to open (required for open operation)" }, limit: { type: "number", description: "Number of events to retrieve (optional, default 10)" }, fromDate: { type: "string", description: "Start date for search range in ISO format (optional, default is today)" }, toDate: { type: "string", description: "End date for search range in ISO format (optional, default is 30 days from now for search, 7 days for list)" }, title: { type: "string", description: "Title of the event to create (required for create operation)" }, startDate: { type: "string", description: "Start date/time of the event in ISO format (required for create operation)" }, endDate: { type: "string", description: "End date/time of the event in ISO format (required for create operation)" }, location: { type: "string", description: "Location of the event (optional for create operation)" }, notes: { type: "string", description: "Additional notes for the event (optional for create operation)" }, isAllDay: { type: "boolean", description: "Whether the event is an all-day event (optional for create operation, default is false)" }, calendarName: { type: "string", description: "Name of the calendar to create the event in (optional for create operation, uses default calendar if not specified)" } }, required: ["operation"] } };
  • Primary handler for 'calendar' tool invocations within the MCP CallToolRequestSchema. Validates arguments, loads the calendar module lazily, and routes to specific operations (search, list, open, create) based on input.
    case "calendar": { if (!isCalendarArgs(args)) { throw new Error("Invalid arguments for calendar tool"); } try { const calendarModule = await loadModule("calendar"); const { operation } = args; switch (operation) { case "search": { const { searchText, limit, fromDate, toDate } = args; const events = await calendarModule.searchEvents( searchText!, limit, fromDate, toDate, ); return { content: [ { type: "text", text: events.length > 0 ? `Found ${events.length} events matching "${searchText}":\n\n${events .map( (event) => `${event.title} (${new Date(event.startDate!).toLocaleString()} - ${new Date(event.endDate!).toLocaleString()})\n` + `Location: ${event.location || "Not specified"}\n` + `Calendar: ${event.calendarName}\n` + `ID: ${event.id}\n` + `${event.notes ? `Notes: ${event.notes}\n` : ""}`, ) .join("\n\n")}` : `No events found matching "${searchText}".`, }, ], isError: false, }; } case "open": { const { eventId } = args; const result = await calendarModule.openEvent(eventId!); return { content: [ { type: "text", text: result.success ? result.message : `Error opening event: ${result.message}`, }, ], isError: !result.success, }; } case "list": { const { limit, fromDate, toDate } = args; const events = await calendarModule.getEvents( limit, fromDate, toDate, ); const startDateText = fromDate ? new Date(fromDate).toLocaleDateString() : "today"; const endDateText = toDate ? new Date(toDate).toLocaleDateString() : "next 7 days"; return { content: [ { type: "text", text: events.length > 0 ? `Found ${events.length} events from ${startDateText} to ${endDateText}:\n\n${events .map( (event) => `${event.title} (${new Date(event.startDate!).toLocaleString()} - ${new Date(event.endDate!).toLocaleString()})\n` + `Location: ${event.location || "Not specified"}\n` + `Calendar: ${event.calendarName}\n` + `ID: ${event.id}`, ) .join("\n\n")}` : `No events found from ${startDateText} to ${endDateText}.`, }, ], isError: false, }; } case "create": { const { title, startDate, endDate, location, notes, isAllDay, calendarName, } = args; const result = await calendarModule.createEvent( title!, startDate!, endDate!, location, notes, isAllDay, calendarName, ); return { content: [ { type: "text", text: result.success ? `${result.message} Event scheduled from ${new Date(startDate!).toLocaleString()} to ${new Date(endDate!).toLocaleString()}${result.eventId ? `\nEvent ID: ${result.eventId}` : ""}` : `Error creating event: ${result.message}`, }, ], isError: !result.success, }; } default: throw new Error(`Unknown calendar operation: ${operation}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: errorMessage.includes("access") ? errorMessage : `Error in calendar tool: ${errorMessage}`, }, ], isError: true, }; } }
  • Runtime TypeGuard function for validating calendar tool arguments, ensuring correct operation and required parameters are provided.
    function isCalendarArgs(args: unknown): args is { operation: "search" | "open" | "list" | "create"; searchText?: string; eventId?: string; limit?: number; fromDate?: string; toDate?: string; title?: string; startDate?: string; endDate?: string; location?: string; notes?: string; isAllDay?: boolean; calendarName?: string; } { if (typeof args !== "object" || args === null) { return false; } const { operation } = args as { operation?: unknown }; if (typeof operation !== "string") { return false; } if (!["search", "open", "list", "create"].includes(operation)) { return false; } // Check that required parameters are present for each operation if (operation === "search") { const { searchText } = args as { searchText?: unknown }; if (typeof searchText !== "string") { return false; } } if (operation === "open") { const { eventId } = args as { eventId?: unknown }; if (typeof eventId !== "string") { return false; } } if (operation === "create") { const { title, startDate, endDate } = args as { title?: unknown; startDate?: unknown; endDate?: unknown; }; if ( typeof title !== "string" || typeof startDate !== "string" || typeof endDate !== "string" ) { return false; } } return true; }
  • Core calendar module exporting helper functions: searchEvents, getEvents (list), openEvent, createEvent, and access checker. These implement the AppleScript interactions for Calendar.app.
    const calendar = { searchEvents, openEvent, getEvents, createEvent, requestCalendarAccess }; export default calendar;

Other Tools

Related Tools

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/supermemoryai/apple-mcp'

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