@chronary/toolkit 1.0.1 → 1.2.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/dist/index.js CHANGED
@@ -107,72 +107,94 @@ __export(schemas_exports, {
107
107
  UpdateWebhookSchema: () => UpdateWebhookSchema
108
108
  });
109
109
  import { z } from "zod";
110
+ var WEBHOOK_EVENT_TYPES = [
111
+ "agent.created",
112
+ "agent.updated",
113
+ "event.created",
114
+ "event.updated",
115
+ "event.deleted",
116
+ "event.started",
117
+ "event.ended",
118
+ "event.reminder",
119
+ "event.hold_created",
120
+ "event.hold_expired",
121
+ "event.hold_released",
122
+ "event.hold_confirmed",
123
+ "proposal.created",
124
+ "proposal.responded",
125
+ "proposal.confirmed",
126
+ "proposal.expired",
127
+ "proposal.cancelled",
128
+ "webhook.deactivated"
129
+ ];
130
+ var WEBHOOK_DELIVERY_STATUSES = ["pending", "delivered", "failed"];
110
131
  var ListCalendarsSchema = z.object({
111
- agent_id: z.string().optional().describe("Filter calendars by agent ID"),
112
- include: z.enum(["all"]).optional().describe('Set to "all" to include soft-deleted calendars'),
113
- limit: z.number().int().min(1).max(200).optional().describe("Max results per page (default 50)"),
114
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)")
132
+ agent_id: z.string().optional().describe("Filter to calendars owned by this agent. Org keys only \u2014 agent-scoped keys are always limited to their own agent and ignore this."),
133
+ include: z.enum(["all"]).optional().describe('Pass "all" to include calendars across all agents (org keys only)'),
134
+ limit: z.number().int().min(1).max(200).default(50).describe("Max results to return"),
135
+ offset: z.number().int().min(0).default(0).describe("Pagination offset")
115
136
  });
116
137
  var GetCalendarSchema = z.object({
117
- calendar_id: z.string().describe("The calendar ID to retrieve")
138
+ calendar_id: z.string().describe("Calendar ID to fetch")
118
139
  });
119
140
  var CreateCalendarSchema = z.object({
120
- name: z.string().describe("Calendar name"),
121
- timezone: z.string().describe('IANA timezone (e.g., "America/New_York")'),
122
- agent_id: z.string().optional().describe("Agent ID to associate the calendar with"),
123
- default_reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Default reminder offsets in minutes before start, inherited by events that don't set their own (e.g. [10, 1440]). null/omit = system default (10 min); [] = no reminders. Max 5, each 1\u201340320."),
124
- metadata: z.record(z.string(), z.unknown()).optional().describe("Arbitrary key-value metadata")
141
+ name: z.string().min(1).max(255).describe("Calendar name"),
142
+ agent_id: z.string().optional().describe("Agent ID to own this calendar (omit for org-level)"),
143
+ timezone: z.string().min(1).describe("IANA timezone (e.g. America/New_York)"),
144
+ default_reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Default reminder offsets in minutes before start, inherited by events on this calendar that don't set their own. Omit or null to use the system default (10 min); [] for no reminders.")
125
145
  });
126
146
  var UpdateCalendarSchema = z.object({
127
- calendar_id: z.string().describe("The calendar ID to update"),
128
- name: z.string().optional().describe("New calendar name"),
129
- timezone: z.string().optional().describe("New IANA timezone"),
130
- default_reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("New default reminder offsets in minutes before start. null = system default (10 min); [] = no reminders. Max 5, each 1\u201340320."),
131
- metadata: z.record(z.string(), z.unknown()).optional().describe("Updated metadata")
147
+ calendar_id: z.string().describe("Calendar ID to update"),
148
+ name: z.string().min(1).max(255).optional().describe("New calendar name"),
149
+ timezone: z.string().min(1).optional().describe("New IANA timezone (e.g. America/New_York)"),
150
+ agent_status: z.enum(["idle", "working", "waiting", "error"]).optional().describe("Owning agent's status"),
151
+ default_reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Default reminder offsets in minutes; null for system default, [] for none"),
152
+ metadata: z.record(z.string(), z.unknown()).optional().describe("Arbitrary metadata (max 16KB)")
132
153
  });
133
154
  var DeleteCalendarSchema = z.object({
134
- calendar_id: z.string().describe("The calendar ID to delete")
155
+ calendar_id: z.string().describe("Calendar ID to delete")
135
156
  });
136
157
  var ListEventsSchema = z.object({
137
- calendar_id: z.string().optional().describe("Calendar ID to list events from (provide this or agent_id)"),
138
- agent_id: z.string().optional().describe("Agent ID to list events for (provide this or calendar_id)"),
139
- start_after: z.string().optional().describe("Only events starting after this ISO 8601 datetime"),
140
- start_before: z.string().optional().describe("Only events starting before this ISO 8601 datetime"),
141
- status: z.enum(["confirmed", "tentative", "cancelled"]).optional().describe("Filter by event status"),
142
- source: z.enum(["internal", "external_ical"]).optional().describe("Filter by event source"),
143
- limit: z.number().int().min(1).max(200).optional().describe("Max results per page (default 50)"),
144
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)")
158
+ calendar_id: z.string().optional().describe("Calendar ID to list events from. Provide this or agent_id."),
159
+ agent_id: z.string().optional().describe("Agent ID to list events for across all of the agent's calendars. Provide this or calendar_id."),
160
+ start_after: z.string().datetime().optional().describe("Only events starting after this ISO 8601 time"),
161
+ start_before: z.string().datetime().optional().describe("Only events starting before this ISO 8601 time"),
162
+ status: z.enum(["confirmed", "tentative", "cancelled", "hold"]).optional().describe("Filter by event status"),
163
+ source: z.enum(["internal", "external_ical"]).optional().describe('Filter by source: "internal" (created via the API) or "external_ical" (synced from an iCal subscription)'),
164
+ limit: z.number().int().min(1).max(200).default(50).describe("Max results to return"),
165
+ offset: z.number().int().min(0).default(0).describe("Pagination offset")
145
166
  });
146
167
  var GetEventSchema = z.object({
147
- calendar_id: z.string().describe("Calendar ID the event belongs to"),
148
- event_id: z.string().describe("The event ID to retrieve")
168
+ event_id: z.string().describe("Event ID to retrieve"),
169
+ calendar_id: z.string().optional().describe("Calendar ID that owns the event. Optional \u2014 if omitted the calendar is resolved from the event.")
149
170
  });
