# Google Sheets MCP Server (`oldjard/google-sheets-mcp`) Actor

Let Claude, Cursor or any MCP client read and write your Google Sheets: list tabs, read ranges, append or update rows, export an Apify dataset. Signs in with your own Google service account; failed calls are free.

- **URL**: https://apify.com/oldjard/google-sheets-mcp.md
- **Developed by:** [Joshua White](https://apify.com/oldjard) (community)
- **Categories:** MCP servers, Integrations, Agents
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event + usage

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Sheets MCP Server

Let Claude, Cursor or any other MCP client **read and write your Google Sheets**. Your agent can list a spreadsheet's
tabs, read ranges, append or update rows, and export a whole Apify dataset to a tab.

It signs in with **your own Google service account**, so there's no shared quota, no OAuth app to approve, and nothing
that expires. The service account can only open sheets you share with it. Apify starts the server when your agent
calls it and stops it when it goes quiet.

### Tools

| Tool | What it does |
|---|---|
| `list_sheets` | Lists a spreadsheet's tabs, with their size and link |
| `read_range` | Reads cells (`Leads!A1:D50`, `A1:D50`, or a whole tab). Long tabs come back in pages, with the next range to read |
| `append_rows` | Adds rows under the last one. Objects are matched to the header by name (new fields become columns). Arrays are written as they are. Can skip rows already in the tab |
| `update_range` | Overwrites cells from a top-left cell, and grows the tab if needed |
| `export_dataset` | Writes an Apify dataset to a tab: append, replace, or only new rows |

Values are written as plain values, never as formulas. One call reads or writes at most 5,000 rows.

### Setup (about 5 minutes, once)

You need a Google service account: a robot Google user that only gets access to the sheets you share with it.
It's free, and Google asks for no billing details to use the Sheets API.

1. Open [console.cloud.google.com](https://console.cloud.google.com) and sign in. In the project picker at the top,
   choose **New project**, name it (for example `apify-sheets`), and click **Create**. Make sure the new project is selected.
2. Open the [Google Sheets API page](https://console.cloud.google.com/apis/library/sheets.googleapis.com) and
   click **Enable**.
3. Go to **IAM & Admin > Service Accounts > Create service account**. Give it a name, click **Create and
   continue**, skip the optional role step, and click **Done**.
4. Click the new service account, open the **Keys** tab, then **Add key > Create new key > JSON > Create**. A
   `.json` file downloads.
5. In the file, find `"client_email"` (something like `apify-sheets@your-project.iam.gserviceaccount.com`). Open
   each Google Sheet your agent should use, click **Share**, paste that email, choose **Editor**, untick *Notify
   people*, and click **Share**.

> **Google Workspace (company) accounts:** some organizations block service-account keys. If step 4 says key
> creation is disabled by policy, use a personal Google account for the project. Your sheet can still live
> anywhere, as long as it is shared with the service account's email.

### Connect your agent

1. Turn your key file into one line of base64: `base64 -w0 key.json` (on macOS: `base64 -i key.json`).
2. Add the server to your client, using the MCP URL from this Actor's *Endpoints* tab (it ends in `/mcp`) and two
   headers. For Claude Code:

   ```
   claude mcp add --transport http google-sheets https://<username>--google-sheets-mcp.apify.actor/mcp \
     --header "Authorization: Bearer <your Apify API token>" \
     --header "X-Google-Service-Account-Key: <the base64 line>"
   ```

   Other clients take the same URL and the same `headers` in their JSON config.
3. Ask your agent something like *"List the tabs of https://docs.google.com/spreadsheets/d/... and add these leads
   to the Leads tab."*

Optional input: a **default sheet** (used when the agent names none) and the key itself, if your client can't send
custom headers. Both are set in the Actor's input; the key field is stored encrypted.

If a tool can't do something (sheet not shared, a wrong tab name, a missing key), it returns a plain-English fix,
for example the exact email to share the sheet with, and that call is free.

To export a dataset to a sheet after every scraper run, without an agent, use the
**Dataset to Google Sheets Export** Actor instead. It shares this server's Google code.

### Pricing

Pay per event: you pay per **successful tool call**, plus a per-row price for rows `export_dataset` writes (header
rows and rows skipped as duplicates are free). Failed calls are free. As with any Actor that runs in Standby mode,
Apify also bills the run's platform usage while your agent is connected, and for a short idle period after its last
call. Starting it by hand (not through the MCP URL) does nothing and charges nothing.

### Limits worth knowing

- Google allows **10 million cells per spreadsheet** and **50,000 characters per cell**.
- Your service account gets Google's standard quota of **60 write requests per minute**. Rate limits and Google
  hiccups are retried with backoff.

### FAQ

**Is my key safe?** It travels in a header over HTTPS to your own Actor run (runs are never shared between users).
It is held in memory only while the run is up, and never logged or stored. The service account can only open sheets
you share with it, and you can delete the key in Google Cloud at any time.

**Can it write formulas?** No. Everything is written as plain values, on purpose.

**Does it read my other files?** No. It asks Google only for spreadsheet access, and it can see only sheets shared with it.

### Testing status

Tested end to end against a fake Google API that checks the signed sign-in and reproduces Google's documented
errors and limits: every tool, through a real MCP client, against the real Actor process. A test against real Google
is still to come.

# Actor input Schema

## `spreadsheet` (type: `string`):

Optional. The sheet tools use when your agent names none. Copy it from the browser's address bar; the spreadsheet ID alone also works.

## `serviceAccountKey` (type: `string`):

Optional. Normally your MCP client sends the key in the X-Google-Service-Account-Key header (see the README). If you put it here instead, it is stored encrypted and used when a request has no key header.

## Actor input object example

```json
{}
```

# Actor output Schema

## `mcpUrl` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("oldjard/google-sheets-mcp").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("oldjard/google-sheets-mcp").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call oldjard/google-sheets-mcp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,oldjard/google-sheets-mcp"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/sJx1rEKcQHIEb1i6L/builds/wQzFXZFyfF7pq8l7n/openapi.json
