Skip to main content
Glama

calendar_create_event

Book one iCloud calendar event with location, notes, alarms, travel time, or guests in a single call. Use when scheduling or adding an event, not for updates or to-dos.

Instructions

Create one calendar event, optionally repeating, with location, notes, alarms, travel time and invited guests, all in a single call.

Use when: the owner asks to book, schedule or add something to the calendar. Not for changing an event (use calendar_update_event), a to-do without a time slot (use reminders_create_reminder), answering someone else's invitation (use calendar_respond_to_event) or finding a time (use calendar_find_free_time first). For a booking found in mail, mail_extract_bookings supplies ready arguments. Parameters:

  • Convert relative dates ('tomorrow at 3pm') to ISO 8601 yourself.

  • start and end must both be dates (all-day) or both date-times, end after start.

  • Omitting calendar uses DEFAULT_CALENDAR, else 'Calendar' or 'Home', else the first.

  • travel_origin and travel_routing need travel_minutes (1 to 1440), taken from the owner or maps_get_travel_time, never guessed.

  • location_geo needs location.

  • rrule may fire at most 48 times a day.

  • Example: summary='Lunch with Anna', start='2026-09-21T12:30', end='2026-09-21T13:30', location='Cafe X', attendees=['anna@example.org'], alarms_minutes_before=[30]. Behavior:

  • The owner is the organizer and iCloud emails each attendee an invitation itself, so send no separate mail.

  • Attendees are refused unless the server allows calendar invites (ALLOW_CALENDAR_INVITES), and are limited by INVITE_ALLOWLIST and MAX_ATTENDEES (default 10).

  • Before writing it checks all calendars for overlaps (travel counted; all-day events never conflict) and the target calendar for the same title at the same start; on_conflict / on_duplicate='refuse' then create nothing.

  • With request_id a retry returns the first event, never a second copy; without it a repeat creates another event. Returns: {created, uid, calendar, event, conflicts, possible_duplicate, now}; with guests also invited and delivery [{address, meaning, ok}]: ok=false means iCloud did not deliver, so do not tell the owner that person was invited. created=false (with already_existed, conflicts or possible_duplicate) means nothing was written. Tell the owner about any conflicts. Errors: invitations blocked by settings, an unusable address (look it up with contacts_search_contacts or mail_find_correspondent), invalid dates or rrule; each message says what to change.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
