Skip to main content
Was this helpful?

PrimeCal MCP Tools and Resources

This page documents the canonical PrimeCal MCP surface exposed by the server.

Tool Families​

Organisations, Resources, and Reservations​

  • primecal_organisations_list
  • primecal_organisations_active_set
  • primecal_organisations_billing_status_get
  • primecal_organisations_billing_settings_update
  • primecal_organisations_stripe_onboardingLink_create
  • primecal_organisations_payments_debug_get
  • primecal_resourceTypes_list
  • primecal_resources_list
  • primecal_reservations_availability_list
  • primecal_reservations_list
  • primecal_reservations_get
  • primecal_reservations_create

Common input fields:

  • organisationId for active-organisation switching only
  • resourceTypeId
  • optional resourceId
  • date for day-level availability
  • startTime / endTime for reservation creation
  • optional status, startFrom, and endTo for reservation listing

Important behavior:

  • reservation and resource tools resolve the active organisation from the agent context, not from arbitrary client payloads
  • billing and payment-debug tools also use the active organisation, but require explicit organisation scope and organisation-admin ownership context
  • availability uses the same blocking logic as public booking
  • MCP does not expose Stripe keys, Checkout sessions, payment intents, or webhook handling
  • reservation creation is limited to non-payment flows unless the owner context is acting in an administrative organisation role

Billing-specific input fields:

  • defaultCurrency for billing-safe updates
  • optional reservationId / bookingId
  • optional paymentStatus
  • optional limit

Calendars and Events​

  • primecal_calendars_list
  • primecal_calendars_get
  • primecal_calendars_events_list
  • primecal_calendars_events_search_v2
  • primecal_calendars_events_get_v2
  • primecal_calendars_events_create
  • primecal_calendars_events_update
  • primecal_calendars_events_delete
  • primecal_calendars_events_move
  • primecal_calendars_events_conflicts
  • primecal_calendars_availability_find
  • primecal_calendar_userGroups_list
  • primecal_calendar_userGroups_details
  • primecal_calendar_userGroups_createInvite
  • primecal_calendar_userGroups_acceptInvite
  • primecal_calendar_userGroups_attachCalendars
  • primecal_calendar_userGroups_detachCalendars

Scheduling tools​

primecal_calendars_events_move reschedules an event, preserving its duration and (for all-day events) its day-span. Prefer it over primecal_calendars_events_update for rescheduling: the server recomputes the end from the original duration, so the caller does not have to, and it returns any events the destination overlaps. Pass rejectOnConflict: true to make a conflicting destination fail rather than double-book.

primecal_calendars_events_conflicts answers "is this slot free?" and primecal_calendars_availability_find answers "when is this free?". Both use half-open overlap, so an event ending exactly when a window opens is adjacent rather than conflicting, and availability merges overlapping busy intervals before walking the gaps so a slot is never reported inside an existing booking.

Move requires calendar.events.update; conflicts and availability require calendar.events.read. No new permission keys were introduced, so existing agent grants already cover these tools.

Common input fields:

  • optional calendarId (number)
  • optional calendarIds (number array)
  • from / to (ISO 8601 UTC timestamps)
  • optional fields, limit, cursor, expandRecurrences, includeFullDescription, and userTimezone
  • eventId or id for updates/deletes
  • event object for create/update payloads

Recommended references:

People-group tool input fields:

  • groupId (number)
  • groupIds (number array) for optional filtering on list
  • calendarIds (number array) for attach/detach operations
  • permission (read, write, or admin) for attach operations
  • email and optional message for invite creation
  • token for invite acceptance

People-group tools are gated by calendar.userGroups.* action keys. Attach and detach tools require both group scope and calendar scope.

Tasks and Reminders​

  • primecal_tasks_list
  • primecal_tasks_create
  • primecal_tasks_update
  • primecal_tasks_delete
  • primecal_tasks_labels_list
  • primecal_tasks_labels_create
  • primecal_tasks_labels_update
  • primecal_tasks_labels_delete
  • primecal_tasks_focus_list
  • primecal_tasks_auto_schedule
  • primecal_tasks_accept_assignment
  • primecal_tasks_bounce_assignment
  • primecal_tasks_dependencies_add
  • primecal_tasks_dependencies_remove
  • primecal_tasks_checklist_list
  • primecal_tasks_checklist_add
  • primecal_tasks_checklist_update
  • primecal_tasks_checklist_remove
  • primecal_tasks_reorder
  • primecal_tasks_archive
  • primecal_tasks_unarchive
  • primecal_tasks_archive_done
  • primecal_tasks_settings_get
  • primecal_tasks_settings_update
  • primecal_reminders_create
  • primecal_reminders_update

