eventkit-rs
A Rust library and CLI for interacting with macOS Calendar events and Reminders via Apple's EventKit framework. Includes a built-in Model Context Protocol (MCP) server for AI assistant integration.
Features
- Calendar Events — full CRUD with alarms, recurrence (incl.
monthsOfTheYear/setPositions), attendees, location chip, URL, structured location, availability (Busy/Free/Tentative/Unavailable), calendar move, andEKSpanchoice (thisvsfuture) for recurring edits/deletes. - Reminders — full CRUD with priority, alarms (time + geofence), recurrence (including
monthsOfTheYear/setPositionsetc.), due/start dates, due-date IANA timezone, and explicit completion-date setting. - MCP Server — built-in MCP server (
--mcp) with structured JSON output, typed input/output schemas, and 32 tools. - Calendar Management — create, update (name + color), and delete both reminder lists and event calendars.
- Batch Operations — batch delete, move, and update across reminders and events.
- Authorization — programmatic consent prompts for Reminders, Calendar, and Location; status diagnostics with remediation hints.
- Location — get current location via CoreLocation; auto-prompt for location auth when a geofence is attached.
- In-Process Transport — embed as a library with
serve_on()forDuplexStream-based in-process MCP. - CLI + Dump + Reflection — command-line tool with curated JSON dumps and runtime ObjC reflection dumps (
dump reminder-raw,dump reminder-private) for debugging.
iCloud caveats (verified empirically — see project notes). On iCloud-synced reminder lists, the iCloud daemon silently drops some
EKReminderwrites even when the framework call succeeds: the plain-textlocation,EKReminder.structuredLocation,EKAlarm.url/soundName/emailAddress. These setters exist in the lib (parity with EventKit) for non-iCloud sources, but the MCP/CLI surface for reminders is intentionally pruned of those fields. Calendar events are unaffected — their URL/location/etc. work end-to-end. For "remind me at a place" on iCloud, use a geofence (location-based alarm) — that's the iCloud-honored path.
Requirements
- macOS 14+ (Sonoma)
- Rust 1.94+
Installation
As a CLI Tool
As a Library
[]
= "0.5"
Without MCP dependencies:
[]
= { = "0.5", = false, = ["events", "reminders"] }
Quick Start
Library Usage
use ;
use ;
In-Process MCP (no separate binary)
use duplex;
let = duplex;
spawn;
// Connect your MCP client to client_stream...
CLI Usage
# MCP server (stdio transport)
# Authorization
# Reminders — basics
# Reminders — date-range queries (uses EventKit's native predicates)
# Reminders — posture setters
# Calendar Events (URL + location are first-class on events)
# Calendar Events — update + recurring-event span semantics
# Dump objects as JSON or raw ObjC reflection (debugging)
MCP Server
All tools return structured JSON with typed output schemas. Responses use structured_content (MCP spec 2025-06-18) with text fallback for older clients.
Tools (32)
| Tool | Description |
|---|---|
| Authorization | |
auth_status |
Check Reminders + Calendar permission status without prompting; returns remediation hints. |
request_access |
Trigger the OS consent dialog for entity: "reminder" | "event". |
| Reminder Lists | |
list_reminder_lists |
List all reminder lists with color, source, permissions. |
create_reminder_list |
Create a new reminder list. |
update_reminder_list |
Update name and/or color (red, blue, green, purple, etc.). |
delete_reminder_list |
Delete a list and all its reminders. |
| Reminders | |
list_reminders |
List reminders. Filters: show_completed, list_name, due_after/due_before (incomplete), completed_after/completed_before (completed). |
create_reminder |
Create with inline alarms, recurrence, due/start dates, due-date IANA timezone, geofence. |
update_reminder |
Update any of the above plus completion_date (authoritative completion toggle). |
get_reminder |
Get full detail (alarms, recurrence rules inline). |
delete_reminder |
Delete a reminder. |
complete_reminder |
Mark as completed. |
uncomplete_reminder |
Mark as not completed. |
set_reminder_due_timezone |
Set or clear the IANA timezone applied to the due date. |
set_reminder_geofence |
Attach (or clear) a location-based alarm — "remind me when I arrive/leave". Auto-prompts for Location permission. |
| Event Calendars | |
list_calendars |
List all event calendars with color, source, permissions. |
get_default_event_calendar |
Return the calendar create_event will use when calendar_name is omitted. |
create_event_calendar |
Create a new calendar. |
update_event_calendar |
Update name and/or color. |
delete_event_calendar |
Delete a calendar and all its events. |
| Events | |
list_events |
List events by date range, filter by calendar ID. |
create_event |
Create with inline alarms, recurrence, URL, location, availability, structured_location. |
update_event |
Update title, notes (clearable), location (clearable), start/end, all_day, calendar move (calendar_name), URL (clearable), availability, structured_location, alarms, recurrence. span: "this" | "future" controls recurring-event edit scope. |
get_event |
Get full detail (alarms, recurrence, attendees, organizer, creation_date, last_modified_date, external_identifier, timezone, attachments_count). |
delete_event |
Delete one event or a recurring series. span: "this" | "future" (legacy affect_future: bool still accepted as alias). |
set_event_availability |
Set an event's availability to "busy" | "free" | "tentative" | "unavailable". Always per-instance. |
| Search & Location | |
search |
Search reminders and/or events by text (item_type optional). |
get_current_location |
Get lat/long via CoreLocation. |
list_sources |
List accounts (iCloud, Local, Exchange). |
| Batch | |
batch_delete |
Delete multiple reminders or events at once. |
batch_move |
Move multiple reminders between lists. |
batch_update |
Update multiple items at once. |
Prompts (4)
| Prompt | Description |
|---|---|
incomplete_reminders |
List all incomplete reminders (optionally by list). |
reminder_lists |
List all available reminder lists. |
move_reminder |
Move a reminder to a different list. |
create_detailed_reminder |
Create a reminder with notes, priority, and due date. |
Configuration
Add to your MCP client config (e.g. Claude Desktop):
Privacy Permissions
Embedded automatically when you use the CLI (see Info.plist in this repo). When linking as a library into your own app, add to your Info.plist:
NSRemindersFullAccessUsageDescription
This app needs access to your reminders.
NSCalendarsFullAccessUsageDescription
This app needs access to your calendar.
NSLocationWhenInUseUsageDescription
This app needs your location for location-based reminders.
<!-- Required for geofenced reminder triggers to fire when the app isn't foreground -->
NSLocationAlwaysAndWhenInUseUsageDescription
This app needs background location access so location-based reminders trigger when you arrive at or leave a place.
Feature Flags
| Feature | Default | Description |
|---|---|---|
events |
Yes | Calendar event support |
reminders |
Yes | Reminders support |
location |
Yes | CoreLocation for geofenced reminders |
mcp |
Yes | MCP server, structured JSON output, dump commands |
Development
# Run all checks (format + clippy + build + nextest) — same as CI
# Auto-fix formatting + clippy, then check
# Run tests directly (parallel via nextest; live-eventkit tests run serial)
# Run only the live-EventKit integration tests (touches real authorization)
# Build universal binary (arm64 + x86_64)
License
Apache 2.0 — see LICENSE.