150
171
  var CreateEventSchema = z.object({
151
- calendar_id: z.string().describe("Calendar ID to create the event on"),
152
- title: z.string().describe("Event title"),
153
- start_time: z.string().describe("Start time in ISO 8601 format"),
154
- end_time: z.string().describe("End time in ISO 8601 format"),
155
- description: z.string().optional().describe("Event description"),
156
- all_day: z.boolean().optional().describe("Whether this is an all-day event"),
157
- status: z.enum(["confirmed", "tentative", "cancelled"]).optional().describe('Event status (default "confirmed")'),
158
- reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Reminder offsets in minutes before start (e.g. [10, 1440]). Each fires an event.reminder webhook. null/omit = inherit calendar default (then 10 min); [] = no reminders. Max 5, each 1\u201340320."),
159
- metadata: z.record(z.string(), z.unknown()).optional().describe("Arbitrary key-value metadata")
172
+ calendar_id: z.string().describe("Calendar ID to add the event to"),
173
+ title: z.string().min(1).max(500).describe("Event title"),
174
+ start_time: z.string().datetime().describe("Start time (ISO 8601)"),
175
+ end_time: z.string().datetime().describe("End time (ISO 8601)"),
176
+ description: z.string().optional().describe("Optional event description"),
177
+ all_day: z.boolean().default(false).describe("Whether this is an all-day event"),
178
+ status: z.enum(["confirmed", "tentative", "hold"]).optional().describe('Event status. "hold" creates a tentative reservation that auto-expires at hold_expires_at. Defaults to "confirmed".'),
179
+ reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Reminder offsets in minutes before start_time (e.g. [10, 1440]). Each fires an event.reminder webhook and shows as an alarm in the iCal feed. Omit or null to inherit the calendar default (then the system default of 10 min); [] for no reminders."),
180
+ hold_expires_at: z.string().datetime().optional().describe('Required when status="hold". ISO 8601 timestamp 30s-15min in the future. Auto-releases the hold when reached.'),
181
+ hold_priority: z.number().int().min(0).max(100).optional().describe('Only valid with status="hold". Higher-priority overlapping holds pre-empt lower-priority ones. Defaults to 0.')
160
182
  });
161
183
  var UpdateEventSchema = z.object({
162
- calendar_id: z.string().describe("Calendar ID the event belongs to"),
163
- event_id: z.string().describe("The event ID to update"),
164
- title: z.string().optional().describe("New event title"),
165
- description: z.string().nullable().optional().describe("New description (null to clear)"),
166
- start_time: z.string().optional().describe("New start time in ISO 8601 format"),
167
- end_time: z.string().optional().describe("New end time in ISO 8601 format"),
184
+ event_id: z.string().describe("Event ID to update"),
185
+ calendar_id: z.string().optional().describe("Calendar ID that owns the event. Optional \u2014 if omitted the calendar is resolved from the event."),
186
+ title: z.string().min(1).max(500).optional().describe("New event title"),
187
+ description: z.string().nullable().optional().describe("New description, or null to clear it"),
188
+ start_time: z.string().datetime().optional().describe("New start time (ISO 8601)"),
189
+ end_time: z.string().datetime().optional().describe("New end time (ISO 8601)"),
168
190
  all_day: z.boolean().optional().describe("Whether this is an all-day event"),
169
191
  status: z.enum(["confirmed", "tentative", "cancelled"]).optional().describe("New event status"),
170
- reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("New reminder offsets in minutes before start. null = inherit calendar default; [] = no reminders. Max 5, each 1\u201340320."),
171
- metadata: z.record(z.string(), z.unknown()).optional().describe("Updated metadata")
192
+ metadata: z.record(z.string(), z.unknown()).optional().describe("Replacement metadata object"),
193
+ reminders: z.array(z.number().int().min(1).max(40320)).max(5).nullable().optional().describe("Reminder offsets in minutes before start_time. Omit to leave unchanged, null to inherit the calendar default, [] for no reminders.")
172
194
  });
173
195
  var CancelEventSchema = z.object({
174
- calendar_id: z.string().describe("Calendar ID that owns the event"),
175
- event_id: z.string().describe("Event ID to cancel")
196
+ event_id: z.string().describe("Event ID to cancel"),
197
+ calendar_id: z.string().optional().describe("Calendar ID that owns the event. Optional \u2014 if omitted the calendar is resolved from the event. Matches the asymmetry with confirm_event / release_event which never required this arg.")
176
198
  });
