Skip to content

Google Suite

Python 3.11+ License: MIT Docs

Unified Python SDK for Google Workspace APIs with Clean Architecture.

Features

  • 🔐 Unified Auth - Single OAuth flow for all Google APIs
  • 📧 Gmail - Send, receive, search, labels, attachments
  • 📅 Calendar - Events, calendars, scheduling
  • 📁 Drive - Files, folders, sharing, upload/download
  • 📊 Sheets - Read/write, upsert, typed rows, validation, conditional formats, charts, pivots, export (engine from GSpreadManager)
  • ✅ Tasks - Task lists, tasks, subtasks, due dates, complete/reopen
  • 👥 Contacts - List, search, create, update and delete contacts (People API)
  • 🚀 REST API - Single FastAPI gateway for all services
  • 💻 CLI - Unified command-line interface

Installation

pip install gsuite-sdk

Optional extras:

pip install gsuite-sdk[cloudrun]  # Google Cloud Secret Manager support
pip install gsuite-sdk[all]       # All optional dependencies (FastAPI, CLI)

Quick Start

Prerequisites

You need OAuth credentials from Google Cloud Console. See Getting Credentials for a step-by-step guide.

Authentication

from gsuite_core import GoogleAuth

# OAuth (interactive, opens browser)
auth = GoogleAuth()
auth.authenticate()

# Or with service account
auth = GoogleAuth.from_service_account("service-account.json")

Gmail

from gsuite_gmail import Gmail, query

gmail = Gmail(auth)

# Get unread messages with fluent API
for message in gmail.get_unread():
    print(f"{message.sender}: {message.subject}")
    message.mark_as_read().archive()  # Fluent chaining!

# Send email with signature
gmail.send(
    to=["recipient@example.com"],
    subject="Hello",
    body="World",
    signature=True,  # Appends your Gmail signature
)

# Search with query builder (inspired by simplegmail)
messages = gmail.search(
    query.newer_than(days=7) & query.has_attachment() & query.from_("boss@company.com")
)

# Or use construct_query for dict-style
messages = gmail.search(query.construct_query(
    unread=True,
    newer_than=(7, "day"),
    labels=["Work"],
))

Drive

from gsuite_drive import Drive

drive = Drive(auth)

# List files
for file in drive.list_files():
    print(f"{file.name} ({file.mime_type})")

# Upload
uploaded = drive.upload("document.pdf")
print(f"Uploaded: {uploaded.web_view_link}")

# Download
file = drive.get("file_id")
file.download("local_copy.pdf")

# Create folder and upload into it
folder = drive.create_folder("My Folder")
drive.upload("file.txt", parent_id=folder.id)

Calendar

from gsuite_calendar import Calendar

calendar = Calendar(auth)

# Get upcoming events
events = calendar.get_upcoming(days=7)
for event in events:
    print(f"{event.start}: {event.summary}")

# Create event
calendar.create_event(
    summary="Meeting",
    start="2026-01-30T10:00:00",
    end="2026-01-30T11:00:00",
)

Sheets

from gsuite_sheets import Sheets

sheets = Sheets(auth)

# Open spreadsheet by title or URL
sheet = sheets.open("My Spreadsheet")
# Or by key
sheet = sheets.open_by_key("1A2B3C...")
# Or by URL
sheet = sheets.open_by_url("https://docs.google.com/spreadsheets/d/...")

# Read values
values = sheet.get_values("Sheet1!A1:D10")
print(values)  # [[row1], [row2], ...]

# Write values
sheet.update_values("Sheet1!A1", [["Name", "Email"], ["John", "john@example.com"]])

# Append rows
sheet.append_values("Sheet1", [["Jane", "jane@example.com"]])

# Batch operations
sheet.batch_update([
    {"range": "Sheet1!A1", "values": [["Header1", "Header2"]]},
    {"range": "Sheet1!A2", "values": [["Data1", "Data2"]]},
])

# Create new spreadsheet
new_sheet = sheets.create("Budget 2026")
print(f"Created: {new_sheet.url}")

# List all spreadsheets
for spreadsheet in sheets.list_spreadsheets():
    print(f"{spreadsheet['name']} - {spreadsheet['id']}")

Tasks and Contacts

Tasks and Contacts are opt-in: their scopes are not in the default login (contacts is a sensitive scope). Log in with them and enable the Google Tasks API / People API in your Cloud project:

gsuite auth login --force --scopes default,tasks,contacts
from datetime import date

from gsuite_contacts import Contacts
from gsuite_tasks import Tasks

