@node2flow/google-calendar-mcp 1.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.
package/src/tools.ts ADDED
@@ -0,0 +1,497 @@
1
+ /**
2
+ * 28 Google Calendar MCP Tool Definitions
3
+ */
4
+
5
+ import type { MCPToolDefinition } from './types.js';
6
+
7
+ export const TOOLS: MCPToolDefinition[] = [
8
+ // ========== Events (10) ==========
9
+ {
10
+ name: 'gcal_list_events',
11
+ description: 'List events on a calendar. Supports time range filtering, search query, and pagination. Use singleEvents=true to expand recurring events into individual instances.',
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar, or a specific calendar ID from gcal_list_calendars)' },
16
+ time_min: { type: 'string', description: 'Lower bound (inclusive) for event start time in RFC 3339 format (e.g., "2026-01-01T00:00:00Z")' },
17
+ time_max: { type: 'string', description: 'Upper bound (exclusive) for event end time in RFC 3339 format (e.g., "2026-12-31T23:59:59Z")' },
18
+ q: { type: 'string', description: 'Free text search query to filter events (searches summary, description, location, attendees)' },
19
+ max_results: { type: 'number', description: 'Maximum number of events to return (default: 250, max: 2500)' },
20
+ page_token: { type: 'string', description: 'Token for next page of results (from previous response nextPageToken)' },
21
+ single_events: { type: 'boolean', description: 'Expand recurring events into instances (true) or return master events (false). Required for orderBy=startTime' },
22
+ order_by: { type: 'string', description: 'Sort order: "startTime" (requires singleEvents=true) or "updated"', enum: ['startTime', 'updated'] },
23
+ time_zone: { type: 'string', description: 'Time zone for the response (e.g., "America/New_York", "Asia/Bangkok")' },
24
+ show_deleted: { type: 'boolean', description: 'Include deleted events (status=cancelled) in results' },
25
+ },
26
+ required: ['calendar_id'],
27
+ },
28
+ annotations: { title: 'List Events', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
29
+ },
30
+ {
31
+ name: 'gcal_get_event',
32
+ description: 'Get a specific event by ID. Returns full event details including attendees, reminders, recurrence, and conference data.',
33
+ inputSchema: {
34
+ type: 'object',
35
+ properties: {
36
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
37
+ event_id: { type: 'string', description: 'The event ID (from gcal_list_events)' },
38
+ time_zone: { type: 'string', description: 'Time zone for the response (e.g., "America/New_York")' },
39
+ },
40
+ required: ['calendar_id', 'event_id'],
41
+ },
42
+ annotations: { title: 'Get Event', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
43
+ },
44
+ {
45
+ name: 'gcal_create_event',
46
+ description: 'Create a new calendar event. Supports timed events (dateTime) and all-day events (date). Can add attendees, recurrence rules, reminders, and set visibility.',
47
+ inputSchema: {
48
+ type: 'object',
49
+ properties: {
50
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
51
+ summary: { type: 'string', description: 'Event title/summary' },
52
+ description: { type: 'string', description: 'Event description (supports HTML)' },
53
+ location: { type: 'string', description: 'Event location (free text or address)' },
54
+ start_date_time: { type: 'string', description: 'Start time in RFC 3339 format for timed events (e.g., "2026-03-15T10:00:00-05:00"). Mutually exclusive with start_date' },
55
+ start_date: { type: 'string', description: 'Start date for all-day events in YYYY-MM-DD format (e.g., "2026-03-15"). Mutually exclusive with start_date_time' },
56
+ start_time_zone: { type: 'string', description: 'Time zone for start time (e.g., "America/New_York"). Used with start_date_time' },
57
+ end_date_time: { type: 'string', description: 'End time in RFC 3339 format for timed events (e.g., "2026-03-15T11:00:00-05:00"). Mutually exclusive with end_date' },
58
+ end_date: { type: 'string', description: 'End date for all-day events in YYYY-MM-DD format. For single day, use next day (e.g., start=03-15, end=03-16)' },
59
+ end_time_zone: { type: 'string', description: 'Time zone for end time (e.g., "America/New_York"). Used with end_date_time' },
60
+ attendees: {
61
+ type: 'array',
62
+ description: 'Email addresses of attendees to invite',
63
+ items: { type: 'string' },
64
+ },
65
+ recurrence: {
66
+ type: 'array',
67
+ description: 'Recurrence rules in RRULE format (e.g., ["RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR", "EXDATE:20260320T100000Z"])',
68
+ items: { type: 'string' },
69
+ },
70
+ color_id: { type: 'string', description: 'Event color ID (1-11, use gcal_get_colors to see available colors)' },
71
+ visibility: { type: 'string', description: 'Event visibility', enum: ['default', 'public', 'private', 'confidential'] },
72
+ transparency: { type: 'string', description: 'Whether the event blocks time: "opaque" (busy) or "transparent" (available)', enum: ['opaque', 'transparent'] },
73
+ send_updates: { type: 'string', description: 'Who to send notifications to: "all", "externalOnly", or "none"', enum: ['all', 'externalOnly', 'none'] },
74
+ },
75
+ required: ['calendar_id'],
76
+ },
77
+ annotations: { title: 'Create Event', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
78
+ },
79
+ {
80
+ name: 'gcal_update_event',
81
+ description: 'Full update of an event (PUT). All fields are replaced — unset fields will be cleared. Use gcal_patch_event for partial updates.',
82
+ inputSchema: {
83
+ type: 'object',
84
+ properties: {
85
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
86
+ event_id: { type: 'string', description: 'The event ID to update' },
87
+ summary: { type: 'string', description: 'Event title/summary' },
88
+ description: { type: 'string', description: 'Event description' },
89
+ location: { type: 'string', description: 'Event location' },
90
+ start_date_time: { type: 'string', description: 'Start time in RFC 3339 format for timed events' },
91
+ start_date: { type: 'string', description: 'Start date for all-day events (YYYY-MM-DD)' },
92
+ start_time_zone: { type: 'string', description: 'Time zone for start time' },
93
+ end_date_time: { type: 'string', description: 'End time in RFC 3339 format for timed events' },
94
+ end_date: { type: 'string', description: 'End date for all-day events (YYYY-MM-DD)' },
95
+ end_time_zone: { type: 'string', description: 'Time zone for end time' },
96
+ attendees: {
97
+ type: 'array',
98
+ description: 'Email addresses of attendees (replaces entire attendee list)',
99
+ items: { type: 'string' },
100
+ },
101
+ recurrence: {
102
+ type: 'array',
103
+ description: 'Recurrence rules in RRULE format',
104
+ items: { type: 'string' },
105
+ },
106
+ color_id: { type: 'string', description: 'Event color ID (1-11)' },
107
+ visibility: { type: 'string', description: 'Event visibility', enum: ['default', 'public', 'private', 'confidential'] },
108
+ transparency: { type: 'string', description: 'Busy/available status', enum: ['opaque', 'transparent'] },
109
+ send_updates: { type: 'string', description: 'Who to send notifications to', enum: ['all', 'externalOnly', 'none'] },
110
+ },
111
+ required: ['calendar_id', 'event_id'],
112
+ },
113
+ annotations: { title: 'Update Event', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
114
+ },
115
+ {
116
+ name: 'gcal_patch_event',
117
+ description: 'Partial update of an event (PATCH). Only specified fields are changed — other fields remain unchanged. Preferred over update for changing individual fields.',
118
+ inputSchema: {
119
+ type: 'object',
120
+ properties: {
121
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
122
+ event_id: { type: 'string', description: 'The event ID to patch' },
123
+ summary: { type: 'string', description: 'New event title/summary' },
124
+ description: { type: 'string', description: 'New event description' },
125
+ location: { type: 'string', description: 'New event location' },
126
+ start_date_time: { type: 'string', description: 'New start time in RFC 3339 format' },
127
+ start_date: { type: 'string', description: 'New start date for all-day events (YYYY-MM-DD)' },
128
+ start_time_zone: { type: 'string', description: 'Time zone for start time' },
129
+ end_date_time: { type: 'string', description: 'New end time in RFC 3339 format' },
130
+ end_date: { type: 'string', description: 'New end date for all-day events (YYYY-MM-DD)' },
131
+ end_time_zone: { type: 'string', description: 'Time zone for end time' },
132
+ attendees: {
133
+ type: 'array',
134
+ description: 'Email addresses of attendees (replaces entire attendee list)',
135
+ items: { type: 'string' },
136
+ },
137
+ color_id: { type: 'string', description: 'Event color ID (1-11)' },
138
+ visibility: { type: 'string', description: 'Event visibility', enum: ['default', 'public', 'private', 'confidential'] },
139
+ transparency: { type: 'string', description: 'Busy/available status', enum: ['opaque', 'transparent'] },
140
+ send_updates: { type: 'string', description: 'Who to send notifications to', enum: ['all', 'externalOnly', 'none'] },
141
+ },
142
+ required: ['calendar_id', 'event_id'],
143
+ },
144
+ annotations: { title: 'Patch Event', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
145
+ },
146
+ {
147
+ name: 'gcal_delete_event',
148
+ description: 'Delete an event from the calendar. This action is irreversible.',
149
+ inputSchema: {
150
+ type: 'object',
151
+ properties: {
152
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
153
+ event_id: { type: 'string', description: 'The event ID to delete' },
154
+ send_updates: { type: 'string', description: 'Who to send cancellation notifications to', enum: ['all', 'externalOnly', 'none'] },
155
+ },
156
+ required: ['calendar_id', 'event_id'],
157
+ },
158
+ annotations: { title: 'Delete Event', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
159
+ },
160
+ {
161
+ name: 'gcal_quick_add',
162
+ description: 'Create an event from natural language text. Google Calendar parses the text to set summary, date, time, and location automatically.',
163
+ inputSchema: {
164
+ type: 'object',
165
+ properties: {
166
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
167
+ text: { type: 'string', description: 'Natural language event description (e.g., "Meeting with John tomorrow at 3pm at Starbucks", "Lunch on Friday 12-1pm")' },
168
+ send_updates: { type: 'string', description: 'Who to send notifications to', enum: ['all', 'externalOnly', 'none'] },
169
+ },
170
+ required: ['calendar_id', 'text'],
171
+ },
172
+ annotations: { title: 'Quick Add Event', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
173
+ },
174
+ {
175
+ name: 'gcal_move_event',
176
+ description: 'Move an event from one calendar to another. The event is removed from the source calendar and added to the destination.',
177
+ inputSchema: {
178
+ type: 'object',
179
+ properties: {
180
+ calendar_id: { type: 'string', description: 'Source calendar ID where the event currently exists' },
181
+ event_id: { type: 'string', description: 'The event ID to move' },
182
+ destination: { type: 'string', description: 'Destination calendar ID to move the event to' },
183
+ send_updates: { type: 'string', description: 'Who to send notifications to', enum: ['all', 'externalOnly', 'none'] },
184
+ },
185
+ required: ['calendar_id', 'event_id', 'destination'],
186
+ },
187
+ annotations: { title: 'Move Event', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
188
+ },
189
+ {
190
+ name: 'gcal_list_instances',
191
+ description: 'List individual instances of a recurring event. Returns expanded occurrences within a time range.',
192
+ inputSchema: {
193
+ type: 'object',
194
+ properties: {
195
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
196
+ event_id: { type: 'string', description: 'The recurring event ID (master event)' },
197
+ time_min: { type: 'string', description: 'Lower bound for instance start time in RFC 3339 format' },
198
+ time_max: { type: 'string', description: 'Upper bound for instance start time in RFC 3339 format' },
199
+ max_results: { type: 'number', description: 'Maximum number of instances to return' },
200
+ page_token: { type: 'string', description: 'Token for next page of results' },
201
+ time_zone: { type: 'string', description: 'Time zone for the response' },
202
+ },
203
+ required: ['calendar_id', 'event_id'],
204
+ },
205
+ annotations: { title: 'List Recurring Instances', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
206
+ },
207
+ {
208
+ name: 'gcal_import_event',
209
+ description: 'Import an event with a unique iCalUID. Used for importing events from external calendars or iCal files. Does not send notifications.',
210
+ inputSchema: {
211
+ type: 'object',
212
+ properties: {
213
+ calendar_id: { type: 'string', description: 'Calendar ID to import into (use "primary" for the main calendar)' },
214
+ ical_uid: { type: 'string', description: 'Unique iCalendar UID for the event (e.g., "event123@example.com")' },
215
+ summary: { type: 'string', description: 'Event title/summary' },
216
+ description: { type: 'string', description: 'Event description' },
217
+ location: { type: 'string', description: 'Event location' },
218
+ start_date_time: { type: 'string', description: 'Start time in RFC 3339 format for timed events' },
219
+ start_date: { type: 'string', description: 'Start date for all-day events (YYYY-MM-DD)' },
220
+ start_time_zone: { type: 'string', description: 'Time zone for start time' },
221
+ end_date_time: { type: 'string', description: 'End time in RFC 3339 format for timed events' },
222
+ end_date: { type: 'string', description: 'End date for all-day events (YYYY-MM-DD)' },
223
+ end_time_zone: { type: 'string', description: 'Time zone for end time' },
224
+ },
225
+ required: ['calendar_id', 'ical_uid'],
226
+ },
227
+ annotations: { title: 'Import Event', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
228
+ },
229
+
230
+ // ========== CalendarList (5) ==========
231
+ {
232
+ name: 'gcal_list_calendars',
233
+ description: 'List all calendars the user has subscribed to. Includes the primary calendar, other owned calendars, and calendars shared with the user.',
234
+ inputSchema: {
235
+ type: 'object',
236
+ properties: {
237
+ max_results: { type: 'number', description: 'Maximum number of calendars to return' },
238
+ page_token: { type: 'string', description: 'Token for next page of results' },
239
+ show_deleted: { type: 'boolean', description: 'Include deleted calendar entries' },
240
+ show_hidden: { type: 'boolean', description: 'Include hidden calendar entries' },
241
+ },
242
+ },
243
+ annotations: { title: 'List Calendars', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
244
+ },
245
+ {
246
+ name: 'gcal_get_calendar_entry',
247
+ description: 'Get a specific calendar list entry with display settings, color, notifications, and access role.',
248
+ inputSchema: {
249
+ type: 'object',
250
+ properties: {
251
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
252
+ },
253
+ required: ['calendar_id'],
254
+ },
255
+ annotations: { title: 'Get Calendar Entry', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
256
+ },
257
+ {
258
+ name: 'gcal_add_calendar',
259
+ description: 'Subscribe to an existing calendar by its ID. Adds the calendar to the user\'s calendar list.',
260
+ inputSchema: {
261
+ type: 'object',
262
+ properties: {
263
+ id: { type: 'string', description: 'Calendar ID to subscribe to (e.g., "user@example.com" or a group calendar ID)' },
264
+ color_id: { type: 'string', description: 'Display color ID for this calendar (use gcal_get_colors)' },
265
+ summary_override: { type: 'string', description: 'Custom display name for this calendar (overrides the calendar\'s own name)' },
266
+ hidden: { type: 'boolean', description: 'Whether to hide this calendar from the list' },
267
+ selected: { type: 'boolean', description: 'Whether events are shown by default' },
268
+ },
269
+ required: ['id'],
270
+ },
271
+ annotations: { title: 'Add Calendar', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
272
+ },
273
+ {
274
+ name: 'gcal_update_calendar_entry',
275
+ description: 'Update display settings for a calendar in the user\'s list. Changes color, display name, visibility, and default reminders.',
276
+ inputSchema: {
277
+ type: 'object',
278
+ properties: {
279
+ calendar_id: { type: 'string', description: 'Calendar ID to update settings for' },
280
+ color_id: { type: 'string', description: 'New display color ID' },
281
+ summary_override: { type: 'string', description: 'Custom display name override' },
282
+ hidden: { type: 'boolean', description: 'Whether to hide this calendar' },
283
+ selected: { type: 'boolean', description: 'Whether events are shown by default' },
284
+ default_reminders: {
285
+ type: 'array',
286
+ description: 'Default reminders for events on this calendar',
287
+ items: {
288
+ type: 'object',
289
+ properties: {
290
+ method: { type: 'string', description: 'Reminder method: "email" or "popup"' },
291
+ minutes: { type: 'number', description: 'Minutes before event to trigger reminder' },
292
+ },
293
+ },
294
+ },
295
+ },
296
+ required: ['calendar_id'],
297
+ },
298
+ annotations: { title: 'Update Calendar Entry', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
299
+ },
300
+ {
301
+ name: 'gcal_remove_calendar',
302
+ description: 'Unsubscribe from a calendar, removing it from the user\'s calendar list. Does not delete the calendar itself.',
303
+ inputSchema: {
304
+ type: 'object',
305
+ properties: {
306
+ calendar_id: { type: 'string', description: 'Calendar ID to unsubscribe from' },
307
+ },
308
+ required: ['calendar_id'],
309
+ },
310
+ annotations: { title: 'Remove Calendar', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
311
+ },
312
+
313
+ // ========== Calendars (5) ==========
314
+ {
315
+ name: 'gcal_get_calendar',
316
+ description: 'Get calendar metadata including summary, description, location, and time zone.',
317
+ inputSchema: {
318
+ type: 'object',
319
+ properties: {
320
+ calendar_id: { type: 'string', description: 'Calendar ID (use "primary" for the main calendar)' },
321
+ },
322
+ required: ['calendar_id'],
323
+ },
324
+ annotations: { title: 'Get Calendar', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
325
+ },
326
+ {
327
+ name: 'gcal_create_calendar',
328
+ description: 'Create a new secondary calendar. The authenticated user becomes the owner.',
329
+ inputSchema: {
330
+ type: 'object',
331
+ properties: {
332
+ summary: { type: 'string', description: 'Calendar name/title' },
333
+ description: { type: 'string', description: 'Calendar description' },
334
+ location: { type: 'string', description: 'Geographic location of the calendar' },
335
+ time_zone: { type: 'string', description: 'Calendar time zone (e.g., "America/New_York", "Asia/Bangkok")' },
336
+ },
337
+ required: ['summary'],
338
+ },
339
+ annotations: { title: 'Create Calendar', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
340
+ },
341
+ {
342
+ name: 'gcal_update_calendar',
343
+ description: 'Update calendar metadata (summary, description, location, time zone). Only works on secondary calendars the user owns.',
344
+ inputSchema: {
345
+ type: 'object',
346
+ properties: {
347
+ calendar_id: { type: 'string', description: 'Calendar ID to update' },
348
+ summary: { type: 'string', description: 'New calendar name/title' },
349
+ description: { type: 'string', description: 'New calendar description' },
350
+ location: { type: 'string', description: 'New geographic location' },
351
+ time_zone: { type: 'string', description: 'New time zone (e.g., "America/New_York")' },
352
+ },
353
+ required: ['calendar_id'],
354
+ },
355
+ annotations: { title: 'Update Calendar', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
356
+ },
357
+ {
358
+ name: 'gcal_delete_calendar',
359
+ description: 'Delete a secondary calendar. Only works on calendars the user owns. The primary calendar cannot be deleted.',
360
+ inputSchema: {
361
+ type: 'object',
362
+ properties: {
363
+ calendar_id: { type: 'string', description: 'Calendar ID to delete (cannot be "primary")' },
364
+ },
365
+ required: ['calendar_id'],
366
+ },
367
+ annotations: { title: 'Delete Calendar', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
368
+ },
369
+ {
370
+ name: 'gcal_clear_calendar',
371
+ description: 'Delete all events from a primary calendar. Only works on the primary calendar. Secondary calendars should use gcal_delete_calendar instead.',
372
+ inputSchema: {
373
+ type: 'object',
374
+ properties: {
375
+ calendar_id: { type: 'string', description: 'Calendar ID to clear (typically "primary")' },
376
+ },
377
+ required: ['calendar_id'],
378
+ },
379
+ annotations: { title: 'Clear Calendar', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
380
+ },
381
+
382
+ // ========== ACL (5) ==========
383
+ {
384
+ name: 'gcal_list_acl',
385
+ description: 'List access control rules for a calendar. Shows who has access and their permission level.',
386
+ inputSchema: {
387
+ type: 'object',
388
+ properties: {
389
+ calendar_id: { type: 'string', description: 'Calendar ID to list ACL rules for' },
390
+ max_results: { type: 'number', description: 'Maximum number of rules to return' },
391
+ page_token: { type: 'string', description: 'Token for next page of results' },
392
+ show_deleted: { type: 'boolean', description: 'Include deleted ACL rules' },
393
+ },
394
+ required: ['calendar_id'],
395
+ },
396
+ annotations: { title: 'List ACL Rules', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
397
+ },
398
+ {
399
+ name: 'gcal_get_acl',
400
+ description: 'Get a specific access control rule by rule ID.',
401
+ inputSchema: {
402
+ type: 'object',
403
+ properties: {
404
+ calendar_id: { type: 'string', description: 'Calendar ID' },
405
+ rule_id: { type: 'string', description: 'ACL rule ID (e.g., "user:user@example.com")' },
406
+ },
407
+ required: ['calendar_id', 'rule_id'],
408
+ },
409
+ annotations: { title: 'Get ACL Rule', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
410
+ },
411
+ {
412
+ name: 'gcal_create_acl',
413
+ description: 'Share a calendar with a user, group, or domain by creating an access control rule.',
414
+ inputSchema: {
415
+ type: 'object',
416
+ properties: {
417
+ calendar_id: { type: 'string', description: 'Calendar ID to share' },
418
+ role: { type: 'string', description: 'Permission level for the grantee', enum: ['none', 'freeBusyReader', 'reader', 'writer', 'owner'] },
419
+ scope_type: { type: 'string', description: 'Type of the grantee: "user", "group", "domain", or "default" (public)', enum: ['user', 'group', 'domain', 'default'] },
420
+ scope_value: { type: 'string', description: 'Email address (user/group) or domain name. Not required for scope_type="default"' },
421
+ send_notifications: { type: 'boolean', description: 'Send notification email to the grantee (default: true)' },
422
+ },
423
+ required: ['calendar_id', 'role', 'scope_type'],
424
+ },
425
+ annotations: { title: 'Create ACL Rule', readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
426
+ },
427
+ {
428
+ name: 'gcal_update_acl',
429
+ description: 'Update the permission level of an existing access control rule.',
430
+ inputSchema: {
431
+ type: 'object',
432
+ properties: {
433
+ calendar_id: { type: 'string', description: 'Calendar ID' },
434
+ rule_id: { type: 'string', description: 'ACL rule ID to update (e.g., "user:user@example.com")' },
435
+ role: { type: 'string', description: 'New permission level', enum: ['none', 'freeBusyReader', 'reader', 'writer', 'owner'] },
436
+ send_notifications: { type: 'boolean', description: 'Send notification about the change' },
437
+ },
438
+ required: ['calendar_id', 'rule_id', 'role'],
439
+ },
440
+ annotations: { title: 'Update ACL Rule', readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
441
+ },
442
+ {
443
+ name: 'gcal_delete_acl',
444
+ description: 'Remove an access control rule, revoking the grantee\'s access to the calendar.',
445
+ inputSchema: {
446
+ type: 'object',
447
+ properties: {
448
+ calendar_id: { type: 'string', description: 'Calendar ID' },
449
+ rule_id: { type: 'string', description: 'ACL rule ID to delete (e.g., "user:user@example.com")' },
450
+ },
451
+ required: ['calendar_id', 'rule_id'],
452
+ },
453
+ annotations: { title: 'Delete ACL Rule', readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true },
454
+ },
455
+
456
+ // ========== Utility (3) ==========
457
+ {
458
+ name: 'gcal_query_freebusy',
459
+ description: 'Check availability (free/busy) for one or more calendars within a time range. Useful for finding meeting times.',
460
+ inputSchema: {
461
+ type: 'object',
462
+ properties: {
463
+ time_min: { type: 'string', description: 'Start of the time range in RFC 3339 format (e.g., "2026-03-15T08:00:00Z")' },
464
+ time_max: { type: 'string', description: 'End of the time range in RFC 3339 format (e.g., "2026-03-15T18:00:00Z")' },
465
+ time_zone: { type: 'string', description: 'Time zone for the response (e.g., "America/New_York")' },
466
+ calendar_ids: {
467
+ type: 'array',
468
+ description: 'Calendar IDs to check availability for (e.g., ["primary", "user@example.com"])',
469
+ items: { type: 'string' },
470
+ },
471
+ },
472
+ required: ['time_min', 'time_max', 'calendar_ids'],
473
+ },
474
+ annotations: { title: 'Query Free/Busy', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
475
+ },
476
+ {
477
+ name: 'gcal_get_colors',
478
+ description: 'Get the color palette for calendars and events. Returns color IDs that can be used with gcal_create_event and gcal_update_calendar_entry.',
479
+ inputSchema: {
480
+ type: 'object',
481
+ properties: {},
482
+ },
483
+ annotations: { title: 'Get Colors', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
484
+ },
485
+ {
486
+ name: 'gcal_list_settings',
487
+ description: 'List all user settings for Google Calendar (locale, timezone, date format, week start, etc.).',
488
+ inputSchema: {
489
+ type: 'object',
490
+ properties: {
491
+ max_results: { type: 'number', description: 'Maximum number of settings to return' },
492
+ page_token: { type: 'string', description: 'Token for next page of results' },
493
+ },
494
+ },
495
+ annotations: { title: 'List Settings', readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true },
496
+ },
497
+ ];