PrimeCal Calendar Events List v2
primecal_calendars_events_list now exposes a compact, MCP-friendly event-list surface optimized for bounded retrieval, AI context windows, and multi-calendar queries.
Breaking Changes
fromis now required.tois optional and defaults tofrom + 1 day.startandendremain accepted as deprecated aliases only.calendarIdis optional. If omitted, PrimeCal searches every accessible calendar in the agent scope.- Timed events now return canonical UTC timestamps in
startsAtandendsAt. - All-day events keep date-only fields (
startDate,endDate) instead of timed UTC fields. - Every event also returns
startsAtLocal/endsAtLocal: the same instants rendered as ISO 8601 strings with a numeric UTC offset (e.g.+02:00) in the resolvedtimezone, alongside the UTCstartsAt/endsAtfields (which remain unchanged for backward compatibility). - Responses are paginated and now return
totalCount,truncated, andnextCursor.
Request Parameters
| Field | Type | Required | Notes |
|---|---|---|---|
from | string | Yes | ISO 8601 UTC timestamp ending in Z. |
to | string | No | ISO 8601 UTC timestamp ending in Z. Defaults to from + 1 day. |
start | string | No | Deprecated alias for from. |
end | string | No | Deprecated alias for to. |
calendarId | number | No | Legacy single-calendar filter. |
calendarIds | number[] | No | Preferred multi-calendar filter. Empty or missing means all accessible calendars. |
expandRecurrences | boolean | No | Default true. If false, recurring series return the master record only. |
fields | string[] | No | Optional sparse field selection. |
includeFullDescription | boolean | No | Default false. |
limit | number | No | Default 50, max 200. |
cursor | string | No | Opaque pagination token. |
userTimezone | string | No | Optional IANA timezone override for logical rendering and for startsAtLocal / endsAtLocal. Falls back to the caller's profile timezone, then UTC. Response startsAt / endsAt remain UTC. |
Default Compact Fields
When fields is omitted, PrimeCal returns a compact event shape:
idtitlestartsAt/endsAtfor timed eventsstartsAtLocal/endsAtLocal(offset-based local rendering; for all-day events,startsAtLocalisstartDateatT00:00:00in the resolved timezone)startDate/endDatefor all-day eventslocationallDaycalendarIdcalendarNameattendeeCountorganizerNametimezone
Optional Fields
PrimeCal only includes these when they are explicitly requested in fields:
descriptionmeetingUrlattendeesorganizersourceIdexternalIdrecurrenceTyperecurrenceRuleinstanceDatecreatedAtupdatedAt
If description is requested and includeFullDescription is false, the value is truncated and PrimeCal also returns hasMoreDescription.
meetingUrl is either a normalized meeting link string or null. PrimeCal computes and persists it during event ingestion or sync, so clients should not need to re-parse descriptions on read.
Supported meeting-link providers currently include:
- Microsoft Teams direct meeting links
- Microsoft Teams legacy meetup-join links
- Zoom
- Google Meet
- Whereby
- Webex
meetingUrl is treated as sensitive event detail data. PrimeCal does not log
it at info level and still applies normal calendar-sharing and event-read
authorization rules before returning it.
Timezone Rules
- PrimeCal stores and filters event windows in UTC.
- The resolved
timezone(and thusstartsAtLocal/endsAtLocal) isuserTimezoneif provided, otherwise the caller's profile timezone, otherwiseUTC. - Timed events always return UTC timestamps ending in
ZinstartsAt/endsAt;startsAtLocal/endsAtLocalrender the same instants as ISO 8601 strings with a numeric UTC offset (e.g.+02:00in summer,+01:00in winter forEurope/Budapest) instead of an IANA zone name. - All-day events return date-only fields in the logical timezone;
startsAtLocalis the event'sstartDateat local midnight (T00:00:00) with that timezone's offset, andendsAtLocalisendDate(the exclusive end date) the same way. - Every response includes
timezoneso clients can interpret date-only values consistently.
Example Timed Event
{
"id": 91,
"title": "May kickoff",
"startsAt": "2032-04-16T07:00:00.000Z",
"endsAt": "2032-04-16T08:00:00.000Z",
"startsAtLocal": "2032-04-16T09:00:00+02:00",
"endsAtLocal": "2032-04-16T10:00:00+02:00",
"location": null,
"allDay": false,
"calendarId": 14,
"calendarName": "May.B.Late Personal",
"attendeeCount": 2,
"organizerName": "May Organizer",
"timezone": "Europe/Budapest"
}
Example All-Day Event
{
"id": 92,
"title": "All-day planning offsite",
"startDate": "2032-04-18",
"endDate": "2032-04-19",
"startsAtLocal": "2032-04-18T00:00:00+02:00",
"endsAtLocal": "2032-04-19T00:00:00+02:00",
"allDay": true,
"calendarId": 14,
"calendarName": "May.B.Late Personal",
"timezone": "Europe/Budapest"
}
Recurrence Behavior
expandRecurrences: true- PrimeCal returns only the instances that intersect
[from, to]. - Occurrences include
instanceDateas aYYYY-MM-DDstring.
- PrimeCal returns only the instances that intersect
expandRecurrences: false- PrimeCal returns the recurrence master record.
- Recurring masters include
recurrenceTypeandrecurrenceRule.
instanceDate reliability
instanceDate is now reliably non-null for every expanded recurrence instance. Earlier versions could return null because TypeORM returned PostgreSQL date columns as strings instead of Date objects, and the serializer could not format them. The toInstanceDateString() helper now handles both Date and string inputs, so MCP clients can safely use instanceDate to identify, de-duplicate, or display a specific instance of a recurring series without null-checking it first.
Filtering Semantics
PrimeCal returns events whose stored UTC interval intersects the requested UTC window:
[event.startsAtUtc, event.endsAtUtc] ∩ [from, to] != ∅
This keeps filtering server-side and avoids in-memory full-table scans.
Pagination Contract
Responses always include:
itemstimezonetotalCounttruncatednextCursor
Example:
{
"items": [{ "id": 91, "title": "May kickoff" }],
"timezone": "Europe/Budapest",
"totalCount": 51,
"truncated": true,
"nextCursor": "eyJvZmZzZXQiOjUwLCJzaWduYXR1cmUiOiIuLi4ifQ"
}
Migration Guidance
- Prefer
calendarIdsovercalendarIdin new clients. - Prefer
from/tooverstart/end. - Request only the fields your client needs.
- Treat
nextCursoras opaque and do not edit it. - For meeting links, prefer
meetingUrlover custom description parsing.
Screenshot Reference