tasks = Tasks(auth)
task = tasks.create_task("Pay rent", due=date(2026, 2, 1))
for t in tasks.list_tasks(show_completed=False):
    print(t.title, t.due, "overdue" if t.is_overdue else "")
tasks.complete_task(task.id)

contacts = Contacts(auth)
for c in contacts.search("ana"):
    print(c.display_name, c.email, c.phone)
ana = contacts.create(given_name="Ana", emails=["ana@example.com"])
contacts.update(ana.id, phones=["+54 11 5555-5555"])

REST API

# Start unified API server
gsuite serve --port 8080

# Or with Docker
docker run -p 8080:8080 gsuite-api
# All services under one roof
curl http://localhost:8080/gmail/messages/unread
curl http://localhost:8080/calendar/events/upcoming
curl http://localhost:8080/drive/files
curl http://localhost:8080/sheets/list
curl http://localhost:8080/sheets/{spreadsheet_id}/values/Sheet1!A1:D10
curl http://localhost:8080/tasks/lists/@default/tasks
curl "http://localhost:8080/contacts/search?q=ana"

Interactive API docs available at /docs when server is running. See API Documentation section below for details.

CLI

# Authentication
gsuite auth login              # Opens browser for OAuth
gsuite auth status             # Check auth status
gsuite auth export             # Export token for Cloud Run

# Gmail
gsuite gmail list --unread     # List unread messages
gsuite gmail read MSG_ID       # Read specific message
gsuite gmail send --to user@example.com --subject "Hi" --body "Hello"
gsuite gmail search "from:boss has:attachment"
gsuite gmail labels            # List all labels

# Calendar  
gsuite calendar list --days 7  # Upcoming events
gsuite calendar today          # Today's events
gsuite calendar week           # Week view
gsuite calendar create "Meeting" --start "2026-01-30 10:00"
gsuite calendar calendars      # List calendars

# Sheets
gsuite sheets list             # List all spreadsheets
gsuite sheets open "Budget"    # Open by title
gsuite sheets read SHEET_ID "Sheet1!A1:D10"  # Read range
gsuite sheets write SHEET_ID "Sheet1!A1" "Name,Email"
gsuite sheets append SHEET_ID "Sheet1" "John,john@example.com"
gsuite sheets create "New Sheet"  # Create spreadsheet

# Tasks (login with --scopes default,tasks)
gsuite tasks lists             # Task lists
gsuite tasks ls --due-before 2026-02-28
gsuite tasks add "Pay rent" --due 2026-02-01
gsuite tasks done TASK_ID

# Contacts (login with --scopes default,contacts)
gsuite contacts search ana
gsuite contacts add -g Ana -e ana@example.com -p "+54 11 5555-5555"
gsuite contacts show CONTACT_ID

# Server
gsuite serve --port 8080       # Start REST API
gsuite status                  # Overall status

Architecture

google-suite/
├── packages/
│   ├── core/           # Shared auth, config, token storage
│   ├── gmail/          # Gmail client + query builder
│   ├── calendar/       # Calendar client
│   ├── drive/          # Drive client (upload, download, share)
│   ├── sheets/         # Sheets client + engine (from GSpreadManager)
│   ├── tasks/          # Tasks client
│   ├── contacts/       # Contacts client (People API)
│   └── mcp/            # MCP server (published as gsuite-mcp)
├── api/                # Unified FastAPI REST gateway
├── cli/                # Unified CLI (Typer + Rich)
├── skills/gsuite-sdk/  # Agent skill (SKILL.md + references), also a Claude Code plugin
├── docs/               # Documentation site (MkDocs)
└── tests/integration/  # Opt-in tests against a real Google account

Design Principles

  • Clean Architecture - Domain entities, interfaces, infrastructure separation
  • Provider Agnostic - Swap implementations via interfaces
  • Shared Auth - One OAuth flow grants access to all services
  • Independent Packages - Install only what you need
  • Unified Gateway - Single API/CLI for all services

For detailed architecture decisions and design patterns, see Architecture Documentation.

Use with AI agents

skills/gsuite-sdk is an Agent Skill that teaches an agent to use the gsuite CLI (JSON output) and the SDK. Install it in your agent:

npx skills add PabloAlaniz/google-suite                          # Claude Code, Codex, Cursor, Gemini CLI, Copilot, ...
claude plugin marketplace add PabloAlaniz/google-suite           # Claude Code plugin
claude plugin install gsuite-sdk@gsuite-sdk
gemini extensions install https://github.com/PabloAlaniz/google-suite   # Gemini CLI extension