endNoEnd, same format as start. Omit for a 1-hour event (1 day if all-day). A date-only end is inclusive.
urlNoA link to attach to the event.
rruleNoRepeat rule (RFC 5545), e.g. 'FREQ=WEEKLY;BYDAY=MO,WE;COUNT=10'. Omit for a one-off event.
startYesStart: ISO 8601 date-time such as 2026-09-21T15:00 (no offset = 'timezone'), or a date such as 2026-09-21 for an all-day event.
summaryYesEvent title.
calendarNoCalendar name (calendar_list_calendars); omit for the default.
locationNoPlace name or address.
timezoneNoIANA timezone for times without an offset, e.g. 'Europe/Berlin'; default the owner's.
attendeesNoPeople to invite: ['anna@example.org'] or ['Anna <anna@example.org>']. iCloud emails each one an invitation, so do not send a separate email. Only a name? Look it up with contacts_search_contacts, then mail_find_correspondent.
request_idNoRetry key unique to this request (e.g. 'lunch-anna-2026-09-24'): a repeat with the same key returns the first result, never a second copy.
descriptionNoNotes for the event. Links in the text stay clickable.
on_conflictNo'refuse' = create nothing when it overlaps another event; the result lists 'conflicts' either way.warn
location_geoNo'lat,lon'. Not needed: Apple maps the location text itself. Only to pin an exact spot; '' removes the map.
on_duplicateNo'refuse' = create nothing when the same title at the same time is already on that calendar.warn
travel_originNoStarting address for the travel time, e.g. 'Unter den Linden 1, 10117 Berlin'. Optional.
travel_minutesNoApple travel time in minutes before the start: a travel block plus an alarm at leave-by, so do not move the start or write a leave-by time. 0 removes it.
travel_routingNoHow they travel: BICYCLE (default), WALKING, AUTOMOBILE or TRANSIT. Only used when travel_origin is given.
travel_origin_geoNoCoordinates of travel_origin as 'lat,lon', e.g. '52.5163,13.3777'. Optional, and only meaningful with travel_origin.
alarms_minutes_beforeNoReminders, as minutes before the start: [60, 15]. Use 0 for at start time.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedOutput schema / (root)
      Previous value: -{
      -  "additionalProperties": true,
      -  "title": "calendar_create_eventDictOutput",
      -  "type": "object"
      -}New value: +null
  2. Changed1 schema field changedv0.12.0
    • changedInput schema / properties / attendees / description
      Previous value: -"People to invite: ['anna@example.org'] or ['Anna <anna@example.org>']. iCloud emails each one an invitation, so do not send a separate email. Only a name? Look it up with contacts_search, then mail_find_correspondent."New value: +"People to invite: ['anna@example.org'] or ['Anna <anna@example.org>']. iCloud emails each one an invitation, so do not send a separate email. Only a name? Look it up with contacts_search_contacts, then mail_find_correspondent."
  3. Changed76 schema fields changedv0.7.0
    • removedInput schema / properties / alarms_minutes_before / anyOf
      Removed value: -[
      -  {
      -    "items": {
      -      "type": "integer"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / alarms_minutes_before / default
      Removed value: -null
    • addedInput schema / properties / alarms_minutes_before / items
      Added value: +{
      +  "type": "integer"
      +}
    • removedInput schema / properties / alarms_minutes_before / title
      Removed value: -"Alarms Minutes Before"
    • addedInput schema / properties / alarms_minutes_before / type
      Added value: +"array"
    • removedInput schema / properties / attendees / anyOf
      Removed value: -[
      -  {
      -    "items": {
      -      "type": "string"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / attendees / default
      Removed value: -null
    • changedInput schema / properties / attendees / description
      Previous value: -"People to invite: ['anna@example.org'] or ['Anna <anna@example.org>']. iCloud emails each one an invitation, so do not send a separate email. If you only know a name, look the address up first with mail_search."New value: +"People to invite: ['anna@example.org'] or ['Anna <anna@example.org>']. iCloud emails each one an invitation, so do not send a separate email. Only a name? Look it up with contacts_search, then mail_find_correspondent."
    • addedInput schema / properties / attendees / items
      Added value: +{
      +  "type": "string"
      +}
    • removedInput schema / properties / attendees / title
      Removed value: -"Attendees"
    • addedInput schema / properties / attendees / type
      Added value: +"array"
    • removedInput schema / properties / calendar / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / calendar / default
      Removed value: -null
    • changedInput schema / properties / calendar / description
      Previous value: -"Calendar name from calendar_list_calendars. Omit to use the default calendar."New value: +"Calendar name (calendar_list_calendars); omit for the default."
    • removedInput schema / properties / calendar / title
      Removed value: -"Calendar"
    • addedInput schema / properties / calendar / type
      Added value: +"string"
    • removedInput schema / properties / description / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / description / default
      Removed value: -null
    • removedInput schema / properties / description / title
      Removed value: -"Description"
    • addedInput schema / properties / description / type
      Added value: +"string"
    • removedInput schema / properties / end / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / end / default
      Removed value: -null
    • removedInput schema / properties / end / title
      Removed value: -"End"
    • addedInput schema / properties / end / type
      Added value: +"string"
    • removedInput schema / properties / location / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / location / default
      Removed value: -null
    • removedInput schema / properties / location / title
      Removed value: -"Location"
    • addedInput schema / properties / location / type
      Added value: +"string"
    • removedInput schema / properties / location_geo / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / location_geo / default
      Removed value: -null
    • changedInput schema / properties / location_geo / description
      Previous value: -"Coordinates of the location as 'lat,lon'. NOT needed: a map is drawn from the location text alone, because Apple geocodes it and fills the coordinates in itself. Pass these only to pin an exact spot. '' removes the map entirely."New value: +"'lat,lon'. Not needed: Apple maps the location text itself. Only to pin an exact spot; '' removes the map."
    • removedInput schema / properties / location_geo / title
      Removed value: -"Location Geo"
    • addedInput schema / properties / location_geo / type
      Added value: +"string"
    • addedInput schema / properties / on_conflict
      Added value: +{
      +  "default": "warn",
      +  "description": "'refuse' = create nothing when it overlaps another event; the result lists 'conflicts' either way.",
      +  "enum": [
      +    "warn",
      +    "refuse"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / on_duplicate
      Added value: +{
      +  "default": "warn",
      +  "description": "'refuse' = create nothing when the same title at the same time is already on that calendar.",
      +  "enum": [
      +    "warn",
      +    "refuse"
      +  ],
      +  "type": "string"
      +}
    • removedInput schema / properties / request_id / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / request_id / default
      Removed value: -null
    • changedInput schema / properties / request_id / description
      Previous value: -"Optional retry key, any short text unique to this one request (e.g. 'lunch-anna-2026-09-24'). If a call times out and you retry with the SAME request_id, the first attempt is found instead of creating a duplicate."New value: +"Retry key unique to this request (e.g. 'lunch-anna-2026-09-24'): a repeat with the same key returns the first result, never a second copy."
    • removedInput schema / properties / request_id / title
      Removed value: -"Request Id"
    • addedInput schema / properties / request_id / type
      Added value: +"string"
    • removedInput schema / properties / rrule / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / rrule / default
      Removed value: -null
    • removedInput schema / properties / rrule / title
      Removed value: -"Rrule"
    • addedInput schema / properties / rrule / type
      Added value: +"string"
    • changedInput schema / properties / start / description
      Previous value: -"Start: ISO 8601 date-time such as 2026-09-21T15:00 (no offset = 'timezone', default the server timezone), or a date such as 2026-09-21 for an all-day event."New value: +"Start: ISO 8601 date-time such as 2026-09-21T15:00 (no offset = 'timezone'), or a date such as 2026-09-21 for an all-day event."
    • removedInput schema / properties / start / title
      Removed value: -"Start"
    • removedInput schema / properties / summary / title
      Removed value: -"Summary"
    • removedInput schema / properties / timezone / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / timezone / default
      Removed value: -null
    • changedInput schema / properties / timezone / description
      Previous value: -"IANA timezone for start/end without an offset, e.g. 'Europe/Berlin'. Omit to use the server timezone."New value: +"IANA timezone for times without an offset, e.g. 'Europe/Berlin'; default the owner's."
    • removedInput schema / properties / timezone / title
      Removed value: -"Timezone"
    • addedInput schema / properties / timezone / type
      Added value: +"string"
    • removedInput schema / properties / travel_minutes / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / travel_minutes / default
      Removed value: -null
    • changedInput schema / properties / travel_minutes / description
      Previous value: -"Apple travel time, in minutes before the start. The event then shows a travel block and its alarm fires at the leave-by moment, so there is no need to write a leave-by time into the notes or to start the event early. 0 removes it."New value: +"Apple travel time in minutes before the start: a travel block plus an alarm at leave-by, so do not move the start or write a leave-by time. 0 removes it."
    • removedInput schema / properties / travel_minutes / title
      Removed value: -"Travel Minutes"
    • addedInput schema / properties / travel_minutes / type
      Added value: +"integer"
    • removedInput schema / properties / travel_origin / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / travel_origin / default
      Removed value: -null
    • changedInput schema / properties / travel_origin / description
      Previous value: -"Where they set off from, as an address: 'Harpstraat 57, 3513 XB Utrecht'. Optional; without it the travel time is still set, just with no starting point attached."New value: +"Starting address for the travel time, e.g. 'Unter den Linden 1, 10117 Berlin'. Optional."
    • removedInput schema / properties / travel_origin / title
      Removed value: -"Travel Origin"
    • addedInput schema / properties / travel_origin / type
      Added value: +"string"
    • removedInput schema / properties / travel_origin_geo / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / travel_origin_geo / default
      Removed value: -null
    • changedInput schema / properties / travel_origin_geo / description
      Previous value: -"Coordinates of travel_origin as 'lat,lon', e.g. '52.099520,5.106825'. Optional, and only meaningful with travel_origin."New value: +"Coordinates of travel_origin as 'lat,lon', e.g. '52.5163,13.3777'. Optional, and only meaningful with travel_origin."
    • removedInput schema / properties / travel_origin_geo / title
      Removed value: -"Travel Origin Geo"
    • addedInput schema / properties / travel_origin_geo / type
      Added value: +"string"
    • removedInput schema / properties / travel_routing / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / travel_routing / default
      Removed value: -null
    • removedInput schema / properties / travel_routing / title
      Removed value: -"Travel Routing"
    • addedInput schema / properties / travel_routing / type
      Added value: +"string"
    • removedInput schema / properties / url / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedInput schema / properties / url / default
      Removed value: -null
    • removedInput schema / properties / url / title
      Removed value: -"Url"
    • addedInput schema / properties / url / type
      Added value: +"string"
    • removedInput schema / title
      Removed value: -"calendar_create_eventArguments"
  4. Changed1 schema field changedv0.4.0
    • addedInput schema / properties / request_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Optional retry key, any short text unique to this one request (e.g. 'lunch-anna-2026-09-24'). If a call times out and you retry with the SAME request_id, the first attempt is found instead of creating a duplicate.",
      +  "title": "Request Id"
      +}
  5. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give the generic safety profile (readOnlyHint=false, openWorldHint=true, idempotentHint=false, destructiveHint=false). The description goes far beyond: iCloud sends invitations itself so no mail should be sent, invites are gated by ALLOW_CALENDAR_INVITES/INVITE_ALLOWLIST/MAX_ATTENDEES, pre-write overlap and same-title duplicate checks with refuse semantics, request_id retry semantics that qualify the non-idempotent default, and per-recipient delivery status where ok=false means the owner must not be told the person was invited.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the purpose sentence, then clearly labeled Use-when / Parameters / Behavior / Returns / Errors sections, so scanning is cheap despite the length. A few statements duplicate schema text (the iCloud invitation rule appears in both the Behavior block and the attendees description), which is minor waste for a definition this dense.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the return contract itself and does so precisely: field list, created=false semantics, conflicts/possible_duplicate meanings, delivery[] ok flag, and a catalog of error conditions with the recovery tool for each. For a 19-parameter mutating open-world tool this is as complete as it needs to be.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline would be 3, but the description adds real cross-parameter meaning absent from the schema: start/end must both be all-day or both date-times, calendar fallback resolution order (DEFAULT_CALENDAR, then 'Calendar'/'Home', then first), travel_origin/travel_routing require travel_minutes (1–1440) sourced from owner or maps, location_geo requires location, and the 48-fires/day rrule cap. It also converts relative dates to ISO 8601 up front, which is the main failure mode for a 19-param tool.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Create one calendar event') and enumerates the scope it covers in a single call (repeat, location, notes, alarms, travel, guests). It explicitly distinguishes itself from the nearest siblings (calendar_update_event, reminders_create_reminder, calendar_respond_to_event, calendar_find_free_time), so an agent can route correctly without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Use when' block gives the positive trigger (owner asks to book/schedule/add) and four named exclusions with the alternative tool for each, plus a cross-server handoff (mail_extract_bookings supplies ready arguments for bookings found in mail). There is nothing left to infer about when to pick this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.