mcp-macos 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +360 -0
  3. package/bin/dev.cjs +10 -0
  4. package/bin/run.cjs +15 -0
  5. package/dist/config/index.d.ts +36 -0
  6. package/dist/config/index.js +127 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config/schema.d.ts +161 -0
  9. package/dist/config/schema.js +45 -0
  10. package/dist/config/schema.js.map +1 -0
  11. package/dist/index.d.ts +11 -0
  12. package/dist/index.js +75 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/server/handlers.d.ts +10 -0
  15. package/dist/server/handlers.js +43 -0
  16. package/dist/server/handlers.js.map +1 -0
  17. package/dist/server/promptAbstractions.d.ts +74 -0
  18. package/dist/server/promptAbstractions.js +150 -0
  19. package/dist/server/promptAbstractions.js.map +1 -0
  20. package/dist/server/prompts.d.ts +8 -0
  21. package/dist/server/prompts.js +480 -0
  22. package/dist/server/prompts.js.map +1 -0
  23. package/dist/server/server.d.ts +29 -0
  24. package/dist/server/server.js +52 -0
  25. package/dist/server/server.js.map +1 -0
  26. package/dist/server/transports/http/auth.d.ts +34 -0
  27. package/dist/server/transports/http/auth.js +148 -0
  28. package/dist/server/transports/http/auth.js.map +1 -0
  29. package/dist/server/transports/http/health.d.ts +35 -0
  30. package/dist/server/transports/http/health.js +93 -0
  31. package/dist/server/transports/http/health.js.map +1 -0
  32. package/dist/server/transports/http/index.d.ts +43 -0
  33. package/dist/server/transports/http/index.js +141 -0
  34. package/dist/server/transports/http/index.js.map +1 -0
  35. package/dist/server/transports/http/middleware.d.ts +53 -0
  36. package/dist/server/transports/http/middleware.js +133 -0
  37. package/dist/server/transports/http/middleware.js.map +1 -0
  38. package/dist/tools/definitions.d.ts +10 -0
  39. package/dist/tools/definitions.js +633 -0
  40. package/dist/tools/definitions.js.map +1 -0
  41. package/dist/tools/handlers/calendarHandlers.d.ts +11 -0
  42. package/dist/tools/handlers/calendarHandlers.js +123 -0
  43. package/dist/tools/handlers/calendarHandlers.js.map +1 -0
  44. package/dist/tools/handlers/contactsHandlers.d.ts +17 -0
  45. package/dist/tools/handlers/contactsHandlers.js +397 -0
  46. package/dist/tools/handlers/contactsHandlers.js.map +1 -0
  47. package/dist/tools/handlers/index.d.ts +11 -0
  48. package/dist/tools/handlers/index.js +12 -0
  49. package/dist/tools/handlers/index.js.map +1 -0
  50. package/dist/tools/handlers/listHandlers.d.ts +10 -0
  51. package/dist/tools/handlers/listHandlers.js +40 -0
  52. package/dist/tools/handlers/listHandlers.js.map +1 -0
  53. package/dist/tools/handlers/mailHandlers.d.ts +11 -0
  54. package/dist/tools/handlers/mailHandlers.js +301 -0
  55. package/dist/tools/handlers/mailHandlers.js.map +1 -0
  56. package/dist/tools/handlers/messagesHandlers.d.ts +17 -0
  57. package/dist/tools/handlers/messagesHandlers.js +350 -0
  58. package/dist/tools/handlers/messagesHandlers.js.map +1 -0
  59. package/dist/tools/handlers/notesHandlers.d.ts +12 -0
  60. package/dist/tools/handlers/notesHandlers.js +305 -0
  61. package/dist/tools/handlers/notesHandlers.js.map +1 -0
  62. package/dist/tools/handlers/reminderHandlers.d.ts +10 -0
  63. package/dist/tools/handlers/reminderHandlers.js +96 -0
  64. package/dist/tools/handlers/reminderHandlers.js.map +1 -0
  65. package/dist/tools/handlers/shared.d.ts +51 -0
  66. package/dist/tools/handlers/shared.js +107 -0
  67. package/dist/tools/handlers/shared.js.map +1 -0
  68. package/dist/tools/index.d.ts +10 -0
  69. package/dist/tools/index.js +125 -0
  70. package/dist/tools/index.js.map +1 -0
  71. package/dist/types/index.d.ts +265 -0
  72. package/dist/types/index.js +67 -0
  73. package/dist/types/index.js.map +1 -0
  74. package/dist/types/prompts.d.ts +84 -0
  75. package/dist/types/prompts.js +6 -0
  76. package/dist/types/prompts.js.map +1 -0
  77. package/dist/types/repository.d.ts +102 -0
  78. package/dist/types/repository.js +6 -0
  79. package/dist/types/repository.js.map +1 -0
  80. package/dist/utils/binaryValidator.d.ts +52 -0
  81. package/dist/utils/binaryValidator.js +152 -0
  82. package/dist/utils/binaryValidator.js.map +1 -0
  83. package/dist/utils/calendarRepository.d.ts +25 -0
  84. package/dist/utils/calendarRepository.js +100 -0
  85. package/dist/utils/calendarRepository.js.map +1 -0
  86. package/dist/utils/cliExecutor.d.ts +28 -0
  87. package/dist/utils/cliExecutor.js +196 -0
  88. package/dist/utils/cliExecutor.js.map +1 -0
  89. package/dist/utils/constants.d.ts +96 -0
  90. package/dist/utils/constants.js +97 -0
  91. package/dist/utils/constants.js.map +1 -0
  92. package/dist/utils/contactResolver.d.ts +142 -0
  93. package/dist/utils/contactResolver.js +386 -0
  94. package/dist/utils/contactResolver.js.map +1 -0
  95. package/dist/utils/dateFiltering.d.ts +22 -0
  96. package/dist/utils/dateFiltering.js +72 -0
  97. package/dist/utils/dateFiltering.js.map +1 -0
  98. package/dist/utils/dateUtils.d.ts +20 -0
  99. package/dist/utils/dateUtils.js +36 -0
  100. package/dist/utils/dateUtils.js.map +1 -0
  101. package/dist/utils/errorHandling.d.ts +30 -0
  102. package/dist/utils/errorHandling.js +101 -0
  103. package/dist/utils/errorHandling.js.map +1 -0
  104. package/dist/utils/helpers.d.ts +35 -0
  105. package/dist/utils/helpers.js +59 -0
  106. package/dist/utils/helpers.js.map +1 -0
  107. package/dist/utils/jxaExecutor.d.ts +47 -0
  108. package/dist/utils/jxaExecutor.js +194 -0
  109. package/dist/utils/jxaExecutor.js.map +1 -0
  110. package/dist/utils/logging.d.ts +31 -0
  111. package/dist/utils/logging.js +98 -0
  112. package/dist/utils/logging.js.map +1 -0
  113. package/dist/utils/permissionPrompt.d.ts +16 -0
  114. package/dist/utils/permissionPrompt.js +42 -0
  115. package/dist/utils/permissionPrompt.js.map +1 -0
  116. package/dist/utils/preflight.d.ts +30 -0
  117. package/dist/utils/preflight.js +196 -0
  118. package/dist/utils/preflight.js.map +1 -0
  119. package/dist/utils/projectUtils.d.ts +11 -0
  120. package/dist/utils/projectUtils.js +76 -0
  121. package/dist/utils/projectUtils.js.map +1 -0
  122. package/dist/utils/reminderDateParser.d.ts +8 -0
  123. package/dist/utils/reminderDateParser.js +77 -0
  124. package/dist/utils/reminderDateParser.js.map +1 -0
  125. package/dist/utils/reminderRepository.d.ts +23 -0
  126. package/dist/utils/reminderRepository.js +91 -0
  127. package/dist/utils/reminderRepository.js.map +1 -0
  128. package/dist/utils/sqliteContactReader.d.ts +51 -0
  129. package/dist/utils/sqliteContactReader.js +216 -0
  130. package/dist/utils/sqliteContactReader.js.map +1 -0
  131. package/dist/utils/sqliteMailReader.d.ts +97 -0
  132. package/dist/utils/sqliteMailReader.js +310 -0
  133. package/dist/utils/sqliteMailReader.js.map +1 -0
  134. package/dist/utils/sqliteMessageReader.d.ts +71 -0
  135. package/dist/utils/sqliteMessageReader.js +400 -0
  136. package/dist/utils/sqliteMessageReader.js.map +1 -0
  137. package/dist/utils/timeHelpers.d.ts +40 -0
  138. package/dist/utils/timeHelpers.js +136 -0
  139. package/dist/utils/timeHelpers.js.map +1 -0
  140. package/dist/utils/timezone.d.ts +24 -0
  141. package/dist/utils/timezone.js +39 -0
  142. package/dist/utils/timezone.js.map +1 -0
  143. package/dist/validation/schemas.d.ts +610 -0
  144. package/dist/validation/schemas.js +354 -0
  145. package/dist/validation/schemas.js.map +1 -0
  146. package/package.json +97 -0
  147. package/scripts/build-swift.mjs +86 -0
  148. package/src/swift/EventKitCLI.swift +778 -0
  149. package/src/swift/Info.plist +38 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../../../src/server/transports/http/middleware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * tools/definitions.ts