177
199
  var ConfirmEventSchema = z.object({
178
200
  event_id: z.string().describe("Event ID of the hold to confirm")
@@ -183,14 +205,13 @@ var ReleaseEventSchema = z.object({
183
205
  var CreateAgentSchema = z.object({
184
206
  name: z.string().min(1).max(255).describe("Display name for the agent"),
185
207
  type: z.enum(["ai", "human", "resource"]).describe("Agent type"),
186
- description: z.string().optional().describe("Optional description"),
187
- metadata: z.record(z.string(), z.unknown()).optional().describe("Arbitrary key-value metadata")
208
+ description: z.string().optional().describe("Optional description")
188
209
  });
189
210
  var ListAgentsSchema = z.object({
190
211
  type: z.enum(["ai", "human", "resource"]).optional().describe("Filter by agent type"),
191
212
  status: z.enum(["active", "paused", "decommissioned"]).optional().describe("Filter by status"),
192
- limit: z.number().int().min(1).max(200).optional().describe("Max results per page (default 50)"),
193
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)")
213
+ limit: z.number().int().min(1).max(200).default(50).describe("Max results to return"),
214
+ offset: z.number().int().min(0).default(0).describe("Pagination offset")
194
215
  });
195
216
  var GetAgentSchema = z.object({
196
217
  agent_id: z.string().describe("Agent ID to fetch")
@@ -207,27 +228,32 @@ var DeleteAgentSchema = z.object({
207
228
  });
208
229
  var GetAvailabilitySchema = z.object({
209
230
  agent_id: z.string().describe("Agent ID to check availability for"),
210
- start: z.string().describe("Range start (ISO 8601)"),
211
- end: z.string().describe("Range end (ISO 8601)"),
212
- slot_duration: z.enum(["15m", "30m", "45m", "1h", "2h"]).optional().describe('Minimum slot duration required (default "30m")'),
213
- include_busy: z.boolean().optional().describe("Include busy blocks in response")
231
+ start: z.string().datetime().optional().describe("Range start (ISO 8601). Alias: start_time."),
232
+ end: z.string().datetime().optional().describe("Range end (ISO 8601). Alias: end_time."),
233
+ start_time: z.string().datetime().optional().describe("Alias for `start` (matches REST events naming)."),
234
+ end_time: z.string().datetime().optional().describe("Alias for `end` (matches REST events naming)."),
235
+ slot_duration: z.enum(["15m", "30m", "45m", "1h", "2h"]).default("30m").describe("Minimum slot duration required \u2014 only free blocks at least this long are returned"),
236
+ include_busy: z.boolean().default(false).describe("Include busy blocks in response")
214
237
  });
215
238
  var FindMeetingTimeSchema = z.object({
216
- agents: z.array(z.string()).min(1).describe("Array of agent IDs to find common free time for. All agents must be free during the returned slots."),
217
- start: z.string().describe("Search range start (ISO 8601)"),
218
- end: z.string().describe("Search range end (ISO 8601)"),
219
- slot_duration: z.enum(["15m", "30m", "45m", "1h", "2h"]).optional().describe('Minimum slot duration required (default "30m")'),
239
+ agents: z.array(z.string()).min(1).optional().describe("Array of agent IDs to find common free time for. All agents must be free during the returned slots. Alias: agent_ids."),
240
+ agent_ids: z.array(z.string()).min(1).optional().describe("Alias for `agents` (matches REST/scheduling-proposal naming)."),
241
+ start: z.string().datetime().optional().describe("Search range start (ISO 8601). Alias: start_time."),
242
+ end: z.string().datetime().optional().describe("Search range end (ISO 8601). Alias: end_time."),
243
+ start_time: z.string().datetime().optional().describe("Alias for `start` (matches REST events naming)."),
244
+ end_time: z.string().datetime().optional().describe("Alias for `end` (matches REST events naming)."),
245
+ slot_duration: z.enum(["15m", "30m", "45m", "1h", "2h"]).default("30m").describe("Minimum slot duration required \u2014 only free blocks at least this long are returned"),
220
246
  calendars: z.array(z.string()).optional().describe("Additional shared calendar IDs to treat as busy"),
221
- include_busy: z.boolean().optional().describe("Include per-agent busy blocks in response")
247
+ include_busy: z.boolean().default(false).describe("Include per-agent busy blocks in response")
222
248
  });
223
249
  var GetCalendarContextSchema = z.object({
224
250
  calendar_id: z.string().describe("Calendar ID")
225
251
  });
226
252
  var proposalSlotSchema = z.object({
227
- start_time: z.string().describe("Slot start (ISO 8601)"),
228
- end_time: z.string().describe("Slot end (ISO 8601)"),
229
- weight: z.number().min(0).max(10).optional().describe("Preference weight (default 1.0)"),
230
- calendar_id: z.string().optional().describe("Override calendar for this slot")
253
+ start_time: z.string().datetime(),
254
+ end_time: z.string().datetime(),
255
+ weight: z.number().min(0).max(10).default(1).optional(),
256
+ calendar_id: z.string().optional()
231
257
  });
232
258
  var CreateProposalSchema = z.object({
233
259
  title: z.string().min(1).max(500).describe("Short description of what the meeting is about"),
@@ -236,7 +262,7 @@ var CreateProposalSchema = z.object({
236
262
  participant_agent_ids: z.array(z.string()).min(1).max(50).describe("Agent IDs invited to respond"),
237
263
  calendar_id: z.string().describe("Calendar the resolved event will be created on"),
238
264
  slots: z.array(proposalSlotSchema).min(1).max(20).describe("Candidate time slots (up to 20)"),
239
- expires_at: z.string().optional().describe("Auto-cancel cutoff if unresolved (ISO 8601)")
265
+ expires_at: z.string().datetime().optional().describe("Auto-cancel cutoff if unresolved")
240
266
  });
241
267
  var ListProposalsSchema = z.object({
242
268
  status: z.enum(["pending", "confirmed", "expired", "cancelled"]).optional().describe("Filter by proposal status"),
@@ -261,10 +287,11 @@ var ResolveProposalSchema = z.object({
261
287
  var CancelProposalSchema = z.object({
262
288
  proposal_id: z.string().describe("Proposal to cancel")
263
289
  });
290
+ var timeOfDay = z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "must be HH:MM in 24-hour time");
264
291
  var workingHoursDaySchema = z.object({
265
- start: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "must be HH:MM in 24-hour time"),
266
- end: z.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/, "must be HH:MM in 24-hour time")
267
- });
292
+ start: timeOfDay,
293
+ end: timeOfDay
294
+ }).refine((v) => v.end > v.start, "end must be after start").describe("A single day's working hours window");
268
295
  var workingHoursSchema = z.object({
269
296
  mon: workingHoursDaySchema.optional(),
270
297
  tue: workingHoursDaySchema.optional(),
@@ -273,13 +300,13 @@ var workingHoursSchema = z.object({
273
300
  fri: workingHoursDaySchema.optional(),
274
301
  sat: workingHoursDaySchema.optional(),
275
302
  sun: workingHoursDaySchema.optional()
276
- }).nullable();
303
+ }).refine((v) => Object.keys(v).length > 0, "at least one day must be specified").nullable();
277
304
  var SetAvailabilityRulesSchema = z.object({
278
305
  calendar_id: z.string().describe("Calendar to configure"),
279
- buffer_before_minutes: z.number().int().min(0).max(120).optional().describe("Minutes of buffer before each event (0\u2013120)"),
280
- buffer_after_minutes: z.number().int().min(0).max(120).optional().describe("Minutes of buffer after each event (0\u2013120)"),
281
- working_hours: workingHoursSchema.optional().describe("Per-day working hours map in the calendar's timezone; omit keys for off-days. Pass null to remove any working-hours constraint."),
282
- timezone: z.string().min(1).max(64).optional().describe("IANA timezone used to interpret working_hours (e.g. America/New_York)")
306
+ buffer_before_minutes: z.number().int().min(0).max(120).default(0).describe("Minutes of buffer before each event (0\u2013120)"),
307
+ buffer_after_minutes: z.number().int().min(0).max(120).default(0).describe("Minutes of buffer after each event (0\u2013120)"),
308
+ working_hours: workingHoursSchema.default(null).describe("Per-day working hours map in the calendar's timezone; omit keys for off-days. Pass null to remove any working-hours constraint."),
309
+ timezone: z.string().min(1).max(64).default("UTC").describe("IANA timezone used to interpret working_hours (e.g. America/New_York)")
283
310
  });
284
311
  var GetAvailabilityRulesSchema = z.object({
285
312
  calendar_id: z.string().describe("Calendar to read")
@@ -296,8 +323,8 @@ var RevokeScopedKeySchema = z.object({
296
323
  key_id: z.string().describe("ID of the scoped key to revoke")
297
324
  });
298
325
  var GetAuditLogSchema = z.object({
299
- from: z.string().optional().describe("Start of the window (ISO 8601). Silently clamped to the plan retention window if older."),
300
- to: z.string().optional().describe("End of the window (ISO 8601)"),
326
+ from: z.string().datetime({ offset: true }).optional().describe("Start of the window (ISO 8601). Silently clamped to the plan retention window if older."),
327
+ to: z.string().datetime({ offset: true }).optional().describe("End of the window (ISO 8601)"),
301
328
  action: z.string().min(1).max(64).optional().describe("Filter by action name (e.g. event.created)"),
302
329
  actor_key_prefix: z.string().min(1).max(32).optional().describe("Filter by the API key prefix that performed the action"),
303
330
  cursor: z.string().min(1).max(256).optional().describe("Opaque pagination cursor from a previous response"),
@@ -307,33 +334,40 @@ var AcceptTermsSchema = z.object({
307
334
  tos_version: z.string().min(1).describe("The terms-of-service version to accept; must match the current version")
308
335
  });
309
336
  var ListWebhooksSchema = z.object({
310
- limit: z.number().int().min(1).max(100).optional().describe("Max results per page (default 20)"),
311
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)")
337
+ limit: z.number().int().min(1).max(100).default(20).describe("Max results to return"),
338
+ offset: z.number().int().min(0).default(0).describe("Pagination offset")
312
339
  });
313
340
  var GetWebhookSchema = z.object({
314
- webhook_id: z.string().describe("The webhook ID to retrieve")
341
+ webhook_id: z.string().describe("Webhook subscription to fetch")
315
342
  });
316
343
  var CreateWebhookSchema = z.object({
317
- url: z.string().describe("HTTPS URL to receive webhook payloads"),
318
- events: z.array(z.string()).describe('Event types to subscribe to (e.g., ["event.created", "event.updated"])')
344
+ url: z.string().url().describe("HTTPS endpoint that will receive event deliveries"),
345
+ events: z.array(z.enum(WEBHOOK_EVENT_TYPES)).min(1).describe("Event types to subscribe to")
319
346
  });
320
347
  var UpdateWebhookSchema = z.object({
321
- webhook_id: z.string().describe("The webhook ID to update"),
322
- url: z.string().optional().describe("New webhook URL"),
323
- events: z.array(z.string()).optional().describe("New event type subscriptions"),
324
- active: z.boolean().optional().describe("Enable or disable the webhook")
348
+ webhook_id: z.string().describe("Webhook subscription to update"),
349
+ url: z.string().url().optional().describe("New HTTPS delivery endpoint"),
350
+ events: z.array(z.enum(WEBHOOK_EVENT_TYPES)).min(1).optional().describe("Replacement set of event types to subscribe to"),
351
+ active: z.boolean().optional().describe("Set false to pause deliveries, true to resume")
325
352
  });
326
353
  var DeleteWebhookSchema = z.object({
327
- webhook_id: z.string().describe("The webhook ID to delete")
354
+ webhook_id: z.string().describe("Webhook subscription to delete")
355
+ });
356
+ var ListWebhookDeliveriesSchema = z.object({
357
+ webhook_id: z.string().describe("Webhook subscription whose deliveries to list"),
358
+ limit: z.number().int().min(1).max(100).default(20).describe("Max results to return"),
359
+ offset: z.number().int().min(0).default(0).describe("Pagination offset"),
360
+ status: z.enum(WEBHOOK_DELIVERY_STATUSES).optional().describe("Filter to a single delivery status"),
361
+ include_payload: z.boolean().optional().describe("Include the full event payload sent on each delivery")
328
362
  });
329
363
  var ListICalSubscriptionsSchema = z.object({
330
- agent_id: z.string().describe("Agent ID to list subscriptions for"),
364
+ agent_id: z.string().describe("Agent ID whose iCal subscriptions to list"),
331
365
  status: z.enum(["active", "error", "paused"]).optional().describe("Filter by subscription status"),
332
- limit: z.number().int().min(1).max(200).optional().describe("Max results per page (default 50)"),
333
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)")
366
+ limit: z.number().int().min(1).max(200).default(50).describe("Max results to return"),
367
+ offset: z.number().int().min(0).default(0).describe("Pagination offset")
334
368
  });
335
369
  var GetICalSubscriptionSchema = z.object({
336
- subscription_id: z.string().describe("The iCal subscription ID to retrieve")
370
+ subscription_id: z.string().describe("iCal subscription ID to fetch")
337
371
  });
338
372
  var SubscribeICalSchema = z.object({
339
373
  agent_id: z.string().describe("Agent ID that will own this subscription"),
@@ -341,23 +375,16 @@ var SubscribeICalSchema = z.object({
341
375
  url: z.string().url().describe("HTTPS URL of the iCal feed (.ics) to subscribe to"),
342
376
  label: z.string().optional().describe("Optional label for this subscription")
343
377
  });
344
- var ListWebhookDeliveriesSchema = z.object({
345
- webhook_id: z.string().describe("Webhook subscription whose deliveries to list"),
346
- limit: z.number().int().min(1).max(100).optional().describe("Max results to return (default 20)"),
347
- offset: z.number().int().min(0).optional().describe("Pagination offset (default 0)"),
348
- status: z.enum(["pending", "delivered", "failed"]).optional().describe("Filter to a single delivery status"),
349
- include_payload: z.boolean().optional().describe("Include the full event payload sent on each delivery")
350
- });
351
378
  var UpdateICalSubscriptionSchema = z.object({
352
- subscription_id: z.string().describe("The iCal subscription ID to update"),
353
- label: z.string().optional().describe("New label"),
354
- url: z.string().optional().describe("New iCal feed URL")
379
+ subscription_id: z.string().describe("iCal subscription ID to update"),
380
+ label: z.string().min(1).max(255).optional().describe("New label for this subscription"),
381
+ url: z.string().url().startsWith("https://", "URL must use HTTPS").optional().describe("New HTTPS URL of the iCal feed (.ics)")
355
382
  });
356
383
  var DeleteICalSubscriptionSchema = z.object({
357
- subscription_id: z.string().describe("The iCal subscription ID to delete")
384
+ subscription_id: z.string().describe("iCal subscription ID to delete")
358
385
  });
359
386
  var SyncICalSubscriptionSchema = z.object({
360
- subscription_id: z.string().describe("The iCal subscription ID to sync immediately")
387
+ subscription_id: z.string().describe("iCal subscription ID to sync")
361
388
  });
362
389
  var GetUsageSchema = z.object({});
363
390
 
@@ -414,6 +441,9 @@ var deleteCalendar = safeFunc(async (ctx) => {
414
441
  });
415
442
  var listEvents = safeFunc(async (ctx) => {
416
443
  const { client, params } = ctx;
444
+ if (!params.calendar_id && !params.agent_id) {
445
+ throw new Error("Provide calendar_id or agent_id");
446
+ }
417
447
  const iter = client.events.list({
418
448
  calendarId: params.calendar_id,
419
449
  agentId: params.agent_id,
@@ -426,7 +456,8 @@ var listEvents = safeFunc(async (ctx) => {
426
456
  return fetchPage(iter, params.offset, params.limit);
427
457
  });
428
458
  var getEvent = safeFunc(async (ctx) => {
429
- return ctx.client.events.get(ctx.params.calendar_id, ctx.params.event_id);
459
+ const { calendar_id, event_id } = ctx.params;
460
+ return calendar_id ? ctx.client.events.get(calendar_id, event_id) : ctx.client.events.getById(event_id);
430
461
  });
431
462
  var createEvent = safeFunc(async (ctx) => {
432
463
  const { client, params } = ctx;
@@ -436,10 +467,15 @@ var createEvent = safeFunc(async (ctx) => {
436
467
  var updateEvent = safeFunc(async (ctx) => {
437
468
  const { client, params } = ctx;
438
469
  const { calendar_id, event_id, ...updates } = params;
439
- return client.events.update(calendar_id, event_id, updates);
470
+ return calendar_id ? client.events.update(calendar_id, event_id, updates) : client.events.updateById(event_id, updates);
440
471
  });
441
472
  var cancelEvent = safeFunc(async (ctx) => {
442
- await ctx.client.events.delete(ctx.params.calendar_id, ctx.params.event_id);
473
+ const { calendar_id, event_id } = ctx.params;
474
+ if (calendar_id) {
475
+ await ctx.client.events.delete(calendar_id, event_id);
476
+ } else {
477
+ await ctx.client.events.deleteById(event_id);
478
+ }
443
479
  return void 0;
444
480
  });
445
481
  var confirmEvent = safeFunc(async (ctx) => {
@@ -470,15 +506,34 @@ var deleteAgent = safeFunc(async (ctx) => {
470
506
  });
471
507
  var getAvailability = safeFunc(async (ctx) => {
472
508
  const { client, params } = ctx;
509
+ const start = params.start ?? params.start_time;
510
+ const end = params.end ?? params.end_time;
511
+ if (!start || !end) {
512
+ throw new Error("start (or start_time) and end (or end_time) are required");
513
+ }
473
514
  return client.availability.forAgent(params.agent_id, {
474
- start: params.start,
475
- end: params.end,
515
+ start,
516
+ end,
476
517
  slot_duration: params.slot_duration,
477
518
  include_busy: params.include_busy
478
519
  });
479
520
  });
480
521
  var findMeetingTime = safeFunc(async (ctx) => {
481
- return ctx.client.availability.check(ctx.params);
522
+ const { client, params } = ctx;
523
+ const agents = params.agents ?? params.agent_ids;
524
+ const start = params.start ?? params.start_time;
525
+ const end = params.end ?? params.end_time;
526
+ if (!agents || !start || !end) {
527
+ throw new Error("agents (or agent_ids), start (or start_time), and end (or end_time) are required");
528
+ }
529
+ return client.availability.check({
530
+ agents,
531
+ start,
532
+ end,
533
+ slot_duration: params.slot_duration,
534
+ calendars: params.calendars,
535
+ include_busy: params.include_busy
536
+ });
482
537
  });
483
538
  var getCalendarContext = safeFunc(async (ctx) => {
484
539
  return ctx.client.calendars.getContext(ctx.params.calendar_id);
@@ -652,35 +707,35 @@ var TOOL_DEFINITIONS = [
652
707
  // ── Calendars ──────────────────────────────────────────────────
653
708
  {
654
709
  name: "list_calendars",
655
- description: "List calendars, optionally filtered by agent. Returns paginated results.",
710
+ description: "List calendars in the org. Org-level API keys see every calendar (agent-owned and shared); agent-scoped keys see only their own agent's calendars. Use this to discover calendar IDs before creating or listing events.",
656
711
  schema: ListCalendarsSchema,
657
712
  annotations: { title: "List Calendars", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
658
713
  execute: createExecutor(listCalendars)
659
714
  },
660
715
  {
661
716
  name: "get_calendar",
662
- description: "Get a calendar by its ID, including its name, timezone, and iCal feed URL.",
717
+ description: "Fetch a single calendar by ID, including its name, timezone, agent status, and default reminders. Agent-scoped keys may only read calendars owned by their agent.",
663
718
  schema: GetCalendarSchema,
664
719
  annotations: { title: "Get Calendar", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
665
720
  execute: createExecutor(getCalendar)
666
721
  },
667
722
  {
668
723
  name: "create_calendar",
669
- description: "Create a new calendar. Specify a name and IANA timezone. Optionally scope it to an agent.",
724
+ description: 'Create a calendar to hold events and track availability. Calendars are required before creating events \u2014 call this first when setting up a new agent. An agent can have multiple calendars (e.g. "Work", "Personal"). Org-level calendars (no agent_id) can be used as shared resources like meeting rooms.',
670
725
  schema: CreateCalendarSchema,
671
726
  annotations: { title: "Create Calendar", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
672
727
  execute: createExecutor(createCalendar)
673
728
  },
674
729
  {
675
730
  name: "update_calendar",
676
- description: "Update a calendar's name, timezone, or metadata.",
731
+ description: "Update a calendar's name, timezone, agent status, default reminders, or metadata. Agent-scoped keys may only update calendars owned by their agent.",
677
732
  schema: UpdateCalendarSchema,
678
733
  annotations: { title: "Update Calendar", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
679
734
  execute: createExecutor(updateCalendar)
680
735
  },
681
736
  {
682
737
  name: "delete_calendar",
683
- description: "Permanently delete a calendar and all its events.",
738
+ description: "Delete a calendar (soft delete). Its events are no longer returned and it stops contributing to availability. Agent-scoped keys may only delete calendars owned by their agent.",
684
739
  schema: DeleteCalendarSchema,
685
740
  annotations: { title: "Delete Calendar", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
686
741
  execute: createExecutor(deleteCalendar)
@@ -688,42 +743,42 @@ var TOOL_DEFINITIONS = [
688
743
  // ── Events ─────────────────────────────────────────────────────
689
744
  {
690
745
  name: "list_events",
691
- description: "List events on a calendar or for an agent. Supports date range and status filters. Provide calendar_id or agent_id.",
746
+ description: "List events on a calendar or across an agent's calendars, including internally created events and externally synced events from iCal subscriptions (e.g. Google Calendar, Outlook). Provide `calendar_id` OR `agent_id`. Narrow with `start_after`/`start_before` (time window), `status`, and `source`.",
692
747
  schema: ListEventsSchema,
693
748
  annotations: { title: "List Events", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
694
749
  execute: createExecutor(listEvents)
695
750
  },
696
751
  {
697
752
  name: "get_event",
698
- description: "Get a specific event by its calendar ID and event ID.",
753
+ description: "Retrieve a single event by ID, including its title, times, status, location, reminders, and metadata. Works for both internally created events and externally synced iCal events. `calendar_id` is optional \u2014 if omitted the calendar is resolved from the event. Provide `calendar_id` to fail fast on cross-calendar typos.",
699
754
  schema: GetEventSchema,
700
755
  annotations: { title: "Get Event", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
701
756
  execute: createExecutor(getEvent)
702
757
  },
703
758
  {
704
759
  name: "create_event",
705
- description: "Create a new event on a calendar. The event blocks the agent's availability during the specified time window and appears in availability queries.",
760
+ description: `Create a booking, appointment, meeting, hold, or any scheduled event on a calendar. The calendar_id comes from create_calendar or list_events. Once created, this event blocks the agent's availability during that time and appears in availability queries. Use status="hold" with hold_expires_at to tentatively reserve a slot that auto-releases on TTL.`,
706
761
  schema: CreateEventSchema,
707
762
  annotations: { title: "Create Event", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
708
763
  execute: createExecutor(createEvent)
709
764
  },
710
765
  {
711
766
  name: "update_event",
712
- description: "Update an existing event's title, times, status, or other properties.",
767
+ description: "Reschedule or edit an event \u2014 change its title, description, start/end times, location, status, reminders, or metadata. Use this to move an appointment to a new time or update its details. Provide only the fields you want to change. Holds cannot be edited via this tool (use confirm_event / release_event). External iCal events are read-only. `calendar_id` is optional \u2014 if omitted it is resolved from the event.",
713
768
  schema: UpdateEventSchema,
714
769
  annotations: { title: "Update Event", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
715
770
  execute: createExecutor(updateEvent)
716
771
  },
717
772
  {
718
773
  name: "cancel_event",
719
- description: "Delete or cancel an event from a calendar. The event is marked cancelled and excluded from future availability calculations.",
774
+ description: "Delete or cancel an event from a calendar. Use this to remove, cancel, or delete any scheduled event or appointment. The event is marked cancelled and excluded from future availability calculations. `calendar_id` is optional \u2014 if omitted the calendar is looked up from the event. Provide `calendar_id` to fail fast on cross-calendar typos.",
720
775
  schema: CancelEventSchema,
721
776
  annotations: { title: "Cancel Event", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
722
777
  execute: createExecutor(cancelEvent)
723
778
  },
724
779
  {
725
780
  name: "confirm_event",
726
- description: 'Promote a held event to a confirmed booking. The event must currently have status="hold" and its hold_expires_at must not have passed.',
781
+ description: 'Promote a held event to a confirmed booking. The event must currently have status="hold" and its hold_expires_at must not have passed. After confirmation, event.started and event.ended lifecycle webhooks fire at the scheduled times.',
727
782
  schema: ConfirmEventSchema,
728
783
  annotations: { title: "Confirm Event", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
729
784
  execute: createExecutor(confirmEvent)
@@ -745,28 +800,28 @@ var TOOL_DEFINITIONS = [
745
800
  },
746
801
  {
747
802
  name: "list_agents",
748
- description: "List all agents in your organization. Returns paginated results.",
803
+ description: "List all agents in your organization",
749
804
  schema: ListAgentsSchema,
750
805
  annotations: { title: "List Agents", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
751
806
  execute: createExecutor(listAgents)
752
807
  },
753
808
  {
754
809
  name: "get_agent",
755
- description: "Fetch a single agent by ID. An agent represents an AI assistant, human, or shared resource (e.g. a meeting room).",
810
+ description: "Fetch a single agent by ID. An agent represents an AI assistant, human, or shared resource (e.g. a meeting room). Agent-scoped API keys may only read their own agent.",
756
811
  schema: GetAgentSchema,
757
812
  annotations: { title: "Get Agent", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
758
813
  execute: createExecutor(getAgent)
759
814
  },
760
815
  {
761
816
  name: "update_agent",
762
- description: "Update an agent's name, description, metadata, or status (active/paused). Requires an org-level API key.",
817
+ description: "Update an agent's name, description, metadata, or status (active/paused). Requires an org-level API key \u2014 agent-scoped keys cannot mutate agents.",
763
818
  schema: UpdateAgentSchema,
764
819
  annotations: { title: "Update Agent", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
765
820
  execute: createExecutor(updateAgent)
766
821
  },
767
822
  {
768
823
  name: "delete_agent",
769
- description: "Decommission an agent. This marks the agent as decommissioned and revokes all of its scoped API keys. Requires an org-level API key.",
824
+ description: "Decommission an agent. This marks the agent as decommissioned and revokes all of its scoped API keys. Requires an org-level API key \u2014 agent-scoped keys cannot delete agents.",
770
825
  schema: DeleteAgentSchema,
771
826
  annotations: { title: "Delete Agent", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
772
827
  execute: createExecutor(deleteAgent)
@@ -774,14 +829,14 @@ var TOOL_DEFINITIONS = [
774
829
  // ── Availability ───────────────────────────────────────────────
775
830
  {
776
831
  name: "get_availability",
777
- description: "Check when a single agent is free within a time range. Returns available time slots and optionally busy blocks.",
832
+ description: "Check when a single agent is free within a time range. Accepts `start`/`end` (preferred \u2014 matches the underlying availability service) or `start_time`/`end_time` (aliases that match the REST events schema).",
778
833
  schema: GetAvailabilitySchema,
779
834
  annotations: { title: "Get Availability", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
780
835
  execute: createExecutor(getAvailability)
781
836
  },
782
837
  {
783
838
  name: "find_meeting_time",
784
- description: "Find time slots when multiple agents are all free simultaneously. All agents must be free during the returned slots.",
839
+ description: "Find time slots when multiple agents are all free simultaneously. Accepts `agents`/`start`/`end` (preferred \u2014 matches the availability service) or `agent_ids`/`start_time`/`end_time` (aliases that match the REST/scheduling-proposal naming).",
785
840
  schema: FindMeetingTimeSchema,
786
841
  annotations: { title: "Find Meeting Time", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
787
842
  execute: createExecutor(findMeetingTime)
@@ -789,7 +844,7 @@ var TOOL_DEFINITIONS = [
789
844
  // ── Calendar context ───────────────────────────────────────────
790
845
  {
791
846
  name: "get_calendar_context",
792
- description: "Get a calendar's temporal context in a single call: the current event, the next upcoming event, recent past events, a short upcoming window, and the owning agent's status.",
847
+ description: `Get a calendar's temporal context in a single call: the current event (if one is happening now), the next upcoming event, recent past events, a short upcoming window, and the owning agent's status (idle/working/waiting/error). Use this to answer "what is this agent doing right now?" without issuing multiple list_events queries.`,
793
848
  schema: GetCalendarContextSchema,
794
849
  annotations: { title: "Get Calendar Context", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
795
850
  execute: createExecutor(getCalendarContext)
@@ -797,14 +852,14 @@ var TOOL_DEFINITIONS = [
797
852
  // ── Scheduling proposals ───────────────────────────────────────
798
853
  {
799
854
  name: "create_proposal",
800
- description: "Create a scheduling proposal \u2014 send candidate time slots to one or more participant agents so they can accept, decline, or counter-propose. Requires an org-level API key. Pro plan only.",
855
+ description: "Create a scheduling proposal \u2014 send a set of candidate time slots to one or more participant agents so they can accept, decline, or counter-propose. The organizer agent owns the proposal; once every participant responds, the system auto-resolves to the highest-scoring slot (or cancels if all decline). Requires an org-level API key. Pro plan only.",
801
856
  schema: CreateProposalSchema,
802
857
  annotations: { title: "Create Proposal", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
803
858
  execute: createExecutor(createProposal)
804
859
  },
805
860
  {
806
861
  name: "list_proposals",
807
- description: "List scheduling proposals for the org. Filter by status or organizer_agent_id. Requires an org-level API key.",
862
+ description: "List scheduling proposals for the org. Filter by status (pending|confirmed|expired|cancelled) or organizer_agent_id. Requires an org-level API key.",
808
863
  schema: ListProposalsSchema,
809
864
  annotations: { title: "List Proposals", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
810
865
  execute: createExecutor(listProposals)
@@ -818,14 +873,14 @@ var TOOL_DEFINITIONS = [
818
873
  },
819
874
  {
820
875
  name: "respond_to_proposal",
821
- description: "Submit a response (accept / decline / counter) on behalf of one participant agent to an open proposal. Requires an org-level API key. Pro plan only.",
876
+ description: 'Submit a response (accept / decline / counter) on behalf of one participant agent to an open proposal. An "accept" requires the slot id from the proposal; a "counter" can suggest alternative slots. When all participants have responded the proposal auto-resolves \u2014 no separate resolve call needed in the normal flow. Requires an org-level API key. Pro plan only.',
822
877
  schema: RespondToProposalSchema,
823
878
  annotations: { title: "Respond To Proposal", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
824
879
  execute: createExecutor(respondToProposal)
825
880
  },
826
881
  {
827
882
  name: "resolve_proposal",
828
- description: "Force-resolve an open proposal using responses collected so far. Picks the highest-scoring slot and creates a confirmed calendar event. Requires an org-level API key. Pro plan only.",
883
+ description: 'Force-resolve an open proposal using responses collected so far. Picks the highest-scoring slot among those accepted by the most participants and creates a confirmed calendar event. If every response was "decline", the proposal is cancelled instead. Use when you want to close out a proposal without waiting for every participant. Requires an org-level API key. Pro plan only.',
829
884
  schema: ResolveProposalSchema,
830
885
  annotations: { title: "Resolve Proposal", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
831
886
  execute: createExecutor(resolveProposal)
@@ -840,7 +895,7 @@ var TOOL_DEFINITIONS = [
840
895
  // ── Availability rules ─────────────────────────────────────────
841
896
  {
842
897
  name: "set_availability_rules",
843
- description: "Set or replace the availability rules on a calendar \u2014 buffer times before/after events and optional per-day working hours. Upsert: overwrites any existing rules.",
898
+ description: "Set or replace the availability rules on a calendar \u2014 buffer times before/after events and optional per-day working hours. When these rules are set, every availability query on this calendar automatically applies them (busy-block expansion for buffers, masking outside working hours). Upsert: overwrites any existing rules.",
844
899
  schema: SetAvailabilityRulesSchema,
845
900
  annotations: { title: "Set Availability Rules", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
846
901
  execute: createExecutor(setAvailabilityRules)
@@ -854,7 +909,7 @@ var TOOL_DEFINITIONS = [
854
909
  },
855
910
  {
856
911
  name: "clear_availability_rules",
857
- description: "Remove the availability rules from a calendar, reverting to the default (no buffers, no working-hours mask).",
912
+ description: "Remove the availability rules from a calendar, reverting to the default (no buffers, no working-hours mask). Returns the deleted row, or an error if none were set.",
858
913
  schema: ClearAvailabilityRulesSchema,
859
914
  annotations: { title: "Clear Availability Rules", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
860
915
  execute: createExecutor(clearAvailabilityRules)
@@ -862,35 +917,35 @@ var TOOL_DEFINITIONS = [
862
917
  // ── Webhooks ───────────────────────────────────────────────────
863
918
  {
864
919
  name: "list_webhooks",
865
- description: "List all webhook subscriptions for the organization.",
920
+ description: "List the org's webhook subscriptions with their subscribed event types and active state. Signing secrets are never returned. Requires an org-level API key.",
866
921
  schema: ListWebhooksSchema,
867
922
  annotations: { title: "List Webhooks", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
868
923
  execute: createExecutor(listWebhooks)
869
924
  },
870
925
  {
871
926
  name: "get_webhook",
872
- description: "Get a webhook subscription by its ID.",
927
+ description: "Get a single webhook subscription by id, including its subscribed event types and active state. The signing secret is never returned. Requires an org-level API key.",
873
928
  schema: GetWebhookSchema,
874
929
  annotations: { title: "Get Webhook", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
875
930
  execute: createExecutor(getWebhook)
876
931
  },
877
932
  {
878
933
  name: "create_webhook",
879
- description: "Create a webhook subscription to receive event notifications at a URL. Payloads are signed with HMAC-SHA256.",
934
+ description: "Create a webhook subscription so the org receives HTTP POST notifications when events occur (e.g. event.created, proposal.confirmed). The signing secret is returned ONCE in this response \u2014 store it to verify the HMAC-SHA256 signature on delivered payloads. Requires an org-level API key.",
880
935
  schema: CreateWebhookSchema,
881
936
  annotations: { title: "Create Webhook", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
882
937
  execute: createExecutor(createWebhook)
883
938
  },
884
939
  {
885
940
  name: "update_webhook",
886
- description: "Update a webhook's URL, subscribed events, or active status.",
941
+ description: "Update a webhook subscription \u2014 change its delivery URL, the set of subscribed event types, or pause/resume it via active. At least one field must be supplied. Requires an org-level API key.",
887
942
  schema: UpdateWebhookSchema,
888
943
  annotations: { title: "Update Webhook", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
889
944
  execute: createExecutor(updateWebhook)
890
945
  },
891
946
  {
892
947
  name: "delete_webhook",
893
- description: "Delete a webhook subscription. No further events will be delivered to this URL.",
948
+ description: "Permanently delete a webhook subscription. This frees its endpoint slot against the per-plan cap. Requires an org-level API key.",
894
949
  schema: DeleteWebhookSchema,
895
950
  annotations: { title: "Delete Webhook", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
896
951
  execute: createExecutor(deleteWebhook)
@@ -905,42 +960,42 @@ var TOOL_DEFINITIONS = [
905
960
  // ── iCal Subscriptions ─────────────────────────────────────────
906
961
  {
907
962
  name: "list_ical_subscriptions",
908
- description: "List external calendar imports (iCal subscriptions) for an agent.",
963
+ description: "List an agent's external iCal feed subscriptions (e.g. linked Google Calendar / Outlook feeds), including their sync status and last sync time.",
909
964
  schema: ListICalSubscriptionsSchema,
910
965
  annotations: { title: "List iCal Subscriptions", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
911
966
  execute: createExecutor(listICalSubscriptions)
912
967
  },
913
968
  {
914
969
  name: "get_ical_subscription",
915
- description: "Get an iCal subscription by its ID, including sync status and last error.",
970
+ description: "Get a single external iCal feed subscription by id, including its sync status, last sync time, and last error.",
916
971
  schema: GetICalSubscriptionSchema,
917
972
  annotations: { title: "Get iCal Subscription", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
918
973
  execute: createExecutor(getICalSubscription)
919
974
  },
920
975
  {
921
976
  name: "subscribe_ical",
922
- description: "Link an external iCal feed (e.g. a human's Google Calendar) to an agent's calendar so external events appear in availability calculations. Events are synced every 30 minutes.",
977
+ description: "Link an external iCal feed (e.g. a human's Google Calendar) to an agent's calendar so external events appear in availability calculations. The target calendar must be owned by the specified agent \u2014 create the calendar with that agent_id first (org-level calendars without an agent_id cannot host external iCal subscriptions; create a dedicated per-agent calendar for sync targets).",
923
978
  schema: SubscribeICalSchema,
924
979
  annotations: { title: "Subscribe iCal", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true },
925
980
  execute: createExecutor(subscribeICal)
926
981
  },
927
982
  {
928
983
  name: "update_ical_subscription",
929
- description: "Update an iCal subscription's label or feed URL.",
984
+ description: "Update an external iCal feed subscription \u2014 change its label or its feed URL. Changing the URL forces a full re-sync on the next poll.",
930
985
  schema: UpdateICalSubscriptionSchema,
931
986
  annotations: { title: "Update iCal Subscription", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
932
987
  execute: createExecutor(updateICalSubscription)
933
988
  },
934
989
  {
935
990
  name: "delete_ical_subscription",
936
- description: "Remove an external calendar import. Previously synced events remain on the calendar.",
991
+ description: "Delete an external iCal feed subscription. Events previously synced from the feed are no longer refreshed.",
937
992
  schema: DeleteICalSubscriptionSchema,
938
993
  annotations: { title: "Delete iCal Subscription", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
939
994
  execute: createExecutor(deleteICalSubscription)
940
995
  },
941
996
  {
942
997
  name: "sync_ical_subscription",
943
- description: "Trigger an immediate sync of an iCal subscription instead of waiting for the next 30-minute poll.",
998
+ description: "Trigger an immediate sync of an external iCal feed subscription instead of waiting for the next scheduled poll. Returns once the sync has been queued.",
944
999
  schema: SyncICalSubscriptionSchema,
945
1000
  annotations: { title: "Sync iCal Subscription", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
946
1001
  execute: createExecutor(syncICalSubscription)
@@ -948,14 +1003,14 @@ var TOOL_DEFINITIONS = [
948
1003
  // ── Scoped keys ────────────────────────────────────────────────
949
1004
  {
950
1005
  name: "create_scoped_key",
951
- description: "Create an agent-scoped API key (chr_ak_*) that can only act on behalf of a single agent. The plaintext key is returned exactly once. Requires an org-level API key.",
1006
+ description: "Create an agent-scoped API key (chr_ak_*) that can only act on behalf of a single agent. Use this to self-provision or rotate per-agent credentials. The plaintext key is returned exactly once in the response \u2014 store it immediately, it cannot be retrieved later. Requires an org-level API key.",
952
1007
  schema: CreateScopedKeySchema,
953
1008
  annotations: { title: "Create Scoped Key", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
954
1009
  execute: createExecutor(createScopedKey)
955
1010
  },
956
1011
  {
957
1012
  name: "list_scoped_keys",
958
- description: "List all live (non-revoked) agent-scoped API keys for this org. Returns key metadata only \u2014 never the plaintext secret. Requires an org-level API key.",
1013
+ description: "List all live (non-revoked) agent-scoped API keys for this org. Returns key metadata only (id, prefix, agent_id, label, created_at) \u2014 never the plaintext secret. Requires an org-level API key.",
959
1014
  schema: ListScopedKeysSchema,
960
1015
  annotations: { title: "List Scoped Keys", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
961
1016
  execute: createExecutor(listScopedKeys)
@@ -970,7 +1025,7 @@ var TOOL_DEFINITIONS = [
970
1025
  // ── Audit log ──────────────────────────────────────────────────
971
1026
  {
972
1027
  name: "get_audit_log",
973
- description: "List audit-log entries for the calling org \u2014 mutating operations and auth-lifecycle events, newest first. Results are clamped to the plan's retention window. Requires an org-level API key.",
1028
+ description: "List audit-log entries for the calling org \u2014 mutating operations and auth-lifecycle events, newest first. Results are clamped to the plan's retention window. Requires an org-level API key (chr_sk_*); agent-scoped keys cannot read the org-wide audit log.",
974
1029
  schema: GetAuditLogSchema,
975
1030
  annotations: { title: "Get Audit Log", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
976
1031
  execute: createExecutor(getAuditLog)
@@ -978,7 +1033,7 @@ var TOOL_DEFINITIONS = [
978
1033
  // ── Terms ──────────────────────────────────────────────────────
979
1034
  {
980
1035
  name: "accept_terms",
981
- description: "Re-accept the current Chronary terms of service on behalf of the calling org. Use this when responses carry the Chronary-Terms-Upgrade-Required header. Requires an org-level API key.",
1036
+ description: "Re-accept the current Chronary terms of service on behalf of the calling org. Use this when responses carry the Chronary-Terms-Upgrade-Required header \u2014 a material ToS bump otherwise leaves MCP-only agents stuck without a console session. Pass the current tos_version (read it from GET /v1/auth/terms/current). Requires an org-level API key (chr_sk_*); agent-scoped keys cannot accept org-wide terms.",
982
1037
  schema: AcceptTermsSchema,
983
1038
  annotations: { title: "Accept Terms", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
984
1039
  execute: createExecutor(acceptTerms)
@@ -986,7 +1041,7 @@ var TOOL_DEFINITIONS = [
986
1041
  // ── Usage ──────────────────────────────────────────────────────
987
1042
  {
988
1043
  name: "get_usage",
989
- description: "Get quota and usage statistics for the current billing period.",
1044
+ description: "Get the calling org's current-period usage and plan limits (agents, calendars, events, API calls, webhooks, availability queries, iCal subscriptions, proposals, scoped keys, holds, cross-calendar queries). Requires an org-level API key (chr_sk_*); agent-scoped keys cannot read org-wide usage.",
990
1045
  schema: GetUsageSchema,
991
1046
  annotations: { title: "Get Usage", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
992
1047
  execute: createExecutor(getUsage)