google-sheets-mcp
google-sheets-mcp
A local MCP server that lets an AI assistant read and write your Google Sheets, with per-user OAuth and no cloud hosting.
Why
Most ways of giving an AI assistant access to a spreadsheet are either read-only or route your data through a third-party automation platform. Neither is good enough for a working document you update every day.
This server runs on your own machine and talks directly to the Google Sheets API as you. It exposes targeted operations rather than a raw API surface, so updating a status field changes that one cell instead of rewriting a block of rows — which matters when the spreadsheet is a register you rely on rather than a scratch file.
Features
Twelve tools, split between reading and writing. Write tools can be disabled entirely with READ_ONLY=true.
Read
Tool | Description |
| Lists a spreadsheet's tabs with dimensions and sheet IDs |
| Reads a range in A1 notation, or a whole tab |
| Returns only rows matching column filters or free text, with their absolute row numbers |
Write
Tool | Description |
| Sets a single cell; cannot affect neighbouring cells |
| Updates only the named columns of an existing row, found by number or by a matching value |
| Overwrites a range with a value grid |
| Appends rows after the last occupied row |
| Clears values while preserving formatting |
| Creates a new spreadsheet in your Drive |
| Adds a tab to an existing spreadsheet |
| Renames a tab |
| Deletes a tab; requires an explicit |
Two design decisions worth calling out. find_rows returns row numbers that feed straight into update_row, so the model can locate a record and change one field without pulling the whole table into context. And update_row refuses to act when a match is ambiguous, listing the candidate rows instead of updating several at once.
Requirements
Node.js 20 or later
A Google account and a Google Cloud project
An MCP-capable client that supports local stdio servers (Claude Desktop, Claude Code, or any other MCP client)
This is a stdio server. It does not listen on a public port and cannot be used by browser-based clients that only reach remote HTTPS endpoints.
Setup
Starting from a clean machine.
1. Enable the Google Sheets API
Go to the Google Cloud Console, create or select a project, then open APIs & Services > Library, search for Google Sheets API and click Enable.
2. Configure the OAuth consent screen
Open Google Auth Platform > Branding and fill in the app name, user support email and developer contact email. Under Audience, choose Internal if your account belongs to a Google Workspace organisation, otherwise External.
If you chose External and stay in Testing publishing status, add your own address under Test users — without it, sign-in fails with access_denied — and be aware that Google revokes refresh tokens seven days after consent. Publishing the app to production removes that expiry; the app stays private either way, since reaching the consent screen requires your client ID.
3. Create OAuth credentials
Open Google Auth Platform > Clients > Create client and choose application type Desktop app. Desktop clients accept a loopback redirect on any port, so there is no redirect URI to configure. Copy the client ID and client secret.
4. Install
git clone https://github.com/your-username/google-sheets-mcp.git
cd google-sheets-mcp
npm install
npm run build5. Configure credentials
cp .env.example .envOpen .env and fill in GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET. On first run, consider also setting ALLOWED_SPREADSHEET_IDS to a single test spreadsheet.
6. Link your Google account
npm run loginThe command prints a URL. Open it, sign in with the account you added as a test user, and grant access. If the app is unverified you will see a "Google hasn't verified this app" screen — click Advanced, then continue. Google redirects to a temporary local server, the code is exchanged automatically, and the refresh token is written to ~/.gsheets-mcp/tokens.json with mode 0600.
To check how much time is left on the authorization:
npm run statusConfiguration
Add the server to your MCP client's configuration file. For Claude Desktop:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"gsheets": {
"command": "node",
"args": ["/absolute/path/to/google-sheets-mcp/dist/index.js"],
"env": {
"GOOGLE_CLIENT_ID": "your-client-id-here.apps.googleusercontent.com",
"GOOGLE_CLIENT_SECRET": "your-client-secret-here",
"ALLOWED_SPREADSHEET_IDS": ""
}
}
}
}The path in args must be absolute. On Windows, escape backslashes: "C:\\path\\to\\google-sheets-mcp\\dist\\index.js". Credentials can be supplied either here or through .env — the env block takes precedence.
Restart the client after editing the file.
Usage
Given a spreadsheet with a Log tab whose columns are Date, Task, Client, Hours, Status:
Find the rows in Log where Status is "Pending"
3 of 214 rows in "Log"
row Date Task Client Hours Status
47 2026-03-02 Draft API spec Acme 3 Pending
88 2026-03-14 Review contract Northwind 1.5 Pending
131 2026-04-01 Migrate CI pipeline Acme 6 PendingMark row 47 as Done
Row 47 of "Log" updated.
Status: "Pending" -> "Done"Only column E of row 47 is written. Every other cell in that row is left untouched, and the response reports the previous value so the change can be verified without opening the spreadsheet.
Known limitations
stdio only. No HTTP transport, so browser and mobile MCP clients cannot reach it. Adding one would require hosting and an OAuth authorization-server layer.
Values, not formatting. Cell values and formulas are supported; colours, borders, conditional formatting, charts, filters and data validation are not. Those need
spreadsheets.batchUpdate, which is deliberately not exposed — a general-purpose passthrough would be hard to reason about and easy to misuse.No server-side search. The Sheets API has no query endpoint, so
find_rowsreads the tab and filters in process. The saving is in what reaches the model's context, not in API traffic. On very large sheets the read itself is the cost.Single account. One linked Google identity per installation.
Scope granularity. The
spreadsheetsscope covers every spreadsheet the account can reach; Google offers no per-file scope.ALLOWED_SPREADSHEET_IDSis the only real restriction available, and it is enforced by this server rather than by Google.Rate limits. Google allows 300 read and 300 write requests per minute per project, and 60 per minute per user. Quota is shared across everything using the same Cloud project. Exceeding it returns HTTP 429; the server surfaces it but does not retry or back off.
Token expiry in Testing. With External audience and Testing publishing status, Google revokes refresh tokens after seven days. The server detects
invalid_grantand returns an actionable message rather than a raw API error.Untrusted cell content. Anything the model reads from a spreadsheet enters its context as untrusted text. A sheet shared by someone else could contain instructions aimed at the model. Consider
READ_ONLY=trueor an allowlist when working with files you did not create.
License
MIT — see LICENSE.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/AurelioCecchi/mcp-google-sheets'
If you have feedback or need assistance with the MCP directory API, please join our Discord server