Skip to main content
Version: Latest

Google Sheets

Proxy for the Google Sheets v4 REST API. Dual auth by design — like drive and calendar, the typical production setup runs the connector in one of two modes per managed resource:

  • idp_passthrough mode for human users who want an agent to read or edit spreadsheets they already own. Each request carries the caller's own OAuth grant.
  • google_sa mode (Workspace service account with domain-wide delegation) for headless workflows that read or write shared/team spreadsheets on a fixed identity's behalf.

Overview

Typical uses:

  • An agent reads a forecast tab and summarizes the numbers (get_values, batch_get_values).
  • A reporting bot appends rows to a tracking sheet (append_values) or rewrites a range (update_values).
  • A workflow spins up a fresh spreadsheet, adds a tab, and copies a template sheet into it (create_spreadsheet, batch_update, copy_sheet).

Two upstream-shape notes specific to Sheets:

  • No list endpoint. The Sheets API can't enumerate spreadsheets; discover spreadsheet IDs via the Google Drive connector (filter on mimeType = 'application/vnd.google-apps.spreadsheet'), then operate on the ID here.
  • Deletes go through batch_update. Deleting a sheet, row, column, or range is a deleteSheet/deleteDimension/deleteRange request object on batch_update; deleting an entire spreadsheet file is the Drive connector's job. update_values/append_values carry valueInputOption in the query string (RAW vs USER_ENTERED), and ranges use A1 notation (Sheet1!A1:C10).

Default policy

The connector ships policy/sheets.rego (package pbac.connectors.identos.google_sheets). It enforces:

1. IdP-routing subject obligation

subject_obligations contains obl if {
input.resource.type == "urn:connector:identos:google-sheets"
input.connector.upstream_auth.type == "idp_passthrough"
input.subject.idp_provider != "google"
obl := { "type": "require_authn_at", "idp": "google", ... }
}

Same pattern as google-drive/gmail — a caller from a non-Google session gets a step-up obligation before any passthrough Sheets call succeeds.

2. Blocked and read-only spreadsheets

Blocking a specific spreadsheet is operator config on the general file-access control, not a rule in this connector. An identity source matches a spreadsheet by its own id: ids in blocked are denied on reads and writes, ids in write_blocked are denied on writes only (update_values, append_values, clear_values, batch_clear_values, batch_update, copy_sheet), so reads still work. See File access control below for the shape — an identity source pools with any label or location source governing the same connector.

File access control

Spreadsheets can be gated by Drive Labels and/or by folder/shared-drive location — a spreadsheet is returnable via get_spreadsheet if it matches any governing source's approval (an approved label or an approved folder), and denied if it matches any source's blocked (pooled OR, deny-wins). This is configured through the shared file_access operator control, used across all Google file connectors (Docs, Sheets, Slides, Drive). Full mechanics (the pooled predicate, OR-combine and deny-wins, fail-closed rules) live in the File Access Control guide; for getting label/folder IDs and the required OAuth scopes, see the Google file access setup guide.

Configuration uses a two-level model:

  1. Define a policy per source — under pbac.operator.controls.file_access.sources, each source declares a type (label, location, or identity — the resource's own id), a required allowlist (any-of; file must match ≥1), a blocked denylist (file withheld if it matches any — always wins), and an optional write_blocked denylist that applies to mutating calls only. Approving a whole folder is a location source with the folder ID in required (Google Drive does not allow labels on folders):
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": {
"google-drive-labels": {
"type": "label",
"required": ["approved-for-ai"],
"blocked": ["restricted"]
}
},
"governed": {
"urn:connector:identos:google-sheets": ["google-drive-labels"]
}
}'
  1. Activate per connector — under governed, list (as an array) which sources govern each connector's resource type; all listed sources pool into one OR-of-approvals, deny-wins decision — a file is returnable if it matches any source's required and withheld if it matches any source's blocked. Omitting a connector leaves it ungoverned (inert; no check). Once a source is configured and a connector is governed by it, enforcement is fail-closed: reads that cannot verify the file's values are denied (403).

The control resolves spreadsheet IDs from tool invocations to fetch labels/location; file and scope requirements are documented in the spec at docs/superpowers/specs/2026-08-11-general-file-access-control-design.md.

Scope model

ScopeUsed for
PBAC scopes (internal)sheets:read, sheets:writeRoute authorization
Upstream OAuth scopesspreadsheetsGoogle-side grant the user consents to (idp_passthrough mode); the service-account flow uses the same scope on the SA

See Google Workspace: multi-connector setup for how sheets' scopes compose with drive, gmail, and calendar on a single Google IdP.

Manifest reference

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

Supported auth modes

TypeDetails
idp_passthroughrequires IdP google
google_sasetup fields: sa_key_env, domain

Setup fields

IDLabelDefaultSecret?Notes
base_urlAPI base URLhttps://sheets.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 impersonating a fixed user.
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
sheets:read
sheets:write

Routes

MethodPatternScopeResource template
POST/v4/spreadsheetssheets:write
GET/v4/spreadsheets/{spreadsheet_id}sheets:readsheets://{{spreadsheet_id}}
GET/v4/spreadsheets/{spreadsheet_id}/values/{range}sheets:readsheets://{{spreadsheet_id}}
GET/v4/spreadsheets/{spreadsheet_id}/values:batchGetsheets:readsheets://{{spreadsheet_id}}
PUT/v4/spreadsheets/{spreadsheet_id}/values/{range}sheets:writesheets://{{spreadsheet_id}}
POST/v4/spreadsheets/{spreadsheet_id}/values/{range}:appendsheets:writesheets://{{spreadsheet_id}}
POST/v4/spreadsheets/{spreadsheet_id}/values/{range}:clearsheets:writesheets://{{spreadsheet_id}}
POST/v4/spreadsheets/{spreadsheet_id}/values:batchClearsheets:writesheets://{{spreadsheet_id}}
POST/v4/spreadsheets/{spreadsheet_id}/sheets/{sheet_id}:copyTosheets:writesheets://{{spreadsheet_id}}
POST/v4/spreadsheets/{spreadsheet_id}:batchUpdatesheets:writesheets://{{spreadsheet_id}}

MCP tools

NameScopeDescription
create_spreadsheetsheets:writeCreate a new spreadsheet. Pass the Sheets Spreadsheet resource body (e.g. {properties:{title}, sheets:[...]}).
get_spreadsheetsheets:readGet a spreadsheet's metadata and (optionally) cell data. Use the includeGridData flag sparingly — it can be large.
get_valuessheets:readRead values from a single A1 range (e.g. "Sheet1!A1:C10").
batch_get_valuessheets:readRead values from multiple A1 ranges in one call.
update_valuessheets:writeOverwrite values in an A1 range. Pass values as a 2-D array; set valueInputOption (RAW or USER_ENTERED).
append_valuessheets:writeAppend rows after the last row of a table within the given A1 range.
clear_valuessheets:writeClear values (not formatting) from a single A1 range.
batch_clear_valuessheets:writeClear values from multiple A1 ranges in one call.
copy_sheetsheets:writeCopy a single sheet from this spreadsheet into another spreadsheet.
batch_updatesheets:writeApply one or more structural updates (add/delete sheet, insert/delete rows & columns, formatting, etc.) via Sheets batchUpdate request objects. This is also how you DELETE sheets/rows/columns/ranges.