In a Claude Code session: /plugin install gsuite-sdk --marketplace PabloAlaniz/google-suite.

MCP server

gsuite-mcp exposes Gmail, Calendar, Drive, Sheets, Tasks and Contacts as MCP tools for any MCP client:

claude mcp add gsuite -e GSUITE_TOKEN_DB_PATH="$PWD/tokens.db" -- uvx gsuite-mcp

It is in the official MCP Registry as io.github.PabloAlaniz/gsuite-sdk. On OpenClaw it is pabloalaniz/gsuite-sdk on ClawHub.

The agent still needs the SDK and a login: pip install "gsuite-sdk[cli]" and gsuite auth login (see Quick Start).

Standalone Repos

This monorepo consolidates and extends these standalone projects:

The standalone repos remain functional for existing deployments.

Configuration

Environment variables (prefix GSUITE_):

Variable Description
GSUITE_CREDENTIALS_FILE OAuth credentials JSON path
GSUITE_TOKEN_STORAGE sqlite or secretmanager
GSUITE_TOKEN_DB_PATH SQLite token database path
GSUITE_GCP_PROJECT_ID GCP project (for Secret Manager)
GSUITE_API_KEY API key for REST endpoints (required unless GSUITE_ALLOW_NO_API_KEY=true)
GSUITE_CORS_ORIGINS Comma-separated origins allowed by CORS (off by default)

See api/README.md for every REST API setting.

Development

# Clone
git clone https://github.com/PabloAlaniz/google-suite.git
cd google-suite

# Install everything, pinned by uv.lock
uv sync --all-extras

# Run tests
uv run pytest

# Lint
uv run ruff check packages api cli

Deployment

Cloud Run (GCP)

Deploy the REST API to Cloud Run with Secret Manager for token storage:

# Build and push Docker image (from the repo root)
docker build -f api/Dockerfile -t gcr.io/YOUR_PROJECT/gsuite-api .
docker push gcr.io/YOUR_PROJECT/gsuite-api

# Deploy to Cloud Run
gcloud run deploy gsuite-api \
  --image gcr.io/YOUR_PROJECT/gsuite-api \
  --platform managed \
  --region us-central1 \
  --set-env-vars GSUITE_TOKEN_STORAGE=secretmanager \
  --set-env-vars GSUITE_GCP_PROJECT_ID=YOUR_PROJECT \
  --set-secrets GSUITE_API_KEY=gsuite-api-key:latest \
  --allow-unauthenticated

The API rejects every request until GSUITE_API_KEY is set. If you protect the service with IAM instead (--no-allow-unauthenticated), set GSUITE_ALLOW_NO_API_KEY=true rather than the key.

Note: For Secret Manager token storage, ensure your Cloud Run service account has secretmanager.versions.access permission.

Docker Compose

For local development or self-hosted deployment:

version: '3.8'
services:
  gsuite-api:
    build:
      context: .
      dockerfile: api/Dockerfile
    ports:
      - "8080:8080"
    environment:
      GSUITE_CREDENTIALS_FILE: /secrets/credentials.json
      GSUITE_TOKEN_DB_PATH: /data/tokens.db
      GSUITE_API_KEY: your-api-key-here
    volumes:
      - ./credentials.json:/secrets/credentials.json:ro
      - ./data:/data

API Documentation

When running the REST API server, interactive API docs are available at:

  • Swagger UI: http://localhost:8080/docs
  • ReDoc: http://localhost:8080/redoc

Troubleshooting

Token refresh failed

Problem: TokenRefreshError: Failed to refresh token

Solution: - Delete the token database: rm ~/.gsuite/tokens.db (or your configured path) - Re-authenticate: gsuite auth login - For service accounts, verify the JSON file hasn't expired

Missing scopes

Problem: HttpError 403: Insufficient Permission

Solution: - Check required scopes in error message - Re-authenticate with additional scopes:

gsuite auth login --scopes gmail.readonly,calendar,drive
- Or update GSUITE_DEFAULT_SCOPES environment variable

Credentials not found

Problem: CredentialsNotFoundError: OAuth credentials file not found

Solution: - Download OAuth credentials from Google Cloud Console - Save as credentials.json in working directory - Or set GSUITE_CREDENTIALS_FILE environment variable

Import errors

Problem: ModuleNotFoundError: No module named 'gsuite_gmail'

Solution: - Install the package: pip install gsuite-sdk - Or for development: uv sync --all-extras (see CONTRIBUTING.md)

License

MIT - see LICENSE

Author

Pablo Alaniz (@PabloAlaniz)