3
+ * MCP tool definitions for Apple Reminders server, adhering to standard JSON Schema.
4
+ */
5
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
6
+ /**
7
+ * Export TOOLS as Tool[] for MCP server compatibility
8
+ * The dependentSchemas are preserved at runtime even though TypeScript doesn't type-check them
9
+ */
10
+ export declare const TOOLS: Tool[];
@@ -0,0 +1,633 @@
1
+ /**
2
+ * tools/definitions.ts
3
+ * MCP tool definitions for Apple Reminders server, adhering to standard JSON Schema.
4
+ */
5
+ import { CALENDAR_ACTIONS, CONTACTS_ACTIONS, DATE_RANGE_SHORTCUTS, DUE_WITHIN_OPTIONS, LIST_ACTIONS, MAIL_ACTIONS, MESSAGES_ACTIONS, NOTES_ACTIONS, NOTES_FOLDERS_ACTIONS, REMINDER_ACTIONS, } from '../types/index.js';
6
+ const _EXTENDED_TOOLS = [
7
+ {
8
+ name: 'reminders_tasks',
9
+ description: 'Manages Apple Reminders tasks. Common actions: (1) "Show my reminders" → read action. (2) "Remind me to X" → create with title and optional dueDate. (3) "Mark X as done" → update with completed=true. Filter by list with filterList, by due date with dueWithin (today/tomorrow/this-week/overdue/no-date), or search by title/notes with search. Use targetList to assign a reminder to a specific list. Title max 200 chars, notes max 2000 chars.',
10
+ inputSchema: {
11
+ type: 'object',
12
+ properties: {
13
+ action: {
14
+ type: 'string',
15
+ enum: REMINDER_ACTIONS,
16
+ description: 'The operation to perform.',
17
+ },
18
+ // ID-based operations
19
+ id: {
20
+ type: 'string',
21
+ description: 'The unique identifier of the reminder (REQUIRED for update, delete; optional for read to get single reminder).',
22
+ },
23
+ // Creation/Update properties
24
+ title: {
25
+ type: 'string',
26
+ description: 'The title of the reminder (REQUIRED for create, optional for update).',
27
+ },
28
+ dueDate: {
29
+ type: 'string',
30
+ description: "Due date. RECOMMENDED format: 'YYYY-MM-DD HH:mm:ss' (local time without timezone, e.g., '2025-11-04 18:00:00'). Also supports: 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ss', or ISO 8601 with timezone (e.g., '2025-10-30T04:00:00Z'). When no timezone is specified, the time is interpreted as local time.",
31
+ },
32
+ note: {
33
+ type: 'string',
34
+ description: 'Additional notes for the reminder.',
35
+ },
36
+ url: {
37
+ type: 'string',
38
+ description: 'A URL to associate with the reminder.',
39
+ format: 'uri',
40
+ },
41
+ completed: {
42
+ type: 'boolean',
43
+ description: 'The completion status of the reminder (for update).',
44
+ },
45
+ targetList: {
46
+ type: 'string',
47
+ description: 'The name of the list for create or update operations.',
48
+ },
49
+ // Read filters
50
+ filterList: {
51
+ type: 'string',
52
+ description: 'Filter reminders by a specific list name.',
53
+ },
54
+ showCompleted: {
55
+ type: 'boolean',
56
+ description: 'Include completed reminders in the results.',
57
+ default: false,
58
+ },
59
+ search: {
60
+ type: 'string',
61
+ description: 'A search term to filter reminders by title or notes.',
62
+ },
63
+ dueWithin: {
64
+ type: 'string',
65
+ enum: DUE_WITHIN_OPTIONS,
66
+ description: 'Filter reminders by a due date range.',
67
+ },
68
+ },
69
+ required: ['action'],
70
+ dependentSchemas: {
71
+ action: {
72
+ oneOf: [
73
+ { properties: { action: { const: 'read' } } },
74
+ {
75
+ properties: { action: { const: 'create' } },
76
+ required: ['title'],
77
+ },
78
+ { properties: { action: { const: 'update' } }, required: ['id'] },
79
+ { properties: { action: { const: 'delete' } }, required: ['id'] },
80
+ ],
81
+ },
82
+ },
83
+ },
84
+ },
85
+ {
86
+ name: 'reminders_lists',
87
+ description: 'Manages Apple Reminders lists (categories/groups that contain tasks). Common actions: (1) "What lists do I have?" → read action. (2) "Create a Shopping list" → create with name. (3) "Rename list X to Y" → update with name (current) and newName. (4) "Delete list X" → delete with name. List name max 100 chars.',
88
+ inputSchema: {
89
+ type: 'object',
90
+ properties: {
91
+ action: {
92
+ type: 'string',
93
+ enum: LIST_ACTIONS,
94
+ description: 'The operation to perform on a list.',
95
+ },
96
+ name: {
97
+ type: 'string',
98
+ description: 'The current name of the list (for update, delete) or the name of the new list (for create).',
99
+ },
100
+ newName: {
101
+ type: 'string',
102
+ description: 'The new name for the list (for update).',
103
+ },
104
+ },
105
+ required: ['action'],
106
+ dependentSchemas: {
107
+ action: {
108
+ oneOf: [
109
+ { properties: { action: { const: 'read' } } },
110
+ { properties: { action: { const: 'create' } }, required: ['name'] },
111
+ {
112
+ properties: { action: { const: 'update' } },
113
+ required: ['name', 'newName'],
114
+ },
115
+ { properties: { action: { const: 'delete' } }, required: ['name'] },
116
+ ],
117
+ },
118
+ },
119
+ },
120
+ },
121
+ {
122
+ name: 'calendar_events',
123
+ description: 'Manages Apple Calendar events. Common actions: (1) "What\'s on my calendar?" → read with startDate/endDate range. (2) "Schedule a meeting" → create with title, startDate, endDate. (3) "Move my meeting" → update with id and new startDate/endDate. Supports recurring events via recurrence param (daily/weekly/monthly/yearly). Use filterCalendar to filter by calendar name, search to find events by title/notes/location. Use enrichContacts=true (default) to resolve attendee emails to contact names. Deleting a recurring event only removes the single occurrence. Use calendar_calendars tool first to see available calendar names. Related tools: Cross-reference with messages_chat or mail_messages to find conversations about a specific event. Use contacts_people for attendee contact details.',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ action: {
128
+ type: 'string',
129
+ enum: CALENDAR_ACTIONS,
130
+ description: 'The operation to perform.',
131
+ },
132
+ // ID-based operations
133
+ id: {
134
+ type: 'string',
135
+ description: 'The unique identifier of the event (REQUIRED for update, delete; optional for read to get single event).',
136
+ },
137
+ // Creation/Update properties
138
+ title: {
139
+ type: 'string',
140
+ description: 'The title of the event (REQUIRED for create, optional for update).',
141
+ },
142
+ startDate: {
143
+ type: 'string',
144
+ description: "Start date and time. RECOMMENDED format: 'YYYY-MM-DD HH:mm:ss' (local time without timezone, e.g., '2025-11-04 09:00:00'). Also supports: 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ss', or ISO 8601 with timezone (e.g., '2025-11-04T09:00:00-05:00'). When no timezone offset is specified, the time is interpreted in the macOS system timezone. Use explicit timezone offsets (e.g., '-05:00', '+09:00', 'Z') for cross-timezone clarity.",
145
+ },
146
+ endDate: {
147
+ type: 'string',
148
+ description: "End date and time. RECOMMENDED format: 'YYYY-MM-DD HH:mm:ss' (local time without timezone, e.g., '2025-11-04 10:00:00'). Also supports: 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ss', or ISO 8601 with timezone (e.g., '2025-11-04T10:00:00-05:00'). When no timezone offset is specified, the time is interpreted in the macOS system timezone. Use explicit timezone offsets (e.g., '-05:00', '+09:00', 'Z') for cross-timezone clarity.",
149
+ },
150
+ note: {
151
+ type: 'string',
152
+ description: 'Additional notes for the event.',
153
+ },
154
+ location: {
155
+ type: 'string',
156
+ description: 'Location for the event.',
157
+ },
158
+ url: {
159
+ type: 'string',
160
+ description: 'A URL to associate with the event.',
161
+ format: 'uri',
162
+ },
163
+ isAllDay: {
164
+ type: 'boolean',
165
+ description: 'Whether the event is an all-day event.',
166
+ },
167
+ targetCalendar: {
168
+ type: 'string',
169
+ description: 'The name of the calendar for create or update operations.',
170
+ },
171
+ // Recurrence properties
172
+ recurrence: {
173
+ type: 'string',
174
+ enum: ['daily', 'weekly', 'monthly', 'yearly'],
175
+ description: 'Recurrence frequency for the event (for create/update).',
176
+ },
177
+ recurrenceInterval: {
178
+ type: 'number',
179
+ description: 'How often the event recurs (e.g., 2 = every 2 days/weeks/months/years). Default: 1.',
180
+ },
181
+ recurrenceEnd: {
182
+ type: 'string',
183
+ description: "End date for recurrence in 'YYYY-MM-DD' format. Specify either recurrenceEnd or recurrenceCount, not both.",
184
+ },
185
+ recurrenceCount: {
186
+ type: 'number',
187
+ description: 'Number of occurrences for the recurrence. Specify either recurrenceEnd or recurrenceCount, not both.',
188
+ },
189
+ // Read filters
190
+ filterCalendar: {
191
+ type: 'string',
192
+ description: 'Filter events by a specific calendar name.',
193
+ },
194
+ search: {
195
+ type: 'string',
196
+ description: 'A search term to filter events by title, notes, or location.',
197
+ },
198
+ enrichContacts: {
199
+ type: 'boolean',
200
+ description: 'Reserved for future use. Attendee names are provided directly by EventKit.',
201
+ default: true,
202
+ },
203
+ },
204
+ required: ['action'],
205
+ dependentSchemas: {
206
+ action: {
207
+ oneOf: [
208
+ { properties: { action: { const: 'read' } } },
209
+ {
210
+ properties: { action: { const: 'create' } },
211
+ required: ['title', 'startDate', 'endDate'],
212
+ },
213
+ { properties: { action: { const: 'update' } }, required: ['id'] },
214
+ { properties: { action: { const: 'delete' } }, required: ['id'] },
215
+ ],
216
+ },
217
+ },
218
+ },
219
+ },
220
+ {
221
+ name: 'calendar_calendars',
222
+ description: 'Lists all available Apple Calendar collections (e.g., "Work", "Personal", "Birthdays"). Read-only. Use this to discover calendar names before creating or filtering events with the calendar_events tool. Only supports the read action.',
223
+ inputSchema: {
224
+ type: 'object',
225
+ properties: {
226
+ action: {
227
+ type: 'string',
228
+ enum: ['read'],
229
+ description: 'The operation to perform on calendars.',
230
+ },
231
+ },
232
+ required: ['action'],
233
+ dependentSchemas: {
234
+ action: {
235
+ oneOf: [{ properties: { action: { const: 'read' } } }],
236
+ },
237
+ },
238
+ },
239
+ },
240
+ {
241
+ name: 'notes_items',
242
+ description: 'Manages Apple Notes. IMPORTANT: Apple Notes uses plain text, NOT markdown — do not send markdown formatting (no **, ##, -, etc.). Title max 200 chars, body max 2000 chars (total after append). Common actions: (1) "Find my note about X" → read with search param (searches title and body). (2) "Create a note" → create with title and body (plain text only). (3) "Move note to folder X" → update with id and targetFolder param. (4) "Edit my note" → update with id, and new title/body. (5) "Add to my note" → update with id, body, and append=true (appends body to existing content without needing to read first). To append to a note by name, this is a 2-call workflow (there is no way to update by name directly): first search with { action: "read", search: "note name" } to get the note ID, then update with { action: "update", id: "...", body: "new content", append: true }. Delete moves notes to Recently Deleted. Use folder param on read to filter by folder, or on create to place in a specific folder (defaults to "Notes"). Note: updating body (with or without append) replaces rich text formatting with plain text. Title note: Apple Notes derives the displayed title from body content — this tool preserves the original title after body updates/appends. Paginated: use limit (default 50, max 200) and offset.',
243
+ inputSchema: {
244
+ type: 'object',
245
+ properties: {
246
+ action: {
247
+ type: 'string',
248
+ enum: NOTES_ACTIONS,
249
+ description: 'The operation to perform.',
250
+ },
251
+ id: {
252
+ type: 'string',
253
+ description: 'The unique identifier of the note (REQUIRED for update, delete; optional for read to get single note).',
254
+ },
255
+ title: {
256
+ type: 'string',
257
+ description: 'The title of the note (REQUIRED for create, max 200 chars).',
258
+ },
259
+ body: {
260
+ type: 'string',
261
+ description: 'The body content of the note (plain text only, max 2000 chars). Do NOT use markdown formatting — Apple Notes does not render it.',
262
+ },
263
+ folder: {
264
+ type: 'string',
265
+ description: 'The folder name — for create (defaults to Notes) or for read to filter by folder.',
266
+ },
267
+ targetFolder: {
268
+ type: 'string',
269
+ description: 'Move the note to this folder (for update action). This is how you move notes between folders — use update with id and targetFolder. Can be combined with title/body changes in the same update call.',
270
+ },
271
+ append: {
272
+ type: 'boolean',
273
+ description: 'When true, appends body content to the existing note instead of replacing it (for update action). Eliminates the need for a read-then-update round trip. The 2000 char limit applies to the final combined length. Note: appending converts existing rich text formatting to plain text.',
274
+ },
275
+ search: {
276
+ type: 'string',
277
+ description: 'A search term to filter notes by title or content.',
278
+ },
279
+ limit: {
280
+ type: 'number',
281
+ description: 'Maximum number of items to return (1-200, default 50).',
282
+ default: 50,
283
+ },
284
+ offset: {
285
+ type: 'number',
286
+ description: 'Number of items to skip for pagination (default 0).',
287
+ default: 0,
288
+ },
289
+ },
290
+ required: ['action'],
291
+ dependentSchemas: {
292
+ action: {
293
+ oneOf: [
294
+ { properties: { action: { const: 'read' } } },
295
+ {
296
+ properties: { action: { const: 'create' } },
297
+ required: ['title'],
298
+ },
299
+ { properties: { action: { const: 'update' } }, required: ['id'] },
300
+ { properties: { action: { const: 'delete' } }, required: ['id'] },
301
+ ],
302
+ },
303
+ },
304
+ },
305
+ },
306
+ {
307
+ name: 'notes_folders',
308
+ description: 'Manages Apple Notes folders. Only read and create are supported — folder renaming and deletion are NOT available through the Apple Notes API. Common actions: (1) "What folders do I have?" → read action (returns folder names and note counts). (2) "Create a folder called X" → create with name. To move a note between folders, use the notes_items tool with update action and targetFolder param. Folder name max 100 chars.',
309
+ inputSchema: {
310
+ type: 'object',
311
+ properties: {
312
+ action: {
313
+ type: 'string',
314
+ enum: NOTES_FOLDERS_ACTIONS,
315
+ description: 'The operation to perform.',
316
+ },
317
+ name: {
318
+ type: 'string',
319
+ description: 'The name of the folder to create (REQUIRED for create).',
320
+ },
321
+ },
322
+ required: ['action'],
323
+ dependentSchemas: {
324
+ action: {
325
+ oneOf: [
326
+ { properties: { action: { const: 'read' } } },
327
+ {
328
+ properties: { action: { const: 'create' } },
329
+ required: ['name'],
330
+ },
331
+ ],
332
+ },
333
+ },
334
+ },
335
+ },
336
+ {
337
+ name: 'mail_messages',
338
+ description: 'Manages Apple Mail. IMPORTANT: The create action creates a DRAFT in Mail, it does NOT send the email — the user must open Mail and click Send. To find emails from a person, use the contact parameter with their name — you do NOT need to look up their email address first. The contact param resolves names to email addresses automatically and searches across all mailboxes. This is the recommended approach for any person-based email lookup. Common actions: (1) "Show emails from John" → read with contact="John" (resolves name to emails automatically, no contacts lookup needed). (2) "Draft an email to John" → first read with contact="John" to get their email address from results, then create with to=[email]. (3) "Search for emails about X" → read with search param (searches subject, sender, and body). (4) "Read my inbox" → read action with no filters. (5) "Draft a reply" → create with replyToId (auto-populates subject, recipients, and quoted body). (6) "List mailboxes" → read with mailbox="_list". Use enrichContacts=true (default) to show sender names instead of raw email addresses. Paginated: use limit (default 50, max 200) and offset. Subject max 200 chars, body max 10000 chars. Related tools: Combine with calendar_events to find emails about upcoming events. Use contacts_people for full contact details, though the contact param here handles name-to-email resolution automatically.',
339
+ inputSchema: {
340
+ type: 'object',
341
+ properties: {
342
+ action: {
343
+ type: 'string',
344
+ enum: MAIL_ACTIONS,
345
+ description: 'The operation to perform.',
346
+ },
347
+ id: {
348
+ type: 'string',
349
+ description: 'The unique identifier of the mail message (REQUIRED for update, delete; optional for read).',
350
+ },
351
+ search: {
352
+ type: 'string',
353
+ description: 'A search term to filter messages by subject, sender, or body content.',
354
+ },
355
+ contact: {
356
+ type: 'string',
357
+ description: 'Find emails from a contact by name (partial match, case-insensitive). Looks up all email addresses for the contact and returns matching messages across all mailboxes. This is the easiest way to find emails from a specific person.',
358
+ },
359
+ enrichContacts: {
360
+ type: 'boolean',
361
+ description: 'Resolve sender email addresses to contact names (default true). Set to false to show raw email addresses.',
362
+ default: true,
363
+ },
364
+ mailbox: {
365
+ type: 'string',
366
+ description: 'Mailbox name to read from. Use "_list" to list all mailboxes.',
367
+ },
368
+ account: {
369
+ type: 'string',
370
+ description: 'Account name to scope mailbox reads (optional).',
371
+ },
372
+ limit: {
373
+ type: 'number',
374
+ description: 'Maximum number of items to return (1-200, default 50).',
375
+ default: 50,
376
+ },
377
+ offset: {
378
+ type: 'number',
379
+ description: 'Number of items to skip for pagination (default 0).',
380
+ default: 0,
381
+ },
382
+ subject: {
383
+ type: 'string',
384
+ description: 'The subject of the email (REQUIRED for create).',
385
+ },
386
+ body: {
387
+ type: 'string',
388
+ description: 'The body content of the email (REQUIRED for create).',
389
+ },
390
+ to: {
391
+ type: 'array',
392
+ items: { type: 'string' },
393
+ description: 'Array of recipient email addresses (REQUIRED for create).',
394
+ },
395
+ cc: {
396
+ type: 'array',
397
+ items: { type: 'string' },
398
+ description: 'Array of CC recipient email addresses.',
399
+ },
400
+ bcc: {
401
+ type: 'array',
402
+ items: { type: 'string' },
403
+ description: 'Array of BCC recipient email addresses.',
404
+ },
405
+ replyToId: {
406
+ type: 'string',
407
+ description: 'ID of the message to reply to. Creates a draft reply with auto-populated "Re:" subject prefix, quoted original body, and pre-filled recipients (to/cc from the original message). When replyToId is provided, subject, body, and to become optional — they will be auto-populated from the original message if omitted.',
408
+ },
409
+ read: {
410
+ type: 'boolean',
411
+ description: 'Mark message as read (true) or unread (false). For update action.',
412
+ },
413
+ },
414
+ required: ['action'],
415
+ dependentSchemas: {
416
+ action: {
417
+ oneOf: [
418
+ { properties: { action: { const: 'read' } } },
419
+ {
420
+ properties: { action: { const: 'create' } },
421
+ required: ['subject', 'body', 'to'],
422
+ },
423
+ {
424
+ properties: { action: { const: 'update' } },
425
+ required: ['id', 'read'],
426
+ },
427
+ { properties: { action: { const: 'delete' } }, required: ['id'] },
428
+ ],
429
+ },
430
+ },
431
+ },
432
+ },
433
+ {
434
+ name: 'messages_chat',
435
+ description: 'Manages Apple Messages (iMessage/SMS). Only read and create are supported — message deletion and editing are NOT available through the Apple Messages API. Common actions: (1) "Show messages from John" → read with contact param (looks up contact by name, finds all their phone numbers, and returns matching messages — this is the EASIEST way to find messages from a person, no need to look up phone numbers first). (2) "Search messages for keyword" → read with search param AND searchMessages=true (without searchMessages, search only matches chat names/participants, not message content). (3) "List my chats" → read with no params (returns chats sorted by most recent, with last message preview). (4) "Read chat history" → read with chatId (returns messages newest-first). (5) "Send a message" → create with text and either to (phone/email) or chatId. (6) "Show today\'s messages" → read with dateRange="today" (shortcuts: today, yesterday, this_week, last_7_days, last_30_days). (7) "Show messages from a specific range" → read with startDate/endDate for custom date ranges. If both dateRange and startDate/endDate are provided, explicit startDate/endDate take precedence. Use enrichContacts=true (default) to show contact names instead of raw phone numbers. Paginated: use limit (default 50, max 200) and offset. Related tools: Combine with calendar_events to cross-reference conversations with scheduled events. Use contacts_people for full contact details, though the contact param here handles name-to-phone resolution automatically.',
436
+ inputSchema: {
437
+ type: 'object',
438
+ properties: {
439
+ action: {
440
+ type: 'string',
441
+ enum: MESSAGES_ACTIONS,
442
+ description: 'The operation to perform.',
443
+ },
444
+ chatId: {
445
+ type: 'string',
446
+ description: 'The chat ID to read messages from or send to.',
447
+ },
448
+ search: {
449
+ type: 'string',
450
+ description: 'Search term to find chats by participant/name, or messages by content (when searchMessages is true).',
451
+ },
452
+ searchMessages: {
453
+ type: 'boolean',
454
+ description: 'IMPORTANT: Must be set to true when you want to search message content/text. Without this flag, search only matches chat names and participant handles. Set searchMessages=true together with search to find messages containing specific words or phrases.',
455
+ },
456
+ contact: {
457
+ type: 'string',
458
+ description: 'Find messages from a contact by name (partial match, case-insensitive). Looks up all phone numbers for the contact and returns matching messages. This is the EASIEST way to find messages from a person — no need to look up phone numbers separately.',
459
+ },
460
+ enrichContacts: {
461
+ type: 'boolean',
462
+ description: 'Resolve phone numbers to contact names in results (default true). Set to false to show raw phone numbers.',
463
+ default: true,
464
+ },
465
+ limit: {
466
+ type: 'number',
467
+ description: 'Maximum number of items to return (1-200, default 50).',
468
+ default: 50,
469
+ },
470
+ offset: {
471
+ type: 'number',
472
+ description: 'Number of items to skip for pagination (default 0).',
473
+ default: 0,
474
+ },
475
+ to: {
476
+ type: 'string',
477
+ description: 'The phone number or email to send an iMessage to (for create).',
478
+ },
479
+ text: {
480
+ type: 'string',
481
+ description: 'The message text to send (REQUIRED for create).',
482
+ },
483
+ dateRange: {
484
+ type: 'string',
485
+ enum: DATE_RANGE_SHORTCUTS,
486
+ description: "Convenience shortcut for common date ranges. Options: 'today' (since midnight), 'yesterday' (midnight to midnight), 'this_week' (since Monday midnight), 'last_7_days' (past 7 days), 'last_30_days' (past 30 days). Resolves to startDate/endDate using system local timezone. If explicit startDate/endDate are also provided, they take precedence over dateRange. Only applies to read action.",
487
+ },
488
+ startDate: {
489
+ type: 'string',
490
+ description: "Filter messages on or after this date. RECOMMENDED format: 'YYYY-MM-DD HH:mm:ss' (local time). Also supports: 'YYYY-MM-DD' or ISO 8601 (e.g., '2025-11-04T09:00:00Z'). Use with endDate for a date range, or alone for 'since date'. Takes precedence over dateRange if both provided. Only applies to read action.",
491
+ },
492
+ endDate: {
493
+ type: 'string',
494
+ description: "Filter messages on or before this date. RECOMMENDED format: 'YYYY-MM-DD HH:mm:ss' (local time). Also supports: 'YYYY-MM-DD' or ISO 8601 (e.g., '2025-11-04T17:00:00Z'). Use with startDate for a date range, or alone for 'before date'. Takes precedence over dateRange if both provided. Only applies to read action.",
495
+ },
496
+ },
497
+ required: ['action'],
498
+ dependentSchemas: {
499
+ action: {
500
+ oneOf: [
501
+ { properties: { action: { const: 'read' } } },
502
+ {
503
+ properties: { action: { const: 'create' } },
504
+ required: ['text'],
505
+ },
506
+ ],
507
+ },
508
+ },
509
+ },
510
+ },
511
+ {
512
+ name: 'contacts_people',
513
+ description: "Manages Apple Contacts. When looking for a specific person, ALWAYS use the search action with a name, email, or phone query — do not use read to browse for them. The read action returns paginated results (default 50, max 200) which may not include all contacts. If a search returns many results, ask the user follow-up questions to narrow down (e.g., last name, company, phone number) rather than listing all matches. Supports search, read, create, update, and delete actions. Related tools: Use a contact's phone with messages_chat or email with mail_messages to find their messages/emails. Both tools accept contact names directly via the contact param, so you usually don't need to look up details first.",
514
+ inputSchema: {
515
+ type: 'object',
516
+ properties: {
517
+ action: {
518
+ type: 'string',
519
+ enum: CONTACTS_ACTIONS,
520
+ description: 'The operation to perform.',
521
+ },
522
+ id: {
523
+ type: 'string',
524
+ description: 'The unique identifier of the contact (REQUIRED for update/delete; optional for read to get single contact).',
525
+ },
526
+ search: {
527
+ type: 'string',
528
+ description: 'Search term to find contacts by name, email, or phone number (REQUIRED for search action). This is the preferred way to find specific contacts — always use search instead of read when looking for a person.',
529
+ },
530
+ firstName: {
531
+ type: 'string',
532
+ description: 'First name for the contact (for create/update).',
533
+ },
534
+ lastName: {
535
+ type: 'string',
536
+ description: 'Last name for the contact (for create/update).',
537
+ },
538
+ organization: {
539
+ type: 'string',
540
+ description: 'Organization/company name (for create/update).',
541
+ },
542
+ jobTitle: {
543
+ type: 'string',
544
+ description: 'Job title (for create/update).',
545
+ },
546
+ email: {
547
+ type: 'string',
548
+ description: 'Email address (for create).',
549
+ format: 'email',
550
+ },
551
+ emailLabel: {
552
+ type: 'string',
553
+ description: 'Label for email address (e.g., "work", "home"). Default: "work".',
554
+ },
555
+ phone: {
556
+ type: 'string',
557
+ description: 'Phone number (for create).',
558
+ },
559
+ phoneLabel: {
560
+ type: 'string',
561
+ description: 'Label for phone number (e.g., "mobile", "home", "work"). Default: "mobile".',
562
+ },
563
+ street: {
564
+ type: 'string',
565
+ description: 'Street address (for create).',
566
+ },
567
+ city: {
568
+ type: 'string',
569
+ description: 'City (for create).',
570
+ },
571
+ state: {
572
+ type: 'string',
573
+ description: 'State/province (for create).',
574
+ },
575
+ zip: {
576
+ type: 'string',
577
+ description: 'ZIP/postal code (for create).',
578
+ },
579
+ country: {
580
+ type: 'string',
581
+ description: 'Country (for create).',
582
+ },
583
+ addressLabel: {
584
+ type: 'string',
585
+ description: 'Label for address (e.g., "home", "work"). Default: "home".',
586
+ },
587
+ note: {
588
+ type: 'string',
589
+ description: 'Notes for the contact (for create/update).',
590
+ },
591
+ limit: {
592
+ type: 'number',
593
+ description: 'Maximum number of items to return (1-200, default 50). Results are paginated — a full page does not mean these are all contacts. Use search to find specific people instead of paginating through read results.',
594
+ default: 50,
595
+ },
596
+ offset: {
597
+ type: 'number',
598
+ description: 'Number of items to skip for pagination (default 0).',
599
+ default: 0,
600
+ },
601
+ },
602
+ required: ['action'],
603
+ dependentSchemas: {
604
+ action: {
605
+ oneOf: [
606
+ { properties: { action: { const: 'read' } } },
607
+ {
608
+ properties: { action: { const: 'search' } },
609
+ required: ['search'],
610
+ },
611
+ {
612
+ properties: { action: { const: 'create' } },
613
+ },
614
+ {
615
+ properties: { action: { const: 'update' } },
616
+ required: ['id'],
617
+ },
618
+ {
619
+ properties: { action: { const: 'delete' } },
620
+ required: ['id'],
621
+ },
622
+ ],
623
+ },
624
+ },
625
+ },
626
+ },
627
+ ];
628
+ /**
629
+ * Export TOOLS as Tool[] for MCP server compatibility
630
+ * The dependentSchemas are preserved at runtime even though TypeScript doesn't type-check them
631
+ */
632
+ export const TOOLS = _EXTENDED_TOOLS;
633
+ //# sourceMappingURL=definitions.js.map