English | 简体中文 A Model Context Protocol (MCP) server that provides native integration with Apple Reminders and Calendar on macOS. This server allows you to interact with Apple Reminders and Calendar Events through a standardized interface with comprehensive management capabilities. - List Management: View all reminders and reminder lists with advanced filtering options - Reminder Operations: Full
Add this skill
npx mdskills install FradSer/mcp-server-apple-remindersComprehensive macOS Reminders/Calendar integration with advanced features and clean architecture
1# Apple Events MCP Server  23[](https://x.com/FradSer)45English | [简体中文](README.zh-CN.md)67A Model Context Protocol (MCP) server that provides native integration with Apple Reminders and Calendar on macOS. This server allows you to interact with Apple Reminders and Calendar Events through a standardized interface with comprehensive management capabilities.89## Features1011### Core Functionality1213- **List Management**: View all reminders and reminder lists with advanced filtering options14- **Reminder Operations**: Full CRUD operations (Create, Read, Update, Delete) for reminders across lists15- **Rich Content Support**: Complete support for titles, notes, due dates, URLs, and completion status16- **Native macOS Integration**: Direct integration with Apple Reminders using EventKit framework1718### Enhanced Reminder Features (v1.3.0)1920- **Priority Support**: Set reminder priority (high/medium/low/none) with visual indicators21- **Recurring Reminders**: Create repeating reminders with flexible recurrence rules (daily, weekly, monthly, yearly)22- **Location-Based Triggers**: Set geofence reminders that trigger when arriving at or leaving a location23- **Tags/Labels**: Organize reminders with custom tags for cross-list categorization and filtering24- **Subtasks/Checklists**: Add checklist items to reminders with progress tracking2526### Advanced Features2728- **Smart Organization**: Automatic categorization and intelligent filtering by priority, due date, category, or completion status29- **Powerful Search**: Multi-criteria filtering including completion status, due date ranges, tags, and full-text search30- **Batch Operations**: Efficient handling of multiple reminders with optimized data access patterns31- **Permission Management**: Automatic validation and request for required macOS system permissions32- **Flexible Date Handling**: Support for multiple date formats (YYYY-MM-DD, ISO 8601) with timezone awareness33- **Unicode Support**: Full international character support with comprehensive input validation3435### Technical Excellence3637- **Clean Architecture**: 4-layer architecture following Clean Architecture principles with dependency injection38- **Type Safety**: Complete TypeScript coverage with Zod schema validation for runtime type checking39- **High Performance**: Swift-compiled binaries for performance-critical Apple Reminders operations40- **Robust Error Handling**: Consistent error responses with detailed diagnostic information41- **Repository Pattern**: Data access abstraction with standardized CRUD operations42- **Functional Programming**: Pure functions with immutable data structures where appropriate4344## Prerequisites4546- **Node.js 18 or later**47- **macOS** (required for Apple Reminders integration)48- **Xcode Command Line Tools** (required for compiling Swift code)49- **pnpm** (recommended for package management)5051## macOS Permission Requirements (Sonoma 14+ / Sequoia 15)5253Apple now separates Reminders and Calendar permissions into _write-only_ and _full-access_ scopes. The Swift bridge declares the following privacy keys so Claude can both read and write data when you approve access:5455- `NSRemindersUsageDescription`56- `NSRemindersFullAccessUsageDescription`57- `NSRemindersWriteOnlyAccessUsageDescription`58- `NSCalendarsUsageDescription`59- `NSCalendarsFullAccessUsageDescription`60- `NSCalendarsWriteOnlyAccessUsageDescription`6162When the CLI detects a `notDetermined` authorization status it calls `requestFullAccessToReminders` / `requestFullAccessToEvents`, which in turn triggers macOS to show the correct prompt. If the OS ever loses track of permissions, rerun `./check-permissions.sh` to re-open the dialogs.6364If a Claude tool call still encounters a permission failure, the Node.js layer automatically runs a minimal AppleScript (`osascript -e 'tell application "Reminders" …'`) to surface the dialog and then retries the Swift CLI once.6566### Troubleshooting Calendar Read Errors6768If you see `Failed to read calendar events`, verify Calendar is set to **Full Calendar Access**:6970- Open `System Settings > Privacy & Security > Calendars`71- Find the app that launches this MCP server (for example Terminal or Claude Desktop)72- Change access to **Full Calendar Access**7374You can also re-run `./check-permissions.sh` (it now validates both Reminders and Calendars access).7576**Verification command**7778```bash79pnpm test -- src/swift/Info.plist.test.ts80```8182The test suite ensures all required usage-description strings are present before shipping the binary.8384## Quick Start8586You can run the server directly using `npx`:8788```bash89npx mcp-server-apple-events90```9192## Configuration9394### Configure Cursor95961. Open Cursor972. Open Cursor settings983. Click on "MCP" in the sidebar994. Click "Add new global MCP server"1005. Configure the server with the following settings:101102 ```json103 {104 "mcpServers": {105 "apple-reminders": {106 "command": "npx",107 "args": ["-y", "mcp-server-apple-events"]108 }109 }110 }111 ```112113### Configure ChatWise1141151. Open ChatWise1162. Go to Settings1173. Navigate to the Tools section1184. Click the "+" button1195. Configure the tool with the following settings:120 - Type: `stdio`121 - ID: `apple-reminders`122 - Command: `mcp-server-apple-events`123 - Args: (leave empty)124125### Configure Claude Desktop126127You need to configure Claude Desktop to recognize the Apple Events MCP server. There are two ways to access the configuration:128129#### Option 1: Through Claude Desktop UI1301311. Open Claude Desktop app1322. Enable Developer Mode from the top-left menu bar1333. Open Settings and navigate to the Developer Option1344. Click the Edit Config button to open `claude_desktop_config.json`135136#### Option 2: Direct File Access137138For macOS:139140```bash141code ~/Library/Application\ Support/Claude/claude_desktop_config.json142```143144For Windows:145146```bash147code %APPDATA%\Claude\claude_desktop_config.json148```149150### 2. Add Server Configuration151152Add the following configuration to your `claude_desktop_config.json`:153154**Option A: Using npx (recommended)**155156```json157{158 "mcpServers": {159 "apple-reminders": {160 "command": "npx",161 "args": ["-y", "mcp-server-apple-events"]162 }163 }164}165```166167**Option B: Using local build**168169If you have built the project locally, use node with the path to run.cjs:170171```json172{173 "mcpServers": {174 "apple-reminders": {175 "command": "node",176 "args": ["/absolute/path/to/mcp-server-apple-events/bin/run.cjs"]177 }178 }179}180```181182For more information on connecting local MCP servers, see the183[official MCP documentation](https://modelcontextprotocol.io/docs/develop/connect-local-servers).184185### 3. Restart Claude Desktop186187For the changes to take effect:1881891. Completely quit Claude Desktop (not just close the window)1902. Start Claude Desktop again1913. Look for the tool icon to verify the Apple Events server is connected192193## Usage Examples194195Once configured, you can ask Claude to interact with your Apple Reminders. Here are some example prompts:196197### Creating Reminders198199```text200Create a reminder to "Buy groceries" for tomorrow at 5 PM.201Add a reminder to "Call mom" with a note "Ask about weekend plans".202Create a reminder in my "Work" list to "Submit report" due next Friday.203Create a reminder with URL "Check this website: https://google.com".204```205206### Creating Reminders with Priority207208```text209Create a high priority reminder to "Finish quarterly report" due Friday.210Add an urgent high-priority reminder to "Call client back" for today.211Create a medium priority reminder to "Review documents".212```213214### Creating Recurring Reminders215216```text217Create a daily reminder to "Take medication" at 9 AM.218Add a weekly reminder every Monday to "Team standup meeting".219Create a monthly reminder on the 1st to "Pay rent".220Set up a yearly reminder on March 15 to "File taxes".221```222223### Creating Location-Based Reminders224225```text226Remind me to "Buy milk" when I arrive at the grocery store.227Create a reminder to "Check mailbox" when I get home.228Add a reminder to "Submit timesheet" when I leave the office.229```230231### Creating Reminders with Tags232233```text234Create a reminder "Review PR" with tags work and urgent.235Add a reminder "Buy birthday gift" tagged personal and shopping.236Create a reminder with tags: project-alpha, backend, review.237```238239### Creating Reminders with Subtasks240241```text242Create a reminder "Grocery shopping" with subtasks: milk, eggs, bread, butter.243Add a reminder "Pack for trip" with checklist items: passport, charger, clothes, toiletries.244Create "Sprint planning" with subtasks: review backlog, estimate stories, assign tasks.245```246247### Managing Subtasks248249```text250Show subtasks for my "Grocery shopping" reminder.251Mark the "milk" subtask as complete.252Add a new subtask "cheese" to my grocery list reminder.253Reorder the subtasks in my packing list.254```255256### Filtering Reminders257258```text259Show me all high priority reminders.260Show reminders tagged with "work".261Show recurring reminders only.262Find location-based reminders.263Show reminders with incomplete subtasks.264```265266### Update Reminders267268```text269Update the reminder "Buy groceries" with a new title "Buy organic groceries".270Update "Call mom" reminder to be due today at 6 PM.271Update the reminder "Submit report" and mark it as completed.272Change the notes on "Buy groceries" to "Don't forget milk and eggs".273Set priority to high on my "Finish report" reminder.274Add the tag "urgent" to my "Review PR" reminder.275```276277### Managing Reminders278279```text280Show me all my reminders.281List all reminders in my "Shopping" list.282Show my completed reminders.283```284285### Working with Lists286287```text288Show all my reminder lists.289Show reminders from my "Work" list.290```291292The server will:293294- Process your natural language requests295- Interact with Apple's native Reminders app296- Return formatted results to Claude297- Maintain native integration with macOS298299## Structured Prompt Library300301The server ships with a consolidated prompt registry exposed via the MCP `ListPrompts` and `GetPrompt` endpoints. Each template shares a mission, context inputs, numbered process, constraints, output format, and quality bar so downstream assistants receive predictable scaffolding instead of brittle free-form examples.302303- **daily-task-organizer** — optional `today_focus` (what you most want to accomplish today) input produces a same-day execution blueprint that keeps priority work balanced with recovery time. Supports intelligent task clustering, focus block scheduling, automatic reminder list organization, and auto-creates calendar time blocks when many due-today reminders need fixed slots. Quick Win clusters become 15-minute "Focus Sprint — [Outcome]" holds that finish at each reminder's due timestamp, while Standard tasks map to 30-, 45-, or 60-minute events anchored to the same due-time window.304- **smart-reminder-creator** — optional `task_idea` (a short description of what you want to do) generates an optimally scheduled reminder structure.305- **reminder-review-assistant** — optional `review_focus` (e.g., overdue or a list name) to audit and optimize existing reminders.306- **weekly-planning-workflow** — optional `user_ideas` (your thoughts and ideas for what you want to accomplish this week) guides a Monday-through-Sunday reset with time blocks tied to existing lists.307308### Design constraints and validation309310- Prompts are intentionally constrained to native Apple Reminders capabilities (no third-party automations) and ask for missing context before committing to irreversible actions.311- Shared formatting keeps outputs renderable as Markdown sections or tables without extra parsing glue in client applications.312- Run `pnpm test -- src/server/prompts.test.ts` to assert metadata, schema compatibility, and narrative assembly each time you amend prompt copy.313314## Available MCP Tools315316This server now exposes service-scoped MCP tools that mirror Apple Reminders and Calendar domains. Use the identifier that matches the resource you want to manipulate:317318### Reminder Tasks Tool319320**Tool Name**: `reminders_tasks`321322Manages individual reminder tasks with full CRUD support, including priority, alarms, recurrence rules, start/due/completion dates, location triggers, tags, and subtasks.323324**Actions**: `read`, `create`, `update`, `delete`325326**Main Handler Functions**:327328- `handleReadReminders()` - Read reminders with filtering options329- `handleCreateReminder()` - Create new reminders330- `handleUpdateReminder()` - Update existing reminders331- `handleDeleteReminder()` - Delete reminders332333#### Parameters by Action334335**Read Action** (`action: "read"`):336337- `id` _(optional)_: Unique identifier of a specific reminder to read338- `filterList` _(optional)_: Name of the reminder list to show339- `showCompleted` _(optional)_: Include completed reminders (default: false)340- `search` _(optional)_: Search term to filter reminders by title or content341- `dueWithin` _(optional)_: Filter by due date range ("today", "tomorrow", "this-week", "overdue", "no-date")342- `filterPriority` _(optional)_: Filter by priority level ("high", "medium", "low", "none")343- `filterRecurring` _(optional)_: Filter to only show recurring reminders when true344- `filterLocationBased` _(optional)_: Filter to only show location-based reminders when true345- `filterTags` _(optional)_: Filter by tags (reminders must have ALL specified tags)346347**Create Action** (`action: "create"`):348349- `title` _(required)_: Title of the reminder350- `startDate` _(optional)_: Start date in format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm:ss'351- `dueDate` _(optional)_: Due date in format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm:ss'352- `targetList` _(optional)_: Name of the reminders list to add to353- `note` _(optional)_: Note text to attach to the reminder354- `url` _(optional)_: URL to associate with the reminder355- `location` _(optional)_: Location text (`EKCalendarItem.location`) (not a geofence trigger)356- `priority` _(optional)_: Priority level (0=none, 1=high, 2=medium, 3=low)357- `alarms` _(optional)_: Array of alarm objects (see Alarm Object below)358- `recurrenceRules` _(optional)_: Array of recurrence rules (see Recurrence Rules below)359- `recurrence` _(optional)_: Legacy single recurrence rule object (shorthand for one-item `recurrenceRules`)360- `locationTrigger` _(optional)_: Location trigger object (see Location Triggers section below)361- `tags` _(optional)_: Array of tags to add to the reminder362- `subtasks` _(optional)_: Array of subtask titles to create with the reminder363364**Update Action** (`action: "update"`):365366- `id` _(required)_: Unique identifier of the reminder to update367- `title` _(optional)_: New title for the reminder368- `startDate` _(optional)_: New start date369- `dueDate` _(optional)_: New due date in format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:mm:ss'370- `note` _(optional)_: New note text371- `url` _(optional)_: New URL to attach to the reminder372- `location` _(optional)_: New location text (set to empty string to clear)373- `completed` _(optional)_: Mark reminder as completed/uncompleted374- `completionDate` _(optional)_: Set an explicit completion date/time375- `targetList` _(optional)_: Name of the list containing the reminder376- `priority` _(optional)_: New priority level (0=none, 1=high, 2=medium, 3=low)377- `alarms` _(optional)_: Replace alarms with this array378- `clearAlarms` _(optional)_: Set to true to remove all alarms379- `recurrenceRules` _(optional)_: Replace recurrence rules with this array380- `recurrence` _(optional)_: Legacy single recurrence rule (shorthand for one-item `recurrenceRules`)381- `clearRecurrence` _(optional)_: Set to true to remove recurrence382- `locationTrigger` _(optional)_: New location trigger383- `clearLocationTrigger` _(optional)_: Set to true to remove location trigger384- `tags` _(optional)_: Replace all tags with this array385- `addTags` _(optional)_: Tags to add (merges with existing)386- `removeTags` _(optional)_: Tags to remove387388**Delete Action** (`action: "delete"`):389390- `id` _(required)_: Unique identifier of the reminder to delete391392#### Alarm Object393394```json395{396 "relativeOffset": -900, // Seconds (relative to due/start); negative = before397 "absoluteDate": "2025-11-04T09:00:00+08:00", // Absolute trigger time (optional)398 "locationTrigger": { // Geofence trigger (optional)399 "title": "Office",400 "latitude": 37.7749,401 "longitude": -122.4194,402 "radius": 100,403 "proximity": "enter"404 }405}406```407408Each alarm must specify exactly **one** of `relativeOffset`, `absoluteDate`, or `locationTrigger`.409410#### Recurrence Rule Object (for `recurrenceRules`)411412```json413{414 "frequency": "daily" | "weekly" | "monthly" | "yearly",415 "interval": 1, // Every N periods (default: 1)416 "endDate": "YYYY-MM-DD", // Optional end date417 "occurrenceCount": 10, // Optional max occurrences418 "daysOfWeek": [1, 3, 5], // 1=Sunday, 7=Saturday (for weekly)419 "daysOfMonth": [1, 15], // 1-31 (for monthly)420 "monthsOfYear": [3, 6] // 1-12 (for yearly)421}422```423424#### Location Trigger Object425426```json427{428 "title": "Home", // Location name429 "latitude": 37.7749, // Latitude coordinate430 "longitude": -122.4194, // Longitude coordinate431 "radius": 100, // Geofence radius in meters (default: 100)432 "proximity": "enter" // "enter" or "leave"433}434```435436#### Example Usage437438```json439{440 "action": "create",441 "title": "Buy groceries",442 "dueDate": "2024-03-25 18:00:00",443 "targetList": "Shopping",444 "note": "Don't forget milk and eggs",445 "priority": 1,446 "tags": ["shopping", "errands"],447 "subtasks": ["Milk", "Eggs", "Bread"]448}449```450451```json452{453 "action": "create",454 "title": "Team standup",455 "dueDate": "2024-03-25 09:00:00",456 "recurrence": {457 "frequency": "weekly",458 "interval": 1,459 "daysOfWeek": [2, 3, 4, 5, 6]460 }461}462```463464```json465{466 "action": "create",467 "title": "Buy milk",468 "locationTrigger": {469 "title": "Grocery Store",470 "latitude": 37.7749,471 "longitude": -122.4194,472 "radius": 200,473 "proximity": "enter"474 }475}476```477478```json479{480 "action": "read",481 "filterList": "Work",482 "showCompleted": false,483 "dueWithin": "today",484 "filterPriority": "high",485 "filterTags": ["urgent"]486}487```488489```json490{491 "action": "delete",492 "id": "reminder-123"493}494```495496### Reminder Subtasks Tool497498**Tool Name**: `reminders_subtasks`499500Manages subtasks/checklists within reminders. Subtasks are stored in the notes field using a human-readable format visible in the native Reminders app.501502**Actions**: `read`, `create`, `update`, `delete`, `toggle`, `reorder`503504**Main Handler Functions**:505506- `handleReadSubtasks()` - List all subtasks for a reminder507- `handleCreateSubtask()` - Add a new subtask508- `handleUpdateSubtask()` - Modify a subtask509- `handleDeleteSubtask()` - Remove a subtask510- `handleToggleSubtask()` - Flip completion status511- `handleReorderSubtasks()` - Change subtask order512513#### Parameters by Action514515**Read Action** (`action: "read"`):516517- `reminderId` _(required)_: Parent reminder ID518519**Create Action** (`action: "create"`):520521- `reminderId` _(required)_: Parent reminder ID522- `title` _(required)_: Subtask title523524**Update Action** (`action: "update"`):525526- `reminderId` _(required)_: Parent reminder ID527- `subtaskId` _(required)_: Subtask ID to update528- `title` _(optional)_: New title529- `completed` _(optional)_: New completion status530531**Delete Action** (`action: "delete"`):532533- `reminderId` _(required)_: Parent reminder ID534- `subtaskId` _(required)_: Subtask ID to delete535536**Toggle Action** (`action: "toggle"`):537538- `reminderId` _(required)_: Parent reminder ID539- `subtaskId` _(required)_: Subtask ID to toggle540541**Reorder Action** (`action: "reorder"`):542543- `reminderId` _(required)_: Parent reminder ID544- `order` _(required)_: Array of all subtask IDs in desired order545546#### Example Usage547548```json549{550 "action": "read",551 "reminderId": "reminder-123"552}553```554555```json556{557 "action": "create",558 "reminderId": "reminder-123",559 "title": "Pick up dry cleaning"560}561```562563```json564{565 "action": "toggle",566 "reminderId": "reminder-123",567 "subtaskId": "a1b2c3d4"568}569```570571#### Subtask Storage Format572573Subtasks are stored in the notes field with this human-readable format:574575```text576User notes here...577578---SUBTASKS---579[ ] {a1b2c3d4} First task580[x] {e5f6g7h8} Completed task581[ ] {i9j0k1l2} Another task582---END SUBTASKS---583```584585This format ensures subtasks are visible in the native Reminders app while enabling programmatic access.586587### Reminder Lists Tool588589**Tool Name**: `reminders_lists`590591Manages reminder lists - view existing lists or create new ones for organizing reminders.592593**Actions**: `read`, `create`, `update`, `delete`594595**Main Handler Functions**:596597- `handleReadReminderLists()` - Read all reminder lists598- `handleCreateReminderList()` - Create new reminder lists599- `handleUpdateReminderList()` - Update existing reminder lists600- `handleDeleteReminderList()` - Delete reminder lists601602#### Parameters by Action603604**Read Action** (`action: "read"`):605606- No additional parameters required607608**Create Action** (`action: "create"`):609610- `name` _(required)_: Name for new reminder list611612**Update Action** (`action: "update"`):613614- `name` _(required)_: Current name of the list to update615- `newName` _(required)_: New name for the reminder list616617**Delete Action** (`action: "delete"`):618619- `name` _(required)_: Name of the list to delete620621#### Example Usage622623```json624{625 "action": "create",626 "name": "Project Alpha"627}628```629630### Calendar Events Tool631632**Tool Name**: `calendar_events`633634Handles EventKit calendar events (time blocks) with CRUD capabilities.635636**Actions**: `read`, `create`, `update`, `delete`637638**Main Handler Functions**:639640- `handleReadCalendarEvents()` - Read events with optional filters641- `handleCreateCalendarEvent()` - Create calendar events642- `handleUpdateCalendarEvent()` - Update existing events643- `handleDeleteCalendarEvent()` - Delete calendar events644645#### Parameters by Action646647**Read Action** (`action: "read"`):648649- `id` _(optional)_: Unique identifier of an event to read650- `filterCalendar` _(optional)_: Calendar name filter651- `search` _(optional)_: Keyword match against title, notes, or location652- `availability` _(optional)_: Filter by availability ("busy", "free", "tentative", "unavailable", "not-supported")653- `startDate` _(optional)_: Filter events starting on/after this date654- `endDate` _(optional)_: Filter events ending on/before this date655656**Create Action** (`action: "create"`):657658- `title` _(required)_: Event title659- `startDate` _(required)_: Start date/time660- `endDate` _(required)_: End date/time661- `targetCalendar` _(optional)_: Calendar name to create in662- `note`, `location`, `structuredLocation`, `url`, `isAllDay` _(optional)_: Additional metadata663- `availability` _(optional)_: Availability ("busy", "free", "tentative", "unavailable")664- `alarms` _(optional)_: Array of alarm objects (see Alarm Object above)665- `recurrenceRules` _(optional)_: Array of recurrence rules (see Recurrence Rule Object above)666667**Update Action** (`action: "update"`):668669- `id` _(required)_: Event identifier670- Other fields align with create parameters and are optional updates671- `clearAlarms` _(optional)_: Set to true to remove all alarms672- `clearRecurrence` _(optional)_: Set to true to remove all recurrence rules673- `span` _(optional)_: Scope for recurring event changes: `"this-event"` or `"future-events"`674675**Delete Action** (`action: "delete"`):676677- `id` _(required)_: Event identifier to remove678- `span` _(optional)_: Scope for recurring event deletes: `"this-event"` or `"future-events"`679680### Calendar Collections Tool681682**Tool Name**: `calendar_calendars`683684Returns the available calendars from EventKit. This is useful before creating or updating events to confirm calendar identifiers.685686**Actions**: `read`687688**Main Handler Function**:689690- `handleReadCalendars()` - List all calendars with IDs and titles691692**Example Usage**693694```json695{696 "action": "read"697}698```699700**Example Response**701702```json703{704 "content": [705 {706 "type": "text",707 "text": "### Calendars (Total: 3)\n- Work (ID: cal-1)\n- Personal (ID: cal-2)\n- Shared (ID: cal-3)"708 }709 ],710 "isError": false711}712```713714#### Response Formats715716**Success Response**:717718```json719{720 "content": [721 {722 "type": "text",723 "text": "Successfully created reminder: Buy groceries"724 }725 ],726 "isError": false727}728```729730**Reminder with Enhanced Features**:731732When reading reminders, the output includes visual indicators for enhanced features:733734- 🔄 - Recurring reminder735- 📍 - Location-based reminder736- 🏷️ - Has tags737- 📋 - Has subtasks738739Example output:740741```text742- [ ] Buy groceries 🏷️📋743 - List: Shopping744 - ID: reminder-123745 - Priority: high746 - Tags: #shopping #errands747 - Subtasks (1/3):748 - [x] Milk749 - [ ] Eggs750 - [ ] Bread751 - Due: 2024-03-25 18:00:00752```753754**Note about URL fields**: The `url` field is fully supported by EventKit API. When you create or update a reminder with a URL parameter, the URL is stored in two places for maximum compatibility:7557561. **EventKit URL field**: The URL is stored in the native `url` property (visible in Reminders app detail view via the "i" icon)7572. **Notes field**: The URL is also appended to the notes using a structured format for parsing758759**Dual Storage Approach**:760761- **URL field**: Stores a single URL for native Reminders app display762- **Notes field**: Stores URLs in a structured format for parsing and multiple URL support763764```text765Reminder note content here...766767URLs:768- https://example.com769- https://another-url.com770```771772This ensures URLs are accessible both in the Reminders app UI and through the API/notes for parsing.773774**URL Extraction**: You can extract URLs from reminder notes using regex:775776```typescript777// Extract URLs from notes using regex778const urlsRegex = reminder.notes?.match(/https?:\/\/[^\s]+/g) || [];779```780781**Benefits of Structured Format**:782783- **Consistent parsing**: URLs are always in a predictable location784- **Multiple URL support**: Handle multiple URLs per reminder reliably785- **Clean separation**: Note content and URLs are clearly separated786- **Backward compatible**: Unstructured URLs still detected as fallback787788**List Response**:789790```json791{792 "reminders": [793 {794 "title": "Buy groceries",795 "list": "Shopping",796 "isCompleted": false,797 "dueDate": "2024-03-25 18:00:00",798 "priority": 1,799 "tags": ["shopping", "errands"],800 "subtasks": [801 { "id": "a1b2c3d4", "title": "Milk", "isCompleted": true },802 { "id": "e5f6g7h8", "title": "Eggs", "isCompleted": false }803 ],804 "subtaskProgress": { "completed": 1, "total": 2, "percentage": 50 },805 "notes": "Don't forget the organic options",806 "url": null807 }808 ],809 "total": 1,810 "filter": {811 "list": "Shopping",812 "showCompleted": false813 }814}815```816817## Organization Strategies818819The server provides intelligent reminder organization capabilities through four built-in strategies:820821### Priority Strategy822823Automatically categorizes reminders based on priority keywords:824825- **High Priority**: Contains words like "urgent", "important", "critical", "asap"826- **Medium Priority**: Default category for standard reminders827- **Low Priority**: Contains words like "later", "someday", "eventually", "maybe"828829### Due Date Strategy830831Organizes reminders based on their due dates:832833- **Overdue**: Past due dates834- **Today**: Due today835- **Tomorrow**: Due tomorrow836- **This Week**: Due within the current week837- **Next Week**: Due next week838- **Future**: Due beyond next week839- **No Date**: Reminders without due dates840841### Category Strategy842843Intelligently categorizes reminders by content analysis:844845- **Work**: Business, meetings, projects, office, client related846- **Personal**: Home, family, friends, self-care related847- **Shopping**: Buy, store, purchase, groceries related848- **Health**: Doctor, exercise, medical, fitness, workout related849- **Finance**: Bills, payments, bank, budget related850- **Travel**: Trips, flights, hotels, vacation related851- **Education**: Study, learn, courses, books, research related852- **Uncategorized**: Doesn't match any specific category853854### Completion Status Strategy855856Simple binary organization:857858- **Active**: Incomplete reminders859- **Completed**: Finished reminders860861### Usage Examples862863Organize all reminders by priority:864865```text866Organize my reminders by priority867```868869Categorize work-related reminders:870871```text872Organize reminders from Work list by category873```874875Sort overdue items:876877```text878Organize overdue reminders by due date879```880881## Tags System882883Tags provide cross-list categorization for reminders. They are stored in the notes field using the `[#tag]` format, which keeps them human-readable in the native Reminders app.884885### Tag Format886887Tags are stored at the end of notes:888889```text890User notes here...891892[#work] [#urgent] [#project-alpha]893```894895### Tag Rules896897- Tags can contain letters, numbers, underscores, and hyphens898- Maximum 50 characters per tag899- Case-sensitive900- Filter by multiple tags uses AND logic (reminder must have ALL specified tags)901902### Example Tag Operations903904Create with tags:905906```json907{908 "action": "create",909 "title": "Review code",910 "tags": ["work", "code-review", "urgent"]911}912```913914Filter by tags:915916```json917{918 "action": "read",919 "filterTags": ["work", "urgent"]920}921```922923Update tags (add/remove):924925```json926{927 "action": "update",928 "id": "reminder-123",929 "addTags": ["completed"],930 "removeTags": ["urgent"]931}932```933934## License935936MIT937938## Contributing939940Contributions welcome! Please read the contributing guidelines first.941942## Development9439441. Install dependencies with pnpm (keeps the Swift bridge and TypeScript graph in sync):945946```bash947pnpm install948```9499501. Build the project (TypeScript and Swift binary) before invoking the CLI:951952```bash953pnpm build954```9559561. Run the full test suite to validate TypeScript, Swift bridge shims, and prompt templates:957958```bash959pnpm test960```9619621. Lint and format with Biome prior to committing:963964```bash965pnpm exec biome check966```967968### Launching from nested directories969970The CLI entry point includes a project-root fallback, so you can start the server from nested paths (for example `dist/` or editor task runners) without losing access to the bundled Swift binary. The bootstrapper walks up to ten directories to find `package.json`; if you customise the folder layout, keep the manifest reachable within that depth to retain the guarantee.971972### Available Scripts973974- `pnpm build` - Build the Swift helper binary (required before starting the server)975- `pnpm build:swift` - Build the Swift helper binary only976- `pnpm dev` - TypeScript development mode with file watching via tsx (runtime TS execution)977- `pnpm start` - Start the MCP server over stdio (auto-fallback to runtime TS if no build)978- `pnpm test` - Run the comprehensive Jest test suite979- `pnpm check` - Run Biome formatting and TypeScript type checking980981### Dependencies982983**Runtime Dependencies:**984985- `@modelcontextprotocol/sdk ^1.25.1` - MCP protocol implementation986- `exit-on-epipe ^1.0.1` - Graceful process termination handling987- `tsx ^4.21.0` - TypeScript execution and REPL988- `zod ^4.3.5` - Runtime type validation989990**Development Dependencies:**991992- `typescript ^5.9.3` - TypeScript compiler993- `@types/node ^25.0.3` - Node.js type definitions994- `@types/jest ^30.0.0` - Jest type definitions995- `jest ^30.2.0` - Testing framework996- `babel-jest ^30.2.0` - Babel Jest transformer997- `babel-plugin-transform-import-meta ^2.3.3` - Babel import meta transform998- `ts-jest ^29.4.6` - Jest TypeScript support999- `@biomejs/biome ^2.3.11` - Code formatting and linting10001001**Build Tools:**10021003- Swift binaries for native macOS integration1004- TypeScript compilation for cross-platform compatibility1005
Full transparency — inspect the skill content before installing.