Reminder tools are task-backed and map reminder fields (remindAt, note) into task fields (dueDate, body).

primecal_tasks_create/primecal_tasks_update also accept durationMinutes (1-1440, used by auto-scheduling), context (deep_work, errand, admin, kid_safe, low_energy), autoScheduled, and preferredWindowStartHour/preferredWindowEndHour (0-23) — e.g. "block 30 minutes of deep work to write the report" maps to primecal_tasks_create with durationMinutes: 30, context: 'deep_work'.

primecal_tasks_focus_list accepts an optional date (YYYY-MM-DD, defaults to today UTC) and returns the same schedule-ordered, dependency-filtered list as GET /api/tasks/focus.

primecal_tasks_auto_schedule, primecal_tasks_accept_assignment, and primecal_tasks_bounce_assignment each accept taskId or id; bounce also accepts an optional reason (max 500 chars). primecal_tasks_dependencies_add/_remove take taskId and dependsOnTaskId.

primecal_tasks_checklist_list/_add/_update/_remove all take taskId, plus title (add), or itemId/id with optional title/isDone/order (update), or itemId/id (remove) — e.g. "add 'book venue' to my party-planning task's checklist" maps to primecal_tasks_checklist_add. All four return the task's full updated checklist.

primecal_tasks_reorder takes status and the full ordered taskIds array for that column — e.g. "move my 'write status report' task to the top of To Do" maps to reading the current To Do order via primecal_tasks_list, then calling primecal_tasks_reorder with that task's id moved to the front. primecal_tasks_archive/primecal_tasks_unarchive take taskId/id; primecal_tasks_archive_done takes no parameters and archives every done, non-archived task at once. primecal_tasks_settings_get takes no parameters; primecal_tasks_settings_update takes autoArchiveCompletedTasksDays (an integer 1-3650, or null to disable auto-archiving).

Routines and Household​

  • primecal_routine_templates_list
  • primecal_routine_templates_clone
  • primecal_routine_templates_instantiate
  • primecal_routine_templates_streak
  • primecal_routine_templates_skip
  • primecal_household_items_list
  • primecal_household_items_create
  • primecal_household_items_mark_used_up
  • primecal_household_items_consume

primecal_routine_templates_clone accepts templateId/id and an optional groupId to clone a system template into a people group instead of the caller's personal templates. primecal_routine_templates_instantiate accepts templateId/id and starts the template right now — e.g. "start my evening routine" — the same as the Start now button, independent of the template's recurrence schedule.

primecal_routine_templates_streak accepts templateId/id and returns { currentStreak, longestStreak, lastCompletedDate, totalInstantiations }. primecal_routine_templates_skip accepts templateId/id and skips today's occurrence without creating tasks — e.g. "skip cleaning this week, we're travelling" — without disturbing rotation history.

primecal_household_items_create accepts name, category, quantity, groupId, expiryDate (YYYY-MM-DD), shelfLifeDays (1-3650), and lowStockThreshold (>= 0, an independent count-based restock trigger). primecal_household_items_mark_used_up accepts an item id and flags it so the hourly restock scan raises a task for it. primecal_household_items_consume accepts itemId/id and an optional amount (defaults to 1) to reduce quantity — e.g. "used 2 rolls of paper towels."

See the Routine Templates API and Household Items API for the underlying REST contract and rotation/restock behavior these tools call into.

Automation​

  • primecal_automation_rules_list
  • primecal_automation_rules_get
  • primecal_automation_rules_trigger
  • primecal_automation_rules_audit_list

Common input fields:

  • ruleId (number)
  • optional status, fromDate, toDate
  • pagination (page, limit)

Profile and Context​

  • primecal_profile_get
  • primecal_context_snapshot
  • primecal_context_snapshot_v2
  • primecal_summary_today_week

Context snapshot input:

  • days (1-30)
  • tasksLimit (1-200)
  • eventsLimit (1-200)
  • includeCompletedTasks (boolean)

primecal_summary_today_week is a one-call today+week digest (events and tasks due, for today and for the rolling 7-day window starting today) — use it instead of two separate context-snapshot/event calls when the goal is a daily or weekly summary. Input: userTimezone, eventsLimit (1-100), tasksLimit (1-200), includeCompletedTasks (boolean).

Notifications​

  • primecal_notifications_list
  • primecal_notifications_mark_read
  • primecal_notifications_act
  • primecal_notifications_preferences_get
  • primecal_notifications_preferences_update

Common input fields:

  • optional unreadOnly, archived (booleans), and threadId (number) for list filtering
  • optional afterCursor (opaque ISO-timestamp cursor) for list pagination
  • ids (number array, 1-100) for marking notifications read
  • notificationId (number) and actionType (confirm | snooze | delegate | claim | done | undo | ack), plus an optional payload object (e.g. { snoozeUntil } or { snoozeMinutes } for a snooze action) for primecal_notifications_act
  • preferences (array of { eventType, channels, digest?, fallbackOrder?, quietHours? }) for preference updates

All five tools are scoped to the authenticated user's own notifications and preferences; there is no cross-user access. primecal_notifications_list returns at most 50 notifications, newest first. primecal_notifications_act records the 'acted' lifecycle stage via the same NotificationsService.recordAction path as the REST /notifications/:id/act endpoint, and also handles side effects (marking read, archiving on done/confirm, snooze rescheduling, clearing archive state on undo). primecal_notifications_preferences_update replaces the stored preference for each submitted eventType — event types left out of the array are removed, matching the behavior of PUT /api/notifications/preferences.

Screens and Devices​

  • primecal_screens_list
  • primecal_screens_get
  • primecal_screen_templates_list
  • primecal_screen_templates_apply
  • primecal_devices_list

Common input fields:

  • screenId or id (number) for primecal_screens_get
  • templateId or id (number), optional screenId (number), and optional newScreenName (string, ≤120) for primecal_screen_templates_apply

All five tools are read-mostly and scoped to the authenticated user's own Screens, Templates, and Devices — primecal_screen_templates_apply is the one write action, and it only ever affects a Screen the caller owns. Pairing-code redemption, Device token issuance/revocation, and org-scoped Screen RBAC admin actions are deliberately not exposed as MCP tools at all — they're simply omitted from tool registration, not gated by a separate permission mechanism. primecal_devices_list never returns a Device's credential — only its name, status, assigned Screen, and last-seen timestamp.

