Skip to main content
Glama
index.ts8.08 kB
#!/usr/bin/env node import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import * as calendars from "./calendars.js"; // Create a simple MCP server for Apple Calendars const server = new McpServer({ name: "apple-calendars", version: "1.0.0" }); // Tool to get all calendars server.tool( "getCalendars", {}, async () => { try { const calendarList = await calendars.getCalendars(); return { content: [{ type: "text", text: JSON.stringify({ calendars: calendarList }) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to get calendars" }) }], isError: true }; } } ); // Tool to get events from a specific calendar server.tool( "getCalendarEvents", { calendarId: z.string() }, async ({ calendarId }) => { try { const events = await calendars.getCalendarEvents(calendarId); return { content: [{ type: "text", text: JSON.stringify({ events }) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: `Failed to get events from calendar: ${calendarId}` }) }], isError: true }; } } ); // Tool to create a new calendar server.tool( "createCalendar", { title: z.string(), color: z.string().optional() }, async ({ title, color }) => { try { const result = await calendars.createCalendar(title, color); return { content: [{ type: "text", text: JSON.stringify({ success: true, message: "Calendar created", calendar: result }) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to create calendar" }) }], isError: true }; } } ); // Tool to create a new event in a calendar server.tool( "createCalendarEvent", { calendarId: z.string(), title: z.string(), startDate: z.string(), endDate: z.string(), location: z.string().optional(), notes: z.string().optional() }, async ({ calendarId, title, startDate, endDate, location, notes }) => { try { try { const result = await calendars.createCalendarEvent( calendarId, title, startDate, endDate, location, notes ); return { content: [{ type: "text", text: JSON.stringify({ success: true, message: "Event created", event: result }) }] }; } catch (error: any) { // Check if it's a date format error if (error.message && (error.message.includes('date') || (error.response?.data?.reason && error.response.data.reason.includes('ISO8601')))) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to create event due to date format issues", message: "The Calendar API requires a specific ISO8601 format that we couldn't determine. The Swift API is expecting a specific format that we haven't been able to match.", details: "This is a known issue with the Calendar API Bridge. Please check the API documentation for the correct date format.", workaround: "You can try creating events directly through the macOS Calendar app instead." }) }], isError: true }; } // If it's not a date format error, rethrow throw error; } } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to create event" }) }], isError: true }; } } ); // Tool to update an existing event server.tool( "updateCalendarEvent", { calendarId: z.string(), eventId: z.string(), title: z.string().optional(), startDate: z.string().optional(), endDate: z.string().optional(), location: z.string().optional(), notes: z.string().optional() }, async ({ calendarId, eventId, title, startDate, endDate, location, notes }) => { try { try { const updates = { title, startDate, endDate, location, notes }; // Filter out undefined values Object.keys(updates).forEach(key => { if (updates[key as keyof typeof updates] === undefined) { delete updates[key as keyof typeof updates]; } }); const result = await calendars.updateCalendarEvent(calendarId, eventId, updates); return { content: [{ type: "text", text: JSON.stringify({ success: true, message: "Event updated", event: result }) }] }; } catch (error: any) { // Check if it's a date format error if (error.message && error.message.includes('date')) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to update event due to date format issues", message: "The Calendar API requires a specific date format that we couldn't determine. Please try using a different date format or contact the API provider for the correct format.", details: error.message }) }], isError: true }; } // If it's not a date format error, rethrow throw error; } } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to update event" }) }], isError: true }; } } ); // Tool to delete an event server.tool( "deleteCalendarEvent", { calendarId: z.string(), eventId: z.string() }, async ({ calendarId, eventId }) => { try { const success = await calendars.deleteCalendarEvent(calendarId, eventId); return { content: [{ type: "text", text: JSON.stringify({ success, message: success ? "Event deleted" : "Failed to delete event" }) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to delete event" }) }], isError: true }; } } ); // Tool to delete a calendar server.tool( "deleteCalendar", { calendarId: z.string() }, async ({ calendarId }) => { try { const success = await calendars.deleteCalendar(calendarId); return { content: [{ type: "text", text: JSON.stringify({ success, message: success ? "Calendar deleted" : "Failed to delete calendar" }) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: "Failed to delete calendar" }) }], isError: true }; } } ); // Start the server export async function runServer() { try { const transport = new StdioServerTransport(); await server.connect(transport); console.error("MCP Apple Calendars server started"); } catch (error) { console.error("Failed to start MCP server:", error); process.exit(1); } } // Auto-start the server if this file is executed directly if (import.meta.url === `file://${process.argv[1]}`) { runServer(); }

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

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