Google Sheets
Arcade.dev LLM tools for Google Sheets.
Google Sheets Toolkit
The Google Sheets toolkit lets Arcade-powered LLM agents read, write, and manage Google Sheets spreadsheets and their associated Drive metadata via the Google APIs.
Capabilities
- Spreadsheet access & discovery: Search Drive for spreadsheets by title/content, batch-check access across multiple files before attempting reads, generate a Google Drive file-picker URL to prompt the user to grant access, and inspect workbook structure or read cell ranges with optional annotations, markdown/CSV/TSV export, and multi-table region detection.
- Read & data quality: Read cell data with per-cell annotations, scan for data issues (type mismatches, blank keys, duplicates, etc.) at the cell level with deterministic severity flags ready to feed back into formatting requests, and retrieve edit history (who, when) from Drive revisions.
- Write & edit: Create new spreadsheets or batch-edit existing ones via the full Sheets
batchUpdateAPI surface (updateCells,addSheet,sortRange,addConditionalFormatRule,autoResizeDimensions, and more), including typed cell values and formatting. - Comments & collaboration: List comment threads with reply previews, read full reply chains, create file-level comments, edit comment body or resolve/reopen status, add replies, and delete comments.
- Account context: Retrieve the authenticated user's profile, email, and Google Sheets permission context.
OAuth
This toolkit authenticates via OAuth 2.0 with Google. See the Arcade Google auth provider docs for setup, required scopes, and configuration details.
Secrets
ENABLE_GOOGLE_DRIVE_INLINE_PICKER_URL
A feature-flag secret that enables the inline Google Drive picker URL to be returned directly inside tool responses (e.g., in CheckSpreadsheetAccess's grant block) rather than requiring a separate GenerateGoogleFilePickerUrl call. This is not a credential from Google — it is an Arcade-side configuration value you set in your Arcade environment.
To enable it, set this secret to a truthy value (e.g., "true") in your Arcade secrets configuration. No external provider dashboard is involved; the value is managed entirely within Arcade.
See the Arcade tool secrets guide for how to define secrets, and the Arcade secrets dashboard to manage them.
Available tools(12)
| Tool name | Description | Secrets | |
|---|---|---|---|
Check whether this app can already read each of several spreadsheets, in one
batched pre-flight call, before attempting to read them.
Use this when the user references multiple spreadsheets so any that are not yet
accessible can be granted together in a single picker step, instead of hitting a
separate access error and grant prompt for each one. Each input may be a bare file id
or a full Google Sheets/Drive URL.
Returns ``spreadsheets`` (a per-id list with ``accessible``, the ``title`` and
``mime_type`` when the file was read, and a ``reason`` when not usable),
``all_accessible`` (true only when every id is an already-accessible spreadsheet),
``connected_account_email`` (the connected Google account, empty when unknown), and a
``grant`` block. ``grant`` is empty when nothing needs granting; otherwise it lists the
ungranted ids (``ungranted_ids``) plus, when the inline picker is enabled, a single
picker URL covering them all.
A ``reason`` of ``not_accessible_or_not_found`` is either a file not granted to this app
yet or one that does not exist (indistinguishable here) — the picker resolves the
former. ``not_a_spreadsheet`` is an accessible file of another type (a Doc, PDF, image,
or Excel/CSV file); granting cannot change a type, so for an Excel/CSV file ask the user
to open it in Google Sheets and use File, Save as Google Sheets, then share the
converted file. ``invalid_reference`` is an input that is not a Drive id or link at all;
ask the user to re-check it. | 1 | ||
Create a comment on a spreadsheet, edit a comment's body, or resolve/reopen it.
Comments are created at the file level: the Drive API cannot anchor a NEW Sheets comment to a
specific cell or range. Cell/range-anchored comments made in the Sheets UI are still readable
via list_spreadsheet_comments (which returns their anchor). Editing a comment's body is
allowed only for the comment's author. | 1 | ||
Create a new spreadsheet or batch-edit an existing one.
Omit `spreadsheet_id` to create; provide it to edit. All writes flow through
`requests[]` — typed operations like updateCells, addSheet, sortRange,
addConditionalFormatRule, autoResizeDimensions, and more.
For updateCells use ExtendedValue with an explicit type field (stringValue,
numberValue, boolValue, formulaValue).
By default, build clean, professional-looking tables with restrained, consistent
formatting and plain-text tab names/headers (no emojis); only use emojis or
decorative styling when the user explicitly asks for it. | 1 | ||
Delete a comment from a spreadsheet.
Only the comment's author can delete it (enforced by Google Drive); deleting marks the
whole thread (the comment and its replies) as deleted. | 1 | ||
Generate a URL where the user can grant this app access to spreadsheets.
Opens Google's first-party Drive picker, filtered to Google Sheets, where the user
browses and selects which spreadsheets to share with this application — it is not a
sign-in or credential prompt.
Use this when a prior tool reported that a file was not found or access was denied, and
the user expects the file to exist. After the user completes the picker flow, retry the
prior operation. | |||
Report who edited a spreadsheet and when, from Google Drive revisions.
Reports the "who" and "when" only — not which cells changed, and it can't revert.
'summary' (default) answers "who last edited this and when" (read from the file's head,
so always accurate), plus per-window aggregates (revisions read, contributors, first
edit) and a preview of recent edits — computed over a bounded window of history per call.
These aggregates describe the whole history only when `is_incomplete` is false; it is
true when the scan was resumed from a token and/or more history remains. To answer
"when was this first edited?" or "who contributed?" reliably, call from the beginning
(no `pagination_token`) and check `is_incomplete` is false. `pagination_token` is
returned when more pages remain so you can resume.
'list' returns one page of individual revisions, oldest first. Drive can't sort
newest-first, so the most recent individual revisions are on the final page. | 1 | ||
Inspect a Google Sheets spreadsheet's structure or read a range of cells.
Use the default 'structure' mode to understand a workbook cheaply before reading.
Switch to 'read' mode to pull a range as a grid of rows, optionally with
per-cell annotations and a rendered markdown/csv/tsv export.
In 'read' mode the response's per-tab 'sheets' block reports only tab identity and
the allocated grid; its scan-derived fields (used_range, populated_cell_count,
formula_cell_count, first_row, table_regions) are placeholders (0/empty) because read
mode does not scan the tab — they do NOT mean the tab is empty or that it has no
tables. The data you read is in the top-level 'range' and 'rows'. Call 'structure'
mode for those aggregates and for the workbook's charts, merges, protected ranges, and
conditional formats.
Workflow for a tab that holds multiple tables, or a table that does not start at A1:
call 'structure' first and use that tab's estimated 'table_regions' to choose the
a1_range to read or filter, so you target one table instead of a glued multi-table
range.
Always check the response's top-level 'warnings' list: read mode reports there when a
result was capped or trimmed (cell budget, the per-cell annotation cap, or an empty
filter scan) and tells you how to recover (page 'next_range', narrow 'a1_range',
'select_columns', or request fewer annotation kinds). | 1 | ||
List a spreadsheet's comment threads, or the full replies of a single comment.
In 'comments' mode each comment includes up to a few trimmed reply previews plus the total reply_count; use 'thread' mode for a comment's complete reply list. Without filters/ordering, pagination walks every comment. Client-side filters (has_replies, resolved) and order_by are applied only within a bounded scan of the first 500 comments, so on larger sheets drop them and page through everything with the native (unbounded) pagination. Each comment's Drive anchor is returned when it was cell/range-anchored in the Sheets UI; comments created via the API are file-level. Filtering, ordering, and offset pagination are best-effort: results can drift if comments are added or removed between paginated calls. | 1 | ||
Add a reply to an existing comment on a spreadsheet.
To resolve or reopen the comment instead, use comment_on_spreadsheet with a status. | 1 | ||
Deterministically flag 'weird'/bad cells in spreadsheet data.
No LLM judgement: the same input always returns the same flags. Each cell-level finding
carries a coord, a 0-based row_index/column_index (ready for a Sheets GridRange), the rule,
a severity (high -> red, medium/low -> yellow), and a note-ready reason — so the output
drops straight into an annotate/format recipe. In the default `mode='grouped'` these are
aggregated per rule+column within each table into `groups` (with A1 `coords`); use
`mode='list'` to get every flagged cell in `flags` with its 0-based indices.
Provide `spreadsheet_id` to scan a live sheet (scan one tab via sheet_id/sheet_title, or
every tab when both are omitted). Set `orientation='rows'` for transposed tables whose
fields run down a column instead of across a row. Findings come back as flags (cell-level,
high certainty) and alerts (table-level, lower certainty), grouped sheet -> table -> rule.
In all-sheets mode an unreadable tab never aborts the scan: its title is collected in
`failed_sheets` (and echoed as a `warnings` entry) while every other tab still returns.
`failed_sheets` is empty for a single-tab scan and whenever every tab reads cleanly. | 1 | ||
Searches for spreadsheets in the user's Google Drive based on the titles and content and
returns the title, ID, and URL for each matching spreadsheet.
Does not return the content/data of the sheets in the spreadsheets - only the metadata.
Excludes spreadsheets that are in the trash. | 1 | ||
Get comprehensive user profile and Google Sheets environment information.
This tool provides detailed information about the authenticated user including
their name, email, profile picture, Google Sheets access permissions, and other
important profile details from Google services. |
Selected tools
No tools selected.
Click "Show all tools" to add tools.
Requirements
Select tools to see requirements
GoogleSheets.CheckSpreadsheetAccess
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Check whether this app can already read each of several spreadsheets, in one batched pre-flight call, before attempting to read them. Use this when the user references multiple spreadsheets so any that are not yet accessible can be granted together in a single picker step, instead of hitting a separate access error and grant prompt for each one. Each input may be a bare file id or a full Google Sheets/Drive URL. Returns ``spreadsheets`` (a per-id list with ``accessible``, the ``title`` and ``mime_type`` when the file was read, and a ``reason`` when not usable), ``all_accessible`` (true only when every id is an already-accessible spreadsheet), ``connected_account_email`` (the connected Google account, empty when unknown), and a ``grant`` block. ``grant`` is empty when nothing needs granting; otherwise it lists the ungranted ids (``ungranted_ids``) plus, when the inline picker is enabled, a single picker URL covering them all. A ``reason`` of ``not_accessible_or_not_found`` is either a file not granted to this app yet or one that does not exist (indistinguishable here) — the picker resolves the former. ``not_a_spreadsheet`` is an accessible file of another type (a Doc, PDF, image, or Excel/CSV file); granting cannot change a type, so for an Excel/CSV file ask the user to open it in Google Sheets and use File, Save as Google Sheets, then share the converted file. ``invalid_reference`` is an input that is not a Drive id or link at all; ask the user to re-check it.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheets | array<string> | Required | The spreadsheets to check access for, each given as a bare spreadsheet id or a full Google Sheets/Drive URL (the id is extracted from the URL). Provide at most 50 per call; split larger lists across multiple calls. |
Requirements
Output
json— Per-id accessibility (`spreadsheets`), an `all_accessible` flag, the `connected_account_email` (the Google account this app is connected through), and a `grant` block — empty when nothing needs granting, otherwise listing the ungranted ids with one consolidated picker URL covering them all.GoogleSheets.CommentOnSpreadsheet
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Create a comment on a spreadsheet, edit a comment's body, or resolve/reopen it. Comments are created at the file level: the Drive API cannot anchor a NEW Sheets comment to a specific cell or range. Cell/range-anchored comments made in the Sheets UI are still readable via list_spreadsheet_comments (which returns their anchor). Editing a comment's body is allowed only for the comment's author.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet to comment on. |
comment_id | string | Optional | Omit to CREATE a new comment. Provide an existing comment id to edit it (pass content) or to resolve/reopen it (pass status). |
content | string | Optional | The comment text. Required when creating. When editing an existing comment (comment_id set, no status) this replaces the body (author-only). When a status is set, this is the optional text of the resolving/reopening reply. |
status | string | Optional | Resolve or reopen an existing comment (requires comment_id). Implemented as a reply with an action. Omit to create or edit instead.resolvereopen |
Requirements
Output
json— The affected comment id, any created reply id, the action taken, the resolved state, and the spreadsheet URL.GoogleSheets.CreateOrEditSpreadsheet
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Create a new spreadsheet or batch-edit an existing one. Omit `spreadsheet_id` to create; provide it to edit. All writes flow through `requests[]` — typed operations like updateCells, addSheet, sortRange, addConditionalFormatRule, autoResizeDimensions, and more. For updateCells use ExtendedValue with an explicit type field (stringValue, numberValue, boolValue, formulaValue). By default, build clean, professional-looking tables with restrained, consistent formatting and plain-text tab names/headers (no emojis); only use emojis or decorative styling when the user explicitly asks for it.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
requests | array<json> | Optional | A list of Google Sheets `spreadsheets.batchUpdate` request objects. Each object must have exactly one key naming the operation. Examples: FIELDS MASK: updateCells, repeatCell, updateSheetProperties, and updateDimensionProperties take a `fields` mask listing which sub-fields to write — anything you set but don't name is silently ignored. You can OMIT `fields` and the tool auto-derives it from the data you provide (recommended). Pass an explicit `fields` only for surgical edits, or `fields: "*"` to overwrite every sub-field (clearing ones you didn't provide). updateCells — write typed values and formatting to a range. Use `range` OR `start` to anchor the write. Values must be wrapped in `userEnteredValue` with an explicit type field (stringValue, numberValue, boolValue, formulaValue). `fields` is auto-derived when omitted: {"updateCells": {"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1, "startColumnIndex": 0, "endColumnIndex": 3}, "rows": [{"values": [{"userEnteredValue": {"stringValue": "Name"}, "userEnteredFormat": {"textFormat": {"bold": true}}}, {"userEnteredValue": {"numberValue": 42}}, {"userEnteredValue": {"formulaValue": "=SUM(B1:B10)"}}]}], "fields": "userEnteredValue,userEnteredFormat.textFormat.bold"}} repeatCell — apply one CellData to every cell in a range. Good for painting formatting, notes, or validation without enumerating rows: {"repeatCell": {"range": {"sheetId": 0, "startRowIndex": 1, "endRowIndex": 100}, "cell": {"userEnteredFormat": {"backgroundColorStyle": {"rgbColor": {"red": 0.95, "green": 0.95, "blue": 0.95}}}}, "fields": "userEnteredFormat.backgroundColorStyle"}} updateBorders — set per-edge borders. Each side takes a Border with a style (SOLID, DASHED, DOTTED, NONE, SOLID_MEDIUM, SOLID_THICK, DOUBLE): {"updateBorders": {"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 3, "startColumnIndex": 0, "endColumnIndex": 3}, "top": {"style": "SOLID_THICK"}, "bottom": {"style": "SOLID_THICK"}, "left": {"style": "SOLID"}, "right": {"style": "SOLID"}, "innerHorizontal": {"style": "DASHED"}, "innerVertical": {"style": "DASHED"}}} addSheet — create a new tab. Omit sheetId to let Google assign one; read the new ID from created_resources in the reply: {"addSheet": {"properties": {"title": "Q2", "index": 1, "gridProperties": {"rowCount": 200, "columnCount": 26, "frozenRowCount": 1}}}} deleteSheet — remove a tab permanently by sheetId: {"deleteSheet": {"sheetId": 1234567890}} duplicateSheet — clone a tab. newSheetId is auto-assigned when omitted: {"duplicateSheet": {"sourceSheetId": 0, "insertSheetIndex": 1, "newSheetName": "Copy of Q1"}} updateSheetProperties — rename, reorder, freeze rows/columns, or recolor a tab. fields is rooted at properties: {"updateSheetProperties": {"properties": {"sheetId": 0, "gridProperties": {"frozenRowCount": 1}}, "fields": "gridProperties.frozenRowCount"}} updateSpreadsheetProperties — rename the whole spreadsheet (file) or change workbook-level properties. Use this (not updateSheetProperties) to change the spreadsheet title: {"updateSpreadsheetProperties": {"properties": {"title": "Q3 Report"}, "fields": "title"}} insertDimension — add rows or columns. Both startIndex and endIndex are REQUIRED: {"insertDimension": {"range": {"sheetId": 0, "dimension": "ROWS", "startIndex": 2, "endIndex": 4}, "inheritFromBefore": true}} deleteDimension — remove rows or columns. Apply largest-index first within a batch to avoid index shift: {"deleteDimension": {"range": {"sheetId": 0, "dimension": "COLUMNS", "startIndex": 5, "endIndex": 8}}} mergeCells — mergeType is MERGE_ALL, MERGE_COLUMNS, or MERGE_ROWS: {"mergeCells": {"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1, "startColumnIndex": 0, "endColumnIndex": 5}, "mergeType": "MERGE_ALL"}} unmergeCells — range must not partially span an existing merge: {"unmergeCells": {"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1, "startColumnIndex": 0, "endColumnIndex": 5}}} findReplace — scope with ONE of range, sheetId, or allSheets: {"findReplace": {"find": "TBD", "replacement": "N/A", "matchCase": false, "matchEntireCell": true, "allSheets": true}} addNamedRange — create a workbook-scoped named range. Server assigns namedRangeId: {"addNamedRange": {"namedRange": {"name": "revenue", "range": {"sheetId": 0, "startRowIndex": 1, "endRowIndex": 1000, "startColumnIndex": 1, "endColumnIndex": 2}}}} addProtectedRange — lock a range. warningOnly=true gives soft protection: {"addProtectedRange": {"protectedRange": {"range": {"sheetId": 0, "startRowIndex": 0, "endRowIndex": 1}, "description": "Do not edit headers", "warningOnly": true}}} setDataValidation — attach a validation rule to a range. Omit rule to clear: {"setDataValidation": {"range": {"sheetId": 0, "startRowIndex": 1, "endRowIndex": 100, "startColumnIndex": 2, "endColumnIndex": 3}, "rule": {"condition": {"type": "ONE_OF_LIST", "values": [{"userEnteredValue": "PENDING"}, {"userEnteredValue": "DONE"}]}, "strict": true, "showCustomUi": true}}} addConditionalFormatRule — insert a conditional-format rule at given index. Use booleanRule for categorical formatting: {"addConditionalFormatRule": {"index": 0, "rule": {"ranges": [{"sheetId": 0, "startRowIndex": 1, "endRowIndex": 100}], "booleanRule": {"condition": {"type": "NUMBER_LESS", "values": [{"userEnteredValue": "0"}]}, "format": {"backgroundColorStyle": {"rgbColor": {"red": 1.0, "green": 0.9, "blue": 0.9}}}}}}} addChart — embed a chart. Server assigns chartId in the reply: {"addChart": {"chart": {"spec": {"title": "Revenue by quarter", "basicChart": {"chartType": "COLUMN", "domains": [{"domain": {"sourceRange": {"sources": [{"sheetId": 0, "startRowIndex": 0, "endRowIndex": 5, "startColumnIndex": 0, "endColumnIndex": 1}]}}}], "series": [{"series": {"sourceRange": {"sources": [{"sheetId": 0, "startRowIndex": 0, "endRowIndex": 5, "startColumnIndex": 1, "endColumnIndex": 2}]}}}]}}, "position": {"newSheet": true}}}} sortRange — sort rows in a range by one or more columns. sortSpecs is ordered by priority (first = primary sort key). sortOrder is ASCENDING or DESCENDING: {"sortRange": {"range": {"sheetId": 0, "startRowIndex": 1, "endRowIndex": 100, "startColumnIndex": 0, "endColumnIndex": 5}, "sortSpecs": [{"dimensionIndex": 0, "sortOrder": "ASCENDING"}, {"dimensionIndex": 2, "sortOrder": "DESCENDING"}]}} autoResizeDimensions — resize columns or rows to fit their content. dimension is COLUMNS or ROWS: {"autoResizeDimensions": {"dimensions": {"sheetId": 0, "dimension": "COLUMNS", "startIndex": 0, "endIndex": 3}}} NOTE: the tool automatically runs all autoResizeDimensions requests in a second batchUpdate call after all other requests have been applied. This ensures the resize measures post-write cell contents, including spilling formulas (ARRAYFORMULA, SEQUENCE, MAKEARRAY, QUERY) whose spill values only exist after the first call returns. If the resize call fails (e.g. transient error), writes are unaffected and a warning is returned instead of an error. updateDimensionProperties (pixelSize) sets an explicit pixel width and does not need this treatment — it can stay in the same batch as writes. updateDimensionProperties — set explicit pixel size or hide a row/column. fields is a mask rooted at DimensionProperties: {"updateDimensionProperties": {"range": {"sheetId": 0, "dimension": "COLUMNS", "startIndex": 1, "endIndex": 2}, "properties": {"pixelSize": 200}, "fields": "pixelSize"}} |
spreadsheet_id | string | Optional | ID of an existing spreadsheet to edit. Omit to create a new spreadsheet. |
title | string | Optional | Title for a newly created spreadsheet. Ignored when spreadsheet_id is provided. Defaults to 'Untitled spreadsheet'. |
Requirements
Output
json— Spreadsheet state after the operation.GoogleSheets.DeleteComment
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Delete a comment from a spreadsheet. Only the comment's author can delete it (enforced by Google Drive); deleting marks the whole thread (the comment and its replies) as deleted.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet the comment belongs to. |
comment_id | string | Required | The id of the comment to delete. |
Requirements
Output
json— Confirmation of deletion and the spreadsheet URL.GoogleSheets.GenerateGoogleFilePickerUrl
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Generate a URL where the user can grant this app access to spreadsheets. Opens Google's first-party Drive picker, filtered to Google Sheets, where the user browses and selects which spreadsheets to share with this application — it is not a sign-in or credential prompt. Use this when a prior tool reported that a file was not found or access was denied, and the user expects the file to exist. After the user completes the picker flow, retry the prior operation.
Parameters
No parameters required.
Requirements
Output
json— Google File Picker URL for user file selection and permission grantingGoogleSheets.GetSpreadsheetEditHistory
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Report who edited a spreadsheet and when, from Google Drive revisions. Reports the "who" and "when" only — not which cells changed, and it can't revert. 'summary' (default) answers "who last edited this and when" (read from the file's head, so always accurate), plus per-window aggregates (revisions read, contributors, first edit) and a preview of recent edits — computed over a bounded window of history per call. These aggregates describe the whole history only when `is_incomplete` is false; it is true when the scan was resumed from a token and/or more history remains. To answer "when was this first edited?" or "who contributed?" reliably, call from the beginning (no `pagination_token`) and check `is_incomplete` is false. `pagination_token` is returned when more pages remain so you can resume. 'list' returns one page of individual revisions, oldest first. Drive can't sort newest-first, so the most recent individual revisions are on the final page.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet to get the edit history for. |
mode | string | Optional | 'summary' (default): the latest edit, plus per-window aggregates (revisions read, contributors, first edit) that cover the whole history only when is_incomplete is false, and a preview of recent edits. 'list': one page of individual revisions.summarylist |
limit | integer | Optional | Max revisions per page in 'list' mode. Between 1 and 50. Defaults to 20. Ignored in 'summary' mode. |
pagination_token | string | Optional | Token from a previous response's pagination_token, to continue reading more history. Works in both modes. |
Requirements
Output
json— Edit history: who modified the spreadsheet and when. Always has spreadsheet_id and mode. 'summary' adds an accurate last_modified_time/last_modified_by, best-effort window_revision_count/contributors/first_modified_time, recent_edits, and is_incomplete. 'list' adds a page of revisions with revisions_count, limit, ordering, has_next_page. Both modes return a pagination_token when more history remains.GoogleSheets.InspectSpreadsheet
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Inspect a Google Sheets spreadsheet's structure or read a range of cells. Use the default 'structure' mode to understand a workbook cheaply before reading. Switch to 'read' mode to pull a range as a grid of rows, optionally with per-cell annotations and a rendered markdown/csv/tsv export. In 'read' mode the response's per-tab 'sheets' block reports only tab identity and the allocated grid; its scan-derived fields (used_range, populated_cell_count, formula_cell_count, first_row, table_regions) are placeholders (0/empty) because read mode does not scan the tab — they do NOT mean the tab is empty or that it has no tables. The data you read is in the top-level 'range' and 'rows'. Call 'structure' mode for those aggregates and for the workbook's charts, merges, protected ranges, and conditional formats. Workflow for a tab that holds multiple tables, or a table that does not start at A1: call 'structure' first and use that tab's estimated 'table_regions' to choose the a1_range to read or filter, so you target one table instead of a glued multi-table range. Always check the response's top-level 'warnings' list: read mode reports there when a result was capped or trimmed (cell budget, the per-cell annotation cap, or an empty filter scan) and tells you how to recover (page 'next_range', narrow 'a1_range', 'select_columns', or request fewer annotation kinds).
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet to inspect. |
mode | string | Optional | What to return. 'structure' (default) gives a cheap workbook overview: every tab's ids, allocated grid, frozen panes, merges, charts, protected ranges, conditional-format counts, real used range, first row, and ESTIMATED table_regions (A1 ranges of distinct data blocks per tab — a heuristic for spotting multiple tables in one tab; scope a1_range to one of these to read or filter a single table; empty for tabs too large to peek). 'read' pulls cell data from one tab.structureread |
sheet_id | integer | Optional | Read mode only: select the tab by its numeric sheetId. Mutually exclusive with sheet_title. Defaults to the first tab when both are omitted. |
sheet_title | string | Optional | Read mode only: select the tab by name. Mutually exclusive with sheet_id. Defaults to the first tab when both are omitted. |
a1_range | string | Optional | Read mode only: the range of cells to pull, in A1 notation (e.g. 'A1:F100'), WITHIN the selected tab — the tab is chosen by sheet_id/sheet_title, and any sheet prefix here (e.g. 'Other!A1:B2') is ignored. Defaults to the tab's used range. This is also the paging knob — request the next range to page. |
annotations | array<string> | Optional | Read mode only: per-cell extras to include — pass only the kinds you need (e.g. ['formulas','notes']); each extra kind adds payload. Omit or leave empty to return values only (cheaper). Returned sparsely — one entry only per cell that carries a requested extra — and capped at the first 500 entries (row-major). Over that cap a warning is returned; rows may extend past the annotated slice, so a missing annotation beyond the cap is NOT authoritative — re-read a narrower a1_range, use select_columns, or request fewer kinds to confirm.formulasnotesnumber_formatsdata_validationconditional_formatsmergestypeshyperlinksprotectedspill |
export_as | string | Optional | Read mode only: also render the returned values as text. Omit to return structured values only. csv/tsv are lossless; markdown is display-oriented (in-cell newlines become <br>, pipes are escaped).markdowncsvtsv |
value_render | string | Optional | Read mode only: 'formatted' (default) returns display strings like '$1,234.50'; 'unformatted' returns raw values suitable for math.formattedunformatted |
max_length | integer | Optional | Read mode only: cap each returned cell string at this many characters. A longer cell becomes '<first chars>…(+N chars)' (the suffix is not counted; N = hidden chars). Pass 0 for full, untruncated strings; a positive value below the floor (or negative) clamps up to the floor. Filtering still matches the full cell value. Defaults to a small cap (50). |
max_rows | integer | Optional | Read mode only: maximum rows to return. Sets truncated=True when the range has more rows; pass the returned next_range as a1_range to page. When filtering, this bounds the rows SCANNED per page (matches may be fewer, even 0 — page until next_range is empty). Also capped so rows x columns stays within 4000 cells: a wide range returns fewer rows than requested (with a warning) and pages the rest. Defaults to 200. |
filter_conditions | array<json> | Optional | Read mode only: keep only rows matching these conditions. Each is {column, op, value} where column is the spreadsheet column LETTER (e.g. 'C'), NOT the header name, and must be inside a1_range. Ops: eq/ne (exact string), contains/not_contains (case-insensitive substring), gt/gte/lt/lte (NUMERIC only — text columns match nothing), blank/not_blank (value is ignored — pass ''). Numeric ops parse currency like $1,234.50, but NOT percents (21%) or other formatted text — set value_render='unformatted' and compare against the underlying number (percents are stored as fractions, e.g. 0.21 for 21%). A warning is returned when a numeric filter matches nothing it scanned. Scans within a1_range only — page next_range for completeness, and scope a1_range to a single homogeneous table (use structure mode's table_regions to find each table's range; exclude header/title rows, which would otherwise be filtered as data). |
filter_combine | string | Optional | Read mode only: how to combine multiple filter_conditions — a single top-level 'and'/'or' applied to all conditions (no nested grouping or mixed and/or). Defaults to 'and'.andor |
select_columns | array<string> | Optional | Read mode only: return only these columns, by spreadsheet column LETTER (not header name), in this order. Defaults to all columns in a1_range. |
include_headers | boolean | Optional | Structure mode only: include each tab's first row in the overview. Defaults to True. |
Requirements
Output
json— The requested structure overview or range data.GoogleSheets.ListSpreadsheetComments
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
List a spreadsheet's comment threads, or the full replies of a single comment. In 'comments' mode each comment includes up to a few trimmed reply previews plus the total reply_count; use 'thread' mode for a comment's complete reply list. Without filters/ordering, pagination walks every comment. Client-side filters (has_replies, resolved) and order_by are applied only within a bounded scan of the first 500 comments, so on larger sheets drop them and page through everything with the native (unbounded) pagination. Each comment's Drive anchor is returned when it was cell/range-anchored in the Sheets UI; comments created via the API are file-level. Filtering, ordering, and offset pagination are best-effort: results can drift if comments are added or removed between paginated calls.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet whose comments to list. |
mode | string | Optional | 'comments' (default) lists top-level comments, each with a capped reply preview and a reply_count. 'thread' lists the FULL replies of one comment (set comment_id).commentsthread |
comment_id | string | Optional | Required when mode='thread': the comment whose replies to list. |
limit | integer | Optional | Max comments (or replies, in thread mode) to return. Clamped to [1, 50]. |
page_token | string | Optional | Opaque token from a previous call's page_token to fetch the next page. |
include_deleted | boolean | Optional | Include deleted comments/replies (their bodies are blank). Defaults to False. |
modified_after | string | Optional | Server-side filter: only comments modified at/after this RFC3339 time (e.g. '2025-01-01T00:00:00Z'). Comments mode only. |
has_replies | boolean | Optional | Client-side filter (comments mode): keep only comments that have (True) or lack (False) replies. |
resolved | boolean | Optional | Client-side filter (comments mode): keep only resolved (True) or unresolved (False) comments. |
comment_ids | array<string> | Optional | Fetch exactly these comments by id (comments mode), instead of paging. Replaces a dedicated get tool. At most 50 ids per call, and not combined with page_token. |
order_by | string | Optional | Client-side ordering (comments mode) by created/modified time, ascending or descending. Defaults to Drive's native order.created_time_asccreated_time_descmodified_time_ascmodified_time_desc |
max_length | integer | Optional | Cap each returned comment/reply body (and quoted text) at this many characters. A longer body becomes '<prefix>…(+N chars)' (suffix not counted; N = hidden chars). Pass 0 for full, untruncated text; a positive value below the floor (or negative) clamps up to the floor. Filtering still matches the FULL text. Defaults to 280. |
Requirements
Output
json— The matching comments (or replies) with pagination info.GoogleSheets.ReplyToComment
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Add a reply to an existing comment on a spreadsheet. To resolve or reopen the comment instead, use comment_on_spreadsheet with a status.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet the comment belongs to. |
comment_id | string | Required | The id of the comment to reply to. |
reply_text | string | Required | The text of the reply. |
Requirements
Output
json— The created reply id, its comment id, and the URL.GoogleSheets.ScanForDataIssues
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Deterministically flag 'weird'/bad cells in spreadsheet data. No LLM judgement: the same input always returns the same flags. Each cell-level finding carries a coord, a 0-based row_index/column_index (ready for a Sheets GridRange), the rule, a severity (high -> red, medium/low -> yellow), and a note-ready reason — so the output drops straight into an annotate/format recipe. In the default `mode='grouped'` these are aggregated per rule+column within each table into `groups` (with A1 `coords`); use `mode='list'` to get every flagged cell in `flags` with its 0-based indices. Provide `spreadsheet_id` to scan a live sheet (scan one tab via sheet_id/sheet_title, or every tab when both are omitted). Set `orientation='rows'` for transposed tables whose fields run down a column instead of across a row. Findings come back as flags (cell-level, high certainty) and alerts (table-level, lower certainty), grouped sheet -> table -> rule. In all-sheets mode an unreadable tab never aborts the scan: its title is collected in `failed_sheets` (and echoed as a `warnings` entry) while every other tab still returns. `failed_sheets` is empty for a single-tab scan and whenever every tab reads cleanly.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_id | string | Required | The id of the spreadsheet to scan. Scan one tab via sheet_id/sheet_title, or every tab when both are omitted. |
sheet_id | integer | Optional | Scan only this tab (by numeric sheetId). Mutually exclusive with sheet_title. Omit both to scan every tab, grouped by sheet. |
sheet_title | string | Optional | Scan only this tab (by name). Mutually exclusive with sheet_id. Omit both to scan every tab. |
a1_range | string | Optional | Single-sheet only: limit the analysis window (e.g. 'A1:F100'). Table detection still runs inside it; scope it to a single table's range for a precise scan. Defaults to the tab's used range. |
treat_range_as_single_table | boolean | Optional | Single-sheet only: treat the whole a1_range as ONE table, skipping auto-detection. Use when detection would over-split a table that has an interior blank row. Defaults to False. |
mode | string | Optional | 'grouped' (default) aggregates findings per rule+column within each table with counts; 'list' enumerates every flagged cell.listgrouped |
rules | array<string> | Optional | Which deterministic checks to run. Omit to run every check. Each is fully reproducible (no LLM judgement).error_valuetext_sentinelparenthesized_numbernumber_stored_as_textwhitespacetype_outlierformula_outlierdate_serialgaprepeated_headerinconsistent_column |
has_header | boolean | Optional | Treat each detected table's first row as labels (never flagged as a type outlier). Defaults to True. |
orientation | string | Optional | 'columns' (default): records are rows, fields are columns. 'rows': the table is transposed — records are columns and fields are rows (row labels down column A). Applies to the whole scan, not per-table (one setting for every table on the tab). Coords are always reported in the sheet's real coordinates.columnsrows |
max_items_per_group | integer | Optional | Grouped mode: max cell coords listed per rule+column (within a table) before an 'omitted' count. Defaults to 10, hard-capped at 50. |
max_rows | integer | Optional | Max rows scanned per tab (applies to every scanned tab). Defaults to 200, floored to 1. |
Requirements
Output
json— Deterministic data-issue flags, grouped sheet -> table -> rule.GoogleSheets.SearchSpreadsheets
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Searches for spreadsheets in the user's Google Drive based on the titles and content and returns the title, ID, and URL for each matching spreadsheet. Does not return the content/data of the sheets in the spreadsheets - only the metadata. Excludes spreadsheets that are in the trash.
Parameters
| Parameter | Type | Req. | Description |
|---|---|---|---|
spreadsheet_contains | array<string> | Optional | Keywords or phrases that must be in the spreadsheet title. Provide a list of keywords or phrases if needed. |
spreadsheet_not_contains | array<string> | Optional | Keywords or phrases that must NOT be in the spreadsheet title. Provide a list of keywords or phrases if needed. |
search_only_in_shared_drive_id | string | Optional | The ID of the shared drive to restrict the search to. If provided, the search will only return spreadsheets from this drive. Defaults to None, which searches across all drives. |
include_shared_drives | boolean | Optional | Whether to include spreadsheets from shared drives. Defaults to False (searches only in the user's 'My Drive'). |
include_organization_domain_spreadsheets | boolean | Optional | Whether to include spreadsheets from the organization's domain. This is applicable to admin users who have permissions to view organization-wide spreadsheets in a Google Workspace account. Defaults to False. |
order_by | array<string> | Optional | Sort order. Defaults to listing the most recently modified spreadsheets first. If spreadsheet_contains or spreadsheet_not_contains is provided, then the order_by will be ignored.createdTimecreatedTime descfolderfolder descmodifiedByMeTimemodifiedByMeTime descmodifiedTimemodifiedTime descnamename descname_naturalname_natural descquotaBytesUsedquotaBytesUsed descrecencyrecency descsharedWithMeTimesharedWithMeTime descstarredstarred descviewedByMeTimeviewedByMeTime desc |
limit | integer | Optional | The maximum number of spreadsheets to list. Defaults to 10. Max is 50 |
pagination_token | string | Optional | The pagination token to continue a previous request |
Requirements
Output
json— A dictionary containing the title, ID, and URL for each matching spreadsheet. Also contains a pagination token if there are more spreadsheets to list.GoogleSheets.WhoAmI
Execution hints
Signals for MCP clients and agents about how this tool behaves.
Reads data without modifying any state in the target system.
May permanently delete or overwrite data in the target system.
Repeated calls with the same inputs produce no additional effect.
Communicates with external APIs, databases, or other services.
Get comprehensive user profile and Google Sheets environment information. This tool provides detailed information about the authenticated user including their name, email, profile picture, Google Sheets access permissions, and other important profile details from Google services.
Parameters
No parameters required.
Requirements
Output
json— Get comprehensive user profile and Google Sheets environment information.