google-sheets-mcp
README.md
# google-sheets-mcp
[](https://github.com/ethanratnofsky/google-sheets-mcp/actions/workflows/ci.yml)
MCP server for Google Sheets — read, write, format, and manage spreadsheets from
Claude Code, Claude Desktop, Cursor, or any MCP client, using your own Google
account via OAuth 2.0.
- **25 task-oriented tools** designed for AI agents: A1 notation, flat inputs,
actionable errors — plus a raw `batch_update` escape hatch for everything else.
- **Minimal access**: requests only the `spreadsheets` scope. No Drive access —
you provide a spreadsheet URL or ID.
- **Local-first**: runs over stdio on your machine; tokens are cached locally
with `0600` permissions and auto-refreshed.
## Setup
### 1. Create Google OAuth credentials (one time, ~5 minutes)
1. Go to [Google Cloud Console](https://console.cloud.google.com/) and create
(or pick) a project.
2. Enable the **Google Sheets API**: APIs & Services → Library → search
"Google Sheets API" → Enable.
3. Configure the OAuth consent screen (APIs & Services → OAuth consent screen):
choose **External**, fill in the required app fields, and add yourself as a
user. Then — important — **publish the app to Production** (Audience →
Publish app). Apps left in "Testing" issue tokens that expire every 7 days,
forcing weekly re-auth. Publishing for personal use with this scope does not
require Google verification.
4. Create credentials: APIs & Services → Credentials → Create credentials →
**OAuth client ID** → application type **Desktop app**. Download the JSON.
5. Save the downloaded file to `~/.config/google-sheets-mcp/oauth-keys.json`
(or anywhere, pointing `GOOGLE_SHEETS_OAUTH_PATH` at it).
### 2. Build and authorize
```bash
git clone https://github.com/ethanratnofsky/google-sheets-mcp.git
cd google-sheets-mcp
npm install
npm run setup
```
`npm run setup` is interactive: it builds the project, walks you through the
credential steps above if needed (you point it at your downloaded OAuth JSON
and it installs it with safe permissions), opens the browser consent flow, and
prints the exact MCP client config for your machine. Already-completed steps
are skipped, so it's safe to re-run. (`npm run auth` re-runs just the consent
flow.)
### 3. Add to your MCP client
**Claude Code:**
```bash
claude mcp add google-sheets -- node /absolute/path/to/google-sheets-mcp/dist/index.js
```
**Claude Desktop / Cursor** (`claude_desktop_config.json` / `mcp.json`):
```json
{
"mcpServers": {
"google-sheets": {
"command": "node",
"args": ["/absolute/path/to/google-sheets-mcp/dist/index.js"]
}
}
}
```
## Configuration
| Env var | Meaning | Default |
| -------------------------- | --------------------------------- | --------------------------------------------- |
| `GOOGLE_SHEETS_OAUTH_PATH` | Path to your OAuth client JSON | `~/.config/google-sheets-mcp/oauth-keys.json` |
| `GOOGLE_SHEETS_TOKEN_PATH` | Where the granted token is cached | `~/.config/google-sheets-mcp/token.json` |
## Tools
Every tool accepts a spreadsheet **ID or full URL**. Ranges use A1 notation
(`Sheet1!A2:D10`); row/column positions are 1-based.
| Tool | What it does |
| ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| `google_sheets_read_values` | Read one or more ranges (formatted, raw, or formulas) |
| `google_sheets_write_values` | Overwrite a range; `=FORMULA(...)` strings become live formulas |
| `google_sheets_append_rows` | Append rows to the end of a table |
| `google_sheets_clear_values` | Clear values, keep formatting |
| `google_sheets_get_spreadsheet` | Title, URL, and all tabs with sizes |
| `google_sheets_create_spreadsheet` | New spreadsheet with optional named tabs |
| `google_sheets_add_sheet` / `delete_sheet` / `rename_sheet` / `duplicate_sheet` | Tab management |
| `google_sheets_insert_dimension` / `delete_dimension` | Insert/delete rows or columns |
| `google_sheets_freeze_panes` | Freeze header rows/columns |
| `google_sheets_resize_dimension` | Set column width / row height, or auto-fit |
| `google_sheets_format_cells` | Bold, colors, alignment, number formats, wrap |
| `google_sheets_set_borders` | Borders: all, outer, or inner |
| `google_sheets_merge_cells` | Merge or unmerge |
| `google_sheets_add_conditional_format` | Highlight cells matching a condition |
| `google_sheets_read_formatting` | Read cell formatting, colors (as #RRGGBB hex), number formats, borders, and merges |
| `google_sheets_list_conditional_formats` | List conditional-format rules with their indices |
| `google_sheets_delete_conditional_format` | Delete a conditional-format rule by index |
| `google_sheets_sort_range` | Sort by one or more columns |
| `google_sheets_find_replace` | Find/replace in a range, sheet, or everywhere |
| `google_sheets_set_data_validation` | Dropdowns and checkboxes |
| `google_sheets_batch_update` | ⚠️ Raw Sheets API requests — charts, pivots, and anything else |
**Formulas:** writes default to `USER_ENTERED`, so any value starting with `=`
becomes a real formula — exactly as if typed into the sheet. Read them back
with `valueRender: "FORMULA"`.
## Quotas
The Sheets API allows 300 read and 300 write requests per minute per project by
default, but also caps each user at 60 read and 60 write requests per minute
— since this server runs as a single user, that per-user limit is the
one you'll actually hit first. The server automatically retries rate-limited
requests (3 attempts, exponential backoff).
## Troubleshooting
- **"Not authenticated"** — run `npm run auth`.
- **Re-auth required every 7 days** — your OAuth consent screen is in
"Testing" status; publish it to Production (Setup step 3).
- **"You don't have access to this spreadsheet"** — the authorized Google
account can't open that sheet; share it with that account.
- **Browser didn't open during auth** — copy the printed URL manually.
## Security
- Your OAuth client JSON and tokens never leave your machine; the token file is
written with `0600` permissions.
- The server talks only to `sheets.googleapis.com` and only with the
`spreadsheets` scope.
- Never commit `oauth-keys.json` or `token.json` (both are gitignored).
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md). MIT licensed.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues