sheets-mcp docs
Reference

Glossary

Key terms used across sheets-mcp docs. Useful for agents reasoning about tool selection and data models.

A1 notation

The standard spreadsheet range reference format used in all sheets-mcp range parameters.

Sheet1!A1:D10     — rows 1–10, columns A–D in "Sheet1"
Sheet1!A:D        — entire columns A–D (all rows)
Sheet1!1:1        — entire row 1 (header row)
'My Sheet'!A1:Z   — sheet name with spaces (single-quoted)
B2:C3             — relative range (no sheet name — defaults to first tab)

All range parameters in sheets-mcp tools use A1 notation. The sheet name prefix is strongly recommended — without it, Sheets API defaults to the first tab.


sheet_data CTE

The virtual table name used inside analyze_range and transform_range SQL queries.

-- You write:
SELECT data->>'Region', SUM((data->>'Revenue')::numeric)
FROM sheet_data GROUP BY 1

-- sheets-mcp wraps it as:
WITH sheet_data AS (
  SELECT value AS data FROM jsonb_array_elements($1::jsonb)
)
SELECT * FROM (<your query>) AS subquery

The data column is JSONB. Each row is a JSON object with header names as string keys and cell values as string values. All values are strings — cast before arithmetic.


_schema

The sheet structure object returned alongside data in read_range and analyze_range responses.

{
  "layout": { "frozenRows": 1, "frozenColumns": 0 },
  "semantics": ["Has 2 conditional format rules"],
  "protectedRanges": [
    { "range": { "startRowIndex": 0, "endRowIndex": 1 }, "warningOnly": false, "description": "Header row" }
  ],
  "arrayFormulaColumns": ["C"],
  "warnings": ["⚠ Column C contains ARRAYFORMULA — do not write to C2:C"],
  "mergedTitleRows": [],
  "constraints": []
}

Agents should check arrayFormulaColumns and protectedRanges before calling any write tool on the same range.


sheet_snapshots

The Postgres table that serves as sheets-mcp's dual-purpose cache:

  • Schema cache — sheet structure (_schema) keyed by '__schema__', TTL = 300 seconds
  • Range cache — JSONB row data keyed by normalized A1 range, TTL = 60 seconds

Both caches are cleared together after every successful write.


write_history

The Postgres table that stores pre-write snapshots before every write_range and transform_range call. Max 50 snapshots per user+spreadsheet. Used by restore_snapshot.


sheet_analyzer

The restricted Postgres role that executes user SQL in analyze_range and transform_range. Has USAGE on public schema only — no access to any application tables. All SQL runs as this role inside BEGIN READ ONLY.


allowFormulaOverwrite

A boolean parameter accepted by write_range, append_rows, and transform_range. Defaults to false. When false, writes are blocked if the target range contains formula cells or ARRAYFORMULA-anchored columns. Set to true only when intentionally replacing formulas with static data.


confirmDelete

A boolean parameter required by manage_sheets for action: "delete" when the target sheet contains data. The server counts rows in column A before executing. If rows exist and confirmDelete is not true, the delete is blocked with a message showing the row count.


renderOption

The read_range parameter controlling how cell values are returned:

ValueReturns
FORMATTED_VALUEDisplay string — $1,200.00, Jan 2026
UNFORMATTED_VALUERaw value — 1200, 46023 (serial date)
FORMULAFormula string — =SUM(A1:A5) or value

needsAuth

A flag returned in error responses when the Google OAuth session has expired or been revoked. When needsAuth: true appears in any tool response, no subsequent tool call will succeed until the user re-authorizes at https://sheets-mcp-xi.vercel.app/dashboard.

{ "error": "Google Authentication Expired...", "needsAuth": true }

sheetId vs spreadsheetId

Two different identifiers — frequently confused.

TermTypeExampleUsed by
spreadsheetIdstring"1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"All tools
sheetIdinteger0, 812345678format_cells, copy_sheet, manage_sheets, batch_update_sheet

spreadsheetId is the document ID (from the URL). sheetId is the numeric tab ID returned by list_sheets. Use list_sheets to get sheetId values before calling tools that require them.


MCP transport

sheets-mcp uses the Streamable HTTP transport (the modern MCP transport as of the June 2025 MCP spec). POST-based with SSE streaming. The [transport] dynamic segment in src/app/api/[transport]/route.ts handles both SSE and HTTP transports from the same handler. Deployed as a single Vercel serverless function with maxDuration: 60.


OIDC vs API key auth

OIDCAPI key
HeaderAuthorization: Bearer x-api-key: <key>
Issued bybetter-auth OAuth2 consent flowDashboard → Create API key
Used byClaude Desktop, CursorScripts, CI pipelines, custom agents
SessionDecoded JWT → oauthAccessToken rowKey lookup → user session
Google sessionSame user Google OAuth tokenSame user Google OAuth token

Both paths resolve to the same Google OAuth access token internally. There is no functional difference in what the MCP tools can access.


What to do next

On this page