Skip to main content
Version: Latest

Google Calendar

Proxy for the Google Calendar v3 REST API. Dual auth by design — the typical production setup runs two managed resources at once:

  • calendar-user in idp_passthrough mode for human users who want an agent to read their schedule, find free slots, or update their own events.
  • calendar-rooms in google_sa mode for a booking agent that schedules meetings into Workspace resource (room) calendars on everyone's behalf.

Overview

The policy layer recognises this split and lets the operator lock each mode down differently:

  • User-mode managed resources typically carry a write_blocked list on the general file-access control, for calendars the user is on but shouldn't let an agent edit (shared team, executive).
  • Room-mode managed resources typically run with room_only_mode: true, which refuses any call whose calendar_id isn't a Workspace resource calendar (*@resource.calendar.google.com).

Default policy

The connector ships policy/calendar.rego (package pbac.connectors.identos.google_calendar). It enforces two things; blocked and read-only calendar ids are operator config on the general file-access control (see below), not rules here.

1. IdP-routing subject obligation

Same shape as drive/gmail — non-Google session + idp_passthrough mode triggers a require_authn_at obligation.

2. room_only_mode deny

deny contains msg if {
input.resource.type == "urn:connector:identos:google-calendar"
data[...].room_only_mode == true
cal := input.context.rs_context.tool_arguments.calendar_id
not endswith(cal, "@resource.calendar.google.com")
...
}

A booking-agent safety net. When enabled, every calendar_id must look like a Workspace resource calendar. If the agent (or, more importantly, a prompt-injected response it's acting on) tries to touch a human calendar, the request is denied. Makes the service account's broad Workspace grants safe to deploy.

Supplying operator data

room_only_mode is the connector's own setting — a suffix test, not an id set, so it stays connector rego:

KEY=pbac.operator.connectors.identos.google-calendar

curl -X PUT "http://localhost:8080/admin/api/policy-data/by-key?dataKey=$KEY" \
-H "X-Admin-API-Key: $PBAC_ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg k "$KEY" --argjson s '{
"room_only_mode": true
}' \
'{dataKey:$k, payload:($s|tojson)}')"

File access control

Blocking a specific calendar is operator config on the general file-access control, shared with the Google file connectors — not a rule in this connector. An identity source matches a calendar by its own id: ids in blocked are denied on reads and writes, ids in write_blocked are denied on writes only, so reads still work.

curl -X PUT http://localhost:8080/admin/policy/data/pbac/operator/controls/file_access \
-H "X-Admin-API-Key: $PBAC_ADMIN_API_KEY" \
-d '{
"sources": {
"calendars": {
"type": "identity",
"blocked": ["ceo@example.com"],
"write_blocked": ["team-alpha@example.com"]
}
},
"governed": {
"urn:connector:identos:google-calendar": ["calendars"]
}
}'

The control reads the id from the calendar_id tool argument and applies to calendar:read, calendar:events:write and calendar:admin calls alike. Listing a connector under governed is what activates it; omit it and the control is inert. Full mechanics (pooling, deny-wins, fail-closed) live in the File Access Control guide.

Scope model

ScopeUsed for
PBAC scopes (internal)calendar:read, calendar:events:write, calendar:adminRoute authorization
Upstream OAuth scopescalendar.readonly, calendar.eventsGoogle-side grants the user consents to (idp_passthrough mode); the service-account flow doesn't use these

See Google Workspace: multi-connector setup for how calendar's scopes compose with drive and gmail on one Google IdP.

Manifest reference

  • ID: identos.google-calendar
  • Version: 1.1.0
  • Resource type: urn:connector:identos:google-calendar

Supported auth modes

TypeDetails
idp_passthroughrequires IdP google
google_sasetup fields: sa_key_env, domain

Setup fields

IDLabelDefaultSecret?Notes
base_urlAPI base URLhttps://www.googleapis.comno
upstream_auth.typeAuthenticationidp_passthroughnoidp_passthrough forwards each user's own Google OAuth token (recommended). google_sa uses a Workspace service account with domain-wide delegation — useful for shared / room calendars where no human caller is involved.
sa_key_envService account keyyesPick a secret containing the service-account JSON. Required only for the google_sa auth mode. / shown when upstream_auth.type == 'google_sa'
domainWorkspace domainnoplaceholder: example.com / Required only for the google_sa auth mode. / shown when upstream_auth.type == 'google_sa'

Scopes

Scope
calendar:read
calendar:events:write
calendar:admin

Routes

MethodPatternScopeResource template
GET/calendar/v3/users/me/calendarListcalendar:read
GET/calendar/v3/calendars/{calendar_id}calendar:readcalendar://{{calendar_id}}
GET/calendar/v3/calendars/{calendar_id}/eventscalendar:readcalendar://{{calendar_id}}
GET/calendar/v3/calendars/{calendar_id}/events/{event_id}calendar:readcalendar://{{calendar_id}}/event/{{event_id}}
POST/calendar/v3/calendars/{calendar_id}/eventscalendar:events:writecalendar://{{calendar_id}}
PATCH/calendar/v3/calendars/{calendar_id}/events/{event_id}calendar:events:writecalendar://{{calendar_id}}/event/{{event_id}}
DELETE/calendar/v3/calendars/{calendar_id}/events/{event_id}calendar:events:writecalendar://{{calendar_id}}/event/{{event_id}}
POST/calendar/v3/calendars/{calendar_id}/events/quickAddcalendar:events:writecalendar://{{calendar_id}}
POST/calendar/v3/freeBusycalendar:read
GET/calendar/v3/calendars/{calendar_id}/aclcalendar:admincalendar://{{calendar_id}}

MCP tools

NameScopeDescription
list_calendarscalendar:readList every calendar the authenticated user has on their calendar list (primary + shared + subscribed).
get_calendarcalendar:readGet a calendar's metadata (summary, timezone, description).
list_eventscalendar:readList events on a calendar. Supports time filters (timeMin/timeMax), single-event expansion, and free-text search.
get_eventcalendar:readGet a single event by ID.
create_eventcalendar:events:writeCreate a new event on a calendar. Provide either the Google Calendar event body (full schema) or the convenience fields summary/start/end/attendees.
update_eventcalendar:events:writeUpdate an event (partial). Only supplied fields are modified.
delete_eventcalendar:events:writeDelete an event. Recurring events: pass sendUpdates=all to notify attendees.
quick_add_eventcalendar:events:writeCreate an event from natural-language text (e.g. "Lunch with Alice Thursday 1pm"). Uses Calendar's quickAdd parser.
query_free_busycalendar:readQuery free/busy information for a set of calendars over a time window. Returns only busy intervals — no event details.
list_aclcalendar:adminList the access-control rules on a calendar (who it's shared with and how).

Operator data schema

Keys the operator can supply under data.pbac.operator.connectors["identos.google-calendar"].* — consumed by the connector's policy.

KeyTypeDescription
room_only_modebooleanWhen true, only calendars whose ID ends with @resource.calendar.google.com (Google Workspace resource/room calendars) are addressable. Useful for booking agents that should never touch human calendars.