Resources​

  • primecal.current-context (primecal://current-context)
  • primecal.automation-summary (primecal://automation-summary)
  • primecal.calendar.user-groups (primecal://calendar/user-groups)
  • primecal.calendar.user-group-detail (primecal://calendar/user-groups/{id})

Both resources return application/json textual content in MCP resources/read responses.

People-group resources are read-only and only include groups and calendars allowed by the agent's scope.

Enterprise Reservation JSON-RPC Examples​

Switch the active organisation​

{
"jsonrpc": "2.0",
"id": 30,
"method": "tools/call",
"params": {
"name": "primecal_organisations_active_set",
"arguments": {
"organisationId": 12
}
}
}

Read availability for one service​

{
"jsonrpc": "2.0",
"id": 31,
"method": "tools/call",
"params": {
"name": "primecal_reservations_availability_list",
"arguments": {
"date": "2026-05-20",
"resourceTypeId": 8
}
}
}

Create a non-payment reservation​

{
"jsonrpc": "2.0",
"id": 32,
"method": "tools/call",
"params": {
"name": "primecal_reservations_create",
"arguments": {
"resourceTypeId": 8,
"resourceIds": [41, 42],
"startTime": "2026-05-20T10:00:00Z",
"endTime": "2026-05-20T11:00:00Z",
"notes": "Agent-assisted booking"
}
}
}

Read active-organisation billing status​

{
"jsonrpc": "2.0",
"id": 33,
"method": "tools/call",
"params": {
"name": "primecal_organisations_billing_status_get",
"arguments": {}
}
}

Update the default billing currency​

{
"jsonrpc": "2.0",
"id": 34,
"method": "tools/call",
"params": {
"name": "primecal_organisations_billing_settings_update",
"arguments": {
"defaultCurrency": "eur"
}
}
}

Prepare Stripe onboarding​

{
"jsonrpc": "2.0",
"id": 35,
"method": "tools/call",
"params": {
"name": "primecal_organisations_stripe_onboardingLink_create",
"arguments": {}
}
}

Inspect payment-debug state​

{
"jsonrpc": "2.0",
"id": 36,
"method": "tools/call",
"params": {
"name": "primecal_organisations_payments_debug_get",
"arguments": {
"paymentStatus": "pending",
"limit": 10
}
}
}

People-Group JSON-RPC Examples​

List scoped groups and calendars​

{
"jsonrpc": "2.0",
"id": 20,
"method": "tools/call",
"params": {
"name": "primecal_calendar_userGroups_list",
"arguments": {
"includeCalendars": true
}
}
}

Create a group invite​

{
"jsonrpc": "2.0",
"id": 21,
"method": "tools/call",
"params": {
"name": "primecal_calendar_userGroups_createInvite",
"arguments": {
"groupId": 9,
"email": "teammate@example.com",
"message": "Join the shared planning calendars."
}
}
}

The result is intentionally generic and does not disclose whether the email maps to an existing PrimeCal user.

Attach a calendar to a group​

{
"jsonrpc": "2.0",
"id": 22,
"method": "tools/call",
"params": {
"name": "primecal_calendar_userGroups_attachCalendars",
"arguments": {
"groupId": 9,
"calendarIds": [5],
"permission": "write"
}
}
}

Read the group summary resource​

{
"jsonrpc": "2.0",
"id": 23,
"method": "resources/read",
"params": {
"uri": "primecal://calendar/user-groups"
}
}

Schema and Result Model​

All tools are listed through MCP tools/list and publish JSON Schema-compatible inputSchema objects.

Result shape follows MCP conventions, with the following important distinctions:

Array-returning tools​

Tools that return collections (listOrganisations, listResources, listReservations, primecal_calendars_events_list, etc.) do not set structuredContent. Callers must parse the JSON string in content[0].text to obtain the array.

{
"content": [
{
"type": "text",
"text": "[{\"id\":41,\"name\":\"Pool lane A\"},{\"id\":42,\"name\":\"Pool lane B\"}]"
}
]
}

Object-returning tools​

Tools that return a single object set structuredContent to the object directly (not wrapped in another object).

{
"content": [
{
"type": "text",
"text": "{\"id\":42,\"title\":\"Project review\"}"
}
],
"structuredContent": {
"id": 42,
"title": "Project review"
}
}

Error envelope​

All errors set isError: true, include a human-readable description in content[0].text, and always set structuredContent to the error object:

{
"isError": true,
"content": [
{
"type": "text",
"text": "Agent does not have access to this tool or scope."
}
],
"structuredContent": {
"error": {
"type": "forbidden",
"message": "Agent does not have access to this tool or scope.",
"statusCode": 403,
"retriable": false
}
}
}

Error type values:

typeHTTP statusMeaning
validation_error400Malformed input or DTO validation failure.
unauthorized401Missing or invalid agent key.
forbidden403Valid key but insufficient permission scope.
not_found404Requested resource does not exist.
conflict409State conflict (e.g. booking overlap).
rate_limited429Rate limit exceeded; retry after back-off.
http_error5xxUpstream or server-side failure.
internal_error—Unexpected internal error.

retriable is true for transient errors (rate_limited, some http_error variants) and false for permanent failures.

Migration note: previous docs showed "type": "permission_denied" in the error envelope. This type no longer exists — use "forbidden" (HTTP 403) instead. Callers that matched on "permission_denied" must update to "forbidden".

Payload Richness Expectations​

PrimeCal tools should return rich data so AI hosts can reason with minimal extra round trips.

  • Event objects include timeline, recurrence, status, color, and metadata.
  • People-group objects include role, minimal member summaries, invite-safe metadata, and simplified calendar references when scoped.
  • Task objects include labels and task-calendar mirror metadata.
  • Automation responses include rule definitions, counters, and audit records.
  • Reservation objects include assigned resources, resource type, quote snapshot, customer payload, status, and payment state.

Quick Protocol Smoke Test​

  1. initialize against /api/mcp
  2. tools/list
  3. resources/list
  4. tools/call with primecal_profile_get
  5. resources/read for primecal://current-context

Alex Example demo expectation:

  • primecal_calendars_list should include Work, Personal, and Side projects.
  • primecal_calendar_userGroups_list should return only groups allowed by the agent's user-group scope.
  • primecal_organisations_list should return only organisations allowed by the agent profile and underlying owner access.