Model Context Protocol (MCP) server for creating, reading, and modifying Google Sheets and Slides, leveraging Google's built-in version history for safe undo and restore
Google Workspace MCP Server
This project provides a Model Context Protocol (MCP) server for interacting with Google Slides and Google Sheets APIs. Create, read, and modify presentations and spreadsheets programmatically, with access to Google's built-in version history for easy undo/restore.
Features
- Google Sheets: Create, read, update, and manipulate spreadsheets
- Google Slides: Create and modify presentations
- Version History: Access Google's native revision history for any document
- Minimal Permissions: Uses least-privilege OAuth scopes
Prerequisites
- Node.js (v18 or later recommended)
- npm (usually comes with Node.js)
- Google Cloud Project with APIs enabled (Slides, Sheets, Drive)
- OAuth 2.0 Credentials (Client ID and Client Secret)
- Google Refresh Token (one-time setup - see below)
- Google Cloud CLI (optional but recommended for debugging) -
brew install google-cloud-sdk
Quick Start
-
Install dependencies:
npm install -
Build the server:
npm run build -
Set up Google OAuth (see detailed setup below)
-
Configure environment variables in
.env:GOOGLE_CLIENT_ID=your_client_id_here GOOGLE_CLIENT_SECRET=your_client_secret_here GOOGLE_REFRESH_TOKEN=your_refresh_token_here -
Run the server:
npm start
Google Cloud Setup
1. Enable Required APIs
Go to Google Cloud Console:
- Create a new project or select an existing one
- Navigate to "APIs & Services" > "Library"
- Enable the following APIs:
- Google Slides API
- Google Sheets API
- Google Drive API
2. Create OAuth 2.0 Credentials
- Go to "APIs & Services" > "Credentials"
- Click "+ CREATE CREDENTIALS" > "OAuth client ID"
- If prompted, configure the OAuth consent screen:
- User type: "External" (or "Internal" for Workspace accounts)
- Add app name, support email, developer contact
- On the "Scopes" page, click "ADD OR REMOVE SCOPES" and add:
https://www.googleapis.com/auth/presentations(Slides access)https://www.googleapis.com/auth/spreadsheets(Sheets access)https://www.googleapis.com/auth/drive.readonly(Read Drive files/revisions)https://www.googleapis.com/auth/drive.file(Manage files created by app)
- Complete consent screen setup
- Back at "Credentials", create OAuth client ID:
- Application type: "Desktop app"
- Name: "Google Workspace MCP" (or your choice)
- Copy your Client ID and Client Secret
3. Get Your Refresh Token (ONE-TIME SETUP)
IMPORTANT: The refresh token is generated once during initial setup. After you get it:
- Store it in your
.envfile or MCP settings - The server will use it automatically for all future sessions
- You only need to regenerate it if you:
- Change the OAuth scopes
- Revoke access from your Google account
- Need to use a different Google account
Option A: Using the Built-in Script (Recommended)
-
Add your Client ID and Secret to
.env:GOOGLE_CLIENT_ID=your_client_id GOOGLE_CLIENT_SECRET=your_client_secret -
Run the token generator:
npm run get-token -
Follow the prompts:
- Browser will open to Google authorization page
- Sign in and grant permissions
- Your refresh token will be displayed in the terminal
-
Copy the refresh token to your
.env:GOOGLE_REFRESH_TOKEN=your_refresh_token_here
Option B: Using OAuth 2.0 Playground
- Go to OAuth 2.0 Playground
- Click the gear icon (Settings), check "Use your own OAuth credentials"
- Enter your Client ID and Client Secret
- In "Step 1", select these scopes:
https://www.googleapis.com/auth/presentationshttps://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/drive.file
- Click "Authorize APIs" and sign in
- In "Step 2", click "Exchange authorization code for tokens"
- Copy the Refresh token to your
.env
MCP Configuration
Add to your MCP settings file (e.g., Claude Code settings):
{
"mcpServers": {
"google-workspace-mcp": {
"command": "node",
"args": ["/absolute/path/to/google-workspace-mcp/build/index.js"],
"env": {
"GOOGLE_CLIENT_ID": "your_client_id",
"GOOGLE_CLIENT_SECRET": "your_client_secret",
"GOOGLE_REFRESH_TOKEN": "your_refresh_token"
}
}
}
}
Replace /absolute/path/to/google-workspace-mcp with the actual path to your installation.
Available Tools
Google Slides Tools
create_presentation- Create a new presentationget_presentation- Get presentation metadata and structureget_page- Get details about a specific slidesummarize_presentation- Extract all text content for summarizationbatch_update_presentation- Apply batch updates to a presentation
Google Sheets Tools
create_spreadsheet- Create a new spreadsheetget_spreadsheet- Get spreadsheet metadata and structureget_sheet_values- Read cell values from a rangesummarize_spreadsheet- Extract all data for summarizationupdate_sheet_values- Update cell values in a rangebatch_update_spreadsheet- Apply formatting/structural changesappend_sheet_values- Append rows to a sheetcopy_sheet- Copy a sheet between spreadsheets (preserves all formatting and styles)
Version History Tools
These tools use Google's native revision history (no extra files created):
list_revisions- List version history for a documentget_revision- Get details about a specific revision with restore instructions
Version History (Undo/Restore)
Both Google Sheets and Google Slides have built-in version history that automatically tracks all changes. This MCP server provides access to that history:
List all versions of a document:
{
"tool": "list_revisions",
"documentId": "your_document_id"
}
Get restore instructions for a specific version:
{
"tool": "get_revision",
"documentId": "your_document_id",
"revisionId": "revision_id",
"documentType": "spreadsheet"
}
To restore a previous version:
- Open the document in Google Sheets/Slides
- Go to File > Version history > See version history
- Click on the version you want to restore
- Click "Restore this version"
Example Use Cases
Automated QA Workbooks
// Create a test plan workbook
await create_spreadsheet({
title: "Release 2.0 QA Plan",
sheets: ["Test Cases", "Bug Tracking", "Sign-off"]
});
// Populate test cases
await update_sheet_values({
spreadsheetId: "...",
range: "Test Cases!A1:C1",
values: [["Test ID", "Description", "Status"]]
});
// Append test results as they come in
await append_sheet_values({
spreadsheetId: "...",
range: "Test Cases!A2",
values: [["TC-001", "Login flow", "PASS"]]
});
Presentation Automation
// Create monthly report presentation
await create_presentation({ title: "Q4 2024 Report" });
// Add slides with data visualization
await batch_update_presentation({
presentationId: "...",
requests: [/* slide creation requests */]
});
Copy Sheets Between Spreadsheets
// Copy a template sheet to a new workbook (preserves all formatting!)
await copy_sheet({
sourceSpreadsheetId: "template_workbook_id",
sourceSheetId: 176288731, // numeric sheet ID, not the name
destinationSpreadsheetId: "target_workbook_id"
});
// Perfect for: QA templates, report templates, data migrations
Version History Management
// List all versions of a spreadsheet
const revisions = await list_revisions({
documentId: "shared_budget_spreadsheet_id"
});
// Get instructions to restore a previous version
const details = await get_revision({
documentId: "shared_budget_spreadsheet_id",
revisionId: revisions[0].revisionId,
documentType: "spreadsheet"
});
// Follow the restoreInstructions in the response
Security
Principle of Least Privilege
This MCP server requests only the minimum OAuth scopes needed:
| Scope | Purpose | Access Level |
|-------|---------|--------------|
| presentations | Create/edit presentations | Full access to Slides |
| spreadsheets | Create/edit spreadsheets | Full access to Sheets |
| drive.readonly | List revisions | Read-only Drive access |
| drive.file | Manage created files | Only files created by this app |
Security Best Practices
- Never commit credentials: Add
.envto your.gitignore - Treat tokens like passwords: Your refresh token grants access to your Google account
- Use separate projects: Create a dedicated Google Cloud project for this MCP
- Review access regularly: Check Google Account Permissions periodically
- Rotate tokens if compromised: Regenerate with
npm run get-tokenif you suspect exposure
What This Server Can Access
- Slides: All presentations in your Google account
- Sheets: All spreadsheets in your Google account
- Drive: Read-only access to list files and revisions; write access only to files created by this app
What This Server Cannot Access
- Gmail, Calendar, or other Google services
- Files created by other apps (due to
drive.filescope limitation) - Your Google account password or 2FA settings
Troubleshooting
Using gcloud CLI for Debugging
Install the Google Cloud CLI to quickly check your project configuration:
# Install (macOS)
brew install google-cloud-sdk
# Add to shell (add to ~/.zshrc for persistence)
source "$(brew --prefix)/share/google-cloud-sdk/path.zsh.inc"
# Initialize and login
gcloud init
# Check which APIs are enabled
gcloud services list --enabled | grep -i "sheets\|slides\|drive"
Expected output when all APIs are enabled:
drive.googleapis.com Google Drive API
sheets.googleapis.com Google Sheets API
slides.googleapis.com Google Slides API
"Request had insufficient authentication scopes" errors
This is the most common issue. Check these in order:
-
Are all 3 APIs enabled? Run:
gcloud services list --enabled | grep -i "sheets\|slides\|drive"If any are missing, enable them:
gcloud services enable sheets.googleapis.com gcloud services enable slides.googleapis.com gcloud services enable drive.googleapis.com -
Are all 4 scopes in your OAuth consent screen?
- Go to: APIs & Services > OAuth consent screen > Edit App > Scopes
- You need ALL of these:
https://www.googleapis.com/auth/presentationshttps://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/drive.readonlyhttps://www.googleapis.com/auth/drive.file
-
Did you regenerate the token AFTER adding scopes?
- This is critical: scopes are baked into the refresh token at generation time
- If you add scopes later, you MUST regenerate:
npm run get-token
"API has not been used in project" errors
The API needs to be enabled in Google Cloud Console. The error message includes a direct link - click it to enable the API, wait 1-2 minutes for propagation, then retry.
"Invalid grant" or "Token expired" errors
- Your refresh token may be invalid
- Re-run
npm run get-tokento get a new one - Check that all 4 OAuth scopes are enabled
Slides works but Sheets doesn't (or vice versa)
This usually means the spreadsheets (or presentations) scope wasn't in your OAuth consent screen when you generated the token:
- Add the missing scope to OAuth consent screen
- Regenerate your token:
npm run get-token - Update your config/env with the new token
- Restart the MCP server
Permission denied errors
- Ensure all 4 APIs are enabled in Google Cloud Console
- Verify your OAuth consent screen has all required scopes
- Check that the refresh token was generated with all scopes
FAQ
Why do I need to regenerate my token after adding scopes?
OAuth refresh tokens encode the scopes they were granted at creation time. If you add new scopes to your OAuth consent screen, existing tokens don't automatically gain access to them. You must generate a new token that includes the new scopes.
Can I use the same token across multiple machines?
Yes! The refresh token is tied to your Google account and OAuth app, not your machine. Copy the same GOOGLE_REFRESH_TOKEN to any machine where you want to use this MCP server.
How do I know which scopes my current token has?
The easiest way is to test each feature. If Slides works but Sheets fails with "insufficient scopes", your token is missing the Sheets scope. Use npm run get-token to generate a fresh token with all scopes.
Why is the gcloud CLI recommended?
It makes debugging much faster. Instead of clicking through the Google Cloud Console UI, you can quickly check:
- Which project you're using
- Which APIs are enabled
- Your current authentication status
The token generator opens a browser but nothing happens
Make sure you're logged into the correct Google account. If you have multiple accounts, the browser may be defaulting to a different one. Try using an incognito window or explicitly signing out first.
Testing with MCP Inspector
You can test the MCP server directly using the MCP Inspector without needing Claude:
cd /path/to/google-workspace-mcp
export $(cat .env | xargs) && npx @modelcontextprotocol/inspector node build/index.js
This opens a web UI where you can:
- Browse all available tools
- Execute tools with custom parameters
- See raw JSON responses
- Debug issues before integrating with Claude
This is useful for verifying your OAuth setup is working correctly.
Development
# Install dependencies
npm install
# Build TypeScript
npm run build
# Run linter
npm run lint
# Start server
npm start
# Generate new refresh token
npm run get-token
License
ISC
Contributing
Issues and pull requests welcome! This MCP server is designed to be extended with additional Google Workspace services (Docs, Forms, etc.) in the future.
Version History
- 0.3.1 - Added
copy_sheettool for copying sheets between spreadsheets with full formatting - 0.3.0 - Simplified version control using Google's native revision history (removed custom snapshots)
- 0.2.0 - Added Google Sheets support
- 0.1.0 - Initial release with Google Slides support