google-workspace

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Google Workspace APIs

Google Workspace APIs

Status: Production Ready Last Updated: 2026-01-09 Dependencies: Cloudflare Workers (recommended), Google Cloud Project Skill Version: 1.0.0

状态:已就绪可用于生产环境 最后更新:2026-01-09 依赖项:Cloudflare Workers(推荐)、Google Cloud Project 技能版本:1.0.0

Quick Reference

快速参考

APICommon Use CasesReference
GmailEmail automation, inbox managementgmail-api.md
CalendarEvent management, schedulingcalendar-api.md
DriveFile storage, sharingdrive-api.md
SheetsSpreadsheet data, reportingsheets-api.md
DocsDocument generationdocs-api.md
ChatBots, webhooks, spaceschat-api.md
MeetVideo conferencingmeet-api.md
FormsForm responses, creationforms-api.md
TasksTask managementtasks-api.md
Admin SDKUser/group managementadmin-sdk.md
PeopleContacts managementpeople-api.md

API常见使用场景参考文档
Gmail邮件自动化、收件箱管理gmail-api.md
Calendar事件管理、日程安排calendar-api.md
Drive文件存储、共享drive-api.md
Sheets电子表格数据、报表生成sheets-api.md
Docs文档生成docs-api.md
Chat机器人、Webhook、空间chat-api.md
Meet视频会议meet-api.md
Forms表单响应、创建forms-api.md
Tasks任务管理tasks-api.md
Admin SDK用户/组管理admin-sdk.md
People联系人管理people-api.md

Shared Authentication Patterns

通用认证模式

All Google Workspace APIs use the same authentication mechanisms. Choose based on your use case.
所有Google Workspace API使用相同的认证机制,请根据使用场景选择。

Option 1: OAuth 2.0 (User Context)

选项1:OAuth 2.0(用户上下文)

Best for: Acting on behalf of a user, accessing user-specific data.
typescript
// Authorization URL
const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth')
authUrl.searchParams.set('client_id', env.GOOGLE_CLIENT_ID)
authUrl.searchParams.set('redirect_uri', `${env.BASE_URL}/callback`)
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('scope', SCOPES.join(' '))
authUrl.searchParams.set('access_type', 'offline')  // For refresh tokens
authUrl.searchParams.set('prompt', 'consent')       // Force consent for refresh token

// Token exchange
async function exchangeCode(code: string): Promise<TokenResponse> {
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      code,
      client_id: env.GOOGLE_CLIENT_ID,
      client_secret: env.GOOGLE_CLIENT_SECRET,
      redirect_uri: `${env.BASE_URL}/callback`,
      grant_type: 'authorization_code',
    }),
  })
  return response.json()
}

// Refresh token
async function refreshToken(refresh_token: string): Promise<TokenResponse> {
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      refresh_token,
      client_id: env.GOOGLE_CLIENT_ID,
      client_secret: env.GOOGLE_CLIENT_SECRET,
      grant_type: 'refresh_token',
    }),
  })
  return response.json()
}
Critical:
  • Always request
    access_type=offline
    for refresh tokens
  • Use
    prompt=consent
    to ensure refresh token is returned
  • Store refresh tokens securely (Cloudflare KV or D1)
  • Access tokens expire in ~1 hour
最佳适用场景:代表用户操作,访问用户特定数据。
typescript
// Authorization URL
const authUrl = new URL('https://accounts.google.com/o/oauth2/v2/auth')
authUrl.searchParams.set('client_id', env.GOOGLE_CLIENT_ID)
authUrl.searchParams.set('redirect_uri', `${env.BASE_URL}/callback`)
authUrl.searchParams.set('response_type', 'code')
authUrl.searchParams.set('scope', SCOPES.join(' '))
authUrl.searchParams.set('access_type', 'offline')  // For refresh tokens
authUrl.searchParams.set('prompt', 'consent')       // Force consent for refresh token

// Token exchange
async function exchangeCode(code: string): Promise<TokenResponse> {
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      code,
      client_id: env.GOOGLE_CLIENT_ID,
      client_secret: env.GOOGLE_CLIENT_SECRET,
      redirect_uri: `${env.BASE_URL}/callback`,
      grant_type: 'authorization_code',
    }),
  })
  return response.json()
}

// Refresh token
async function refreshToken(refresh_token: string): Promise<TokenResponse> {
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      refresh_token,
      client_id: env.GOOGLE_CLIENT_ID,
      client_secret: env.GOOGLE_CLIENT_SECRET,
      grant_type: 'refresh_token',
    }),
  })
  return response.json()
}
关键注意事项:
  • 始终请求
    access_type=offline
    以获取刷新令牌
  • 使用
    prompt=consent
    确保返回刷新令牌
  • 安全存储刷新令牌(Cloudflare KV或D1)
  • 访问令牌约1小时后过期

Option 2: Service Account (Server-to-Server)

选项2:服务账号(服务器到服务器)

Best for: Backend automation, no user interaction, domain-wide delegation.
typescript
import { SignJWT } from 'jose'

async function getServiceAccountToken(
  serviceAccount: ServiceAccountKey,
  scopes: string[]
): Promise<string> {
  const now = Math.floor(Date.now() / 1000)

  // Create JWT
  const jwt = await new SignJWT({
    iss: serviceAccount.client_email,
    scope: scopes.join(' '),
    aud: 'https://oauth2.googleapis.com/token',
    iat: now,
    exp: now + 3600,
  })
    .setProtectedHeader({ alg: 'RS256', typ: 'JWT' })
    .sign(await importPKCS8(serviceAccount.private_key, 'RS256'))

  // Exchange JWT for access token
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      assertion: jwt,
    }),
  })

  const data = await response.json()
  return data.access_token
}
Domain-Wide Delegation (impersonate users):
typescript
const jwt = await new SignJWT({
  iss: serviceAccount.client_email,
  sub: 'user@domain.com',  // User to impersonate
  scope: scopes.join(' '),
  aud: 'https://oauth2.googleapis.com/token',
  iat: now,
  exp: now + 3600,
})
Setup Required:
  1. Create service account in Google Cloud Console
  2. Download JSON key file
  3. Enable domain-wide delegation in Admin Console (if impersonating)
  4. Store key as Cloudflare secret (JSON stringified)

最佳适用场景:后端自动化,无需用户交互,域范围委派。
typescript
import { SignJWT } from 'jose'

async function getServiceAccountToken(
  serviceAccount: ServiceAccountKey,
  scopes: string[]
): Promise<string> {
  const now = Math.floor(Date.now() / 1000)

  // Create JWT
  const jwt = await new SignJWT({
    iss: serviceAccount.client_email,
    scope: scopes.join(' '),
    aud: 'https://oauth2.googleapis.com/token',
    iat: now,
    exp: now + 3600,
  })
    .setProtectedHeader({ alg: 'RS256', typ: 'JWT' })
    .sign(await importPKCS8(serviceAccount.private_key, 'RS256'))

  // Exchange JWT for access token
  const response = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      assertion: jwt,
    }),
  })

  const data = await response.json()
  return data.access_token
}
域范围委派(模拟用户):
typescript
const jwt = await new SignJWT({
  iss: serviceAccount.client_email,
  sub: 'user@domain.com',  // User to impersonate
  scope: scopes.join(' '),
  aud: 'https://oauth2.googleapis.com/token',
  iat: now,
  exp: now + 3600,
})
所需设置:
  1. 在Google Cloud Console中创建服务账号
  2. 下载JSON密钥文件
  3. 在Admin Console中启用域范围委派(如果需要模拟用户)
  4. 将密钥存储为Cloudflare密钥(JSON字符串化)

Common Rate Limits

常见速率限制

All Google Workspace APIs enforce quotas. These are approximate - check each API's specific limits.
所有Google Workspace API都实施配额限制。以下为近似值 - 请查看各API的具体限制。

Per-User Limits (OAuth)

每用户限制(OAuth)

APIReadsWritesNotes
Gmail250/user/sec250/user/secAggregate across all methods
Calendar500/user/100sec500/user/100secPer calendar
Drive1000/user/100sec1000/user/100sec
Sheets100/user/100sec100/user/100secLower than others
API读取写入说明
Gmail250/用户/秒250/用户/秒所有方法的总和
Calendar500/用户/100秒500/用户/100秒每个日历
Drive1000/用户/100秒1000/用户/100秒
Sheets100/用户/100秒100/用户/100秒比其他API低

Per-Project Limits

每项目限制

APIDaily QuotaPer-MinuteNotes
Gmail1B unitsVariesUnit-based (send = 100 units)
Calendar1M queries500/sec
Drive1B queries1000/sec
SheetsUnlimited500/user/100sec
API每日配额每分钟限制说明
Gmail10亿单位可变基于单位(发送=100单位)
Calendar100万次查询500/秒
Drive10亿次查询1000/秒
Sheets无限制500/用户/100秒

Handling Rate Limits

处理速率限制

typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 5
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn()
    } catch (error: any) {
      const status = error.status || error.code

      if (status === 429 || status === 503) {
        // Rate limited or service unavailable
        const retryAfter = error.headers?.get('Retry-After') || Math.pow(2, i)
        await new Promise(r => setTimeout(r, retryAfter * 1000))
        continue
      }

      if (status === 403 && error.message?.includes('rateLimitExceeded')) {
        // Quota exceeded - exponential backoff
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000))
        continue
      }

      throw error
    }
  }
  throw new Error('Max retries exceeded')
}

typescript
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 5
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn()
    } catch (error: any) {
      const status = error.status || error.code

      if (status === 429 || status === 503) {
        // Rate limited or service unavailable
        const retryAfter = error.headers?.get('Retry-After') || Math.pow(2, i)
        await new Promise(r => setTimeout(r, retryAfter * 1000))
        continue
      }

      if (status === 403 && error.message?.includes('rateLimitExceeded')) {
        // Quota exceeded - exponential backoff
        await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000))
        continue
      }

      throw error
    }
  }
  throw new Error('Max retries exceeded')
}

Batch Requests

批量请求

Most Google APIs support batching multiple requests into one HTTP call.
typescript
async function batchRequest(
  accessToken: string,
  requests: BatchRequestItem[]
): Promise<BatchResponse[]> {
  const boundary = 'batch_boundary'

  let body = ''
  requests.forEach((req, i) => {
    body += `--${boundary}\r\n`
    body += 'Content-Type: application/http\r\n'
    body += `Content-ID: <item${i}>\r\n\r\n`
    body += `${req.method} ${req.path} HTTP/1.1\r\n`
    body += 'Content-Type: application/json\r\n\r\n'
    if (req.body) body += JSON.stringify(req.body)
    body += '\r\n'
  })
  body += `--${boundary}--`

  const response = await fetch('https://www.googleapis.com/batch/v1', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': `multipart/mixed; boundary=${boundary}`,
    },
    body,
  })

  // Parse multipart response...
  return parseBatchResponse(await response.text())
}
Limits:
  • Max 100 requests per batch (most APIs)
  • Max 1000 requests per batch (some APIs like Drive)
  • Each request in batch counts toward quota

大多数Google API支持将多个请求合并为一个HTTP调用。
typescript
async function batchRequest(
  accessToken: string,
  requests: BatchRequestItem[]
): Promise<BatchResponse[]> {
  const boundary = 'batch_boundary'

  let body = ''
  requests.forEach((req, i) => {
    body += `--${boundary}\r\n`
    body += 'Content-Type: application/http\r\n'
    body += `Content-ID: <item${i}>\r\n\r\n`
    body += `${req.method} ${req.path} HTTP/1.1\r\n`
    body += 'Content-Type: application/json\r\n\r\n'
    if (req.body) body += JSON.stringify(req.body)
    body += '\r\n'
  })
  body += `--${boundary}--`

  const response = await fetch('https://www.googleapis.com/batch/v1', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': `multipart/mixed; boundary=${boundary}`,
    },
    body,
  })

  // Parse multipart response...
  return parseBatchResponse(await response.text())
}
限制:
  • 每批最多100个请求(大多数API)
  • 每批最多1000个请求(部分API如Drive)
  • 批处理中的每个请求都会占用配额

Cloudflare Workers Configuration

Cloudflare Workers配置

jsonc
// wrangler.jsonc
{
  "name": "google-workspace-mcp",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-03",
  "compatibility_flags": ["nodejs_compat"],

  // Store OAuth tokens
  "kv_namespaces": [
    { "binding": "TOKENS", "id": "xxx" }
  ],

  // Or use D1 for structured storage
  "d1_databases": [
    { "binding": "DB", "database_name": "workspace-mcp", "database_id": "xxx" }
  ]
}
Secrets to set:
bash
echo "your-client-id" | npx wrangler secret put GOOGLE_CLIENT_ID
echo "your-client-secret" | npx wrangler secret put GOOGLE_CLIENT_SECRET
jsonc
// wrangler.jsonc
{
  "name": "google-workspace-mcp",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-03",
  "compatibility_flags": ["nodejs_compat"],

  // Store OAuth tokens
  "kv_namespaces": [
    { "binding": "TOKENS", "id": "xxx" }
  ],

  // Or use D1 for structured storage
  "d1_databases": [
    { "binding": "DB", "database_name": "workspace-mcp", "database_id": "xxx" }
  ]
}
需要设置的密钥:
bash
echo "your-client-id" | npx wrangler secret put GOOGLE_CLIENT_ID
echo "your-client-secret" | npx wrangler secret put GOOGLE_CLIENT_SECRET

For service accounts:

For service accounts:

cat service-account.json | npx wrangler secret put GOOGLE_SERVICE_ACCOUNT

---
cat service-account.json | npx wrangler secret put GOOGLE_SERVICE_ACCOUNT

---

Common Errors

常见错误

Error: "invalid_grant" on Token Refresh

错误:令牌刷新时出现"invalid_grant"

Cause: Refresh token revoked or expired (6 months of inactivity) Fix: Re-authenticate user, request new refresh token
原因:刷新令牌已被撤销或过期(6个月未使用) 解决方法:重新认证用户,请求新的刷新令牌

Error: "access_denied" on OAuth

错误:OAuth时出现"access_denied"

Cause: App not verified, or user not in test users list Fix: Add user to OAuth consent screen test users, or complete app verification
原因:应用未通过验证,或用户不在测试用户列表中 解决方法:将用户添加到OAuth同意屏幕的测试用户列表,或完成应用验证

Error: "insufficientPermissions" (403)

错误:"insufficientPermissions"(403)

Cause: Missing required scope Fix: Check scopes in authorization URL, re-authenticate with correct scopes
原因:缺少所需的权限范围 解决方法:检查授权URL中的权限范围,使用正确的范围重新认证

Error: "rateLimitExceeded" (403)

错误:"rateLimitExceeded"(403)

Cause: Quota exceeded Fix: Implement exponential backoff, reduce request frequency, request quota increase
原因:配额已用尽 解决方法:实现指数退避,降低请求频率,申请增加配额

Error: "notFound" (404) on Known Resource

错误:已知资源出现"notFound"(404)

Cause: Using wrong API version, or resource in trash Fix: Check API version in URL, check trash for deleted items

原因:使用了错误的API版本,或资源已被放入回收站 解决方法:检查URL中的API版本,查看回收站中的已删除项目

API-Specific Guides

特定API指南

Detailed patterns for each API are in the
references/
directory. Load these when working with specific APIs.
每个API的详细模式位于
references/
目录中。处理特定API时请加载这些文档。

Gmail API

Gmail API

See references/gmail-api.md
  • Message CRUD, labels, threads
  • MIME handling, attachments
  • Push notifications (Pub/Sub)
查看references/gmail-api.md
  • 消息增删改查、标签、线程
  • MIME处理、附件
  • 推送通知(Pub/Sub)

Calendar API

Calendar API

See references/calendar-api.md
  • Events CRUD, recurring events
  • Free/busy queries
  • Calendar sharing
查看references/calendar-api.md
  • 事件增删改查、重复事件
  • 空闲/忙碌查询
  • 日历共享

Drive API

Drive API

See references/drive-api.md
  • File upload/download
  • Permissions, sharing
  • Search queries
查看references/drive-api.md
  • 文件上传/下载
  • 权限、共享
  • 搜索查询

Sheets API

Sheets API

See references/sheets-api.md
  • Reading/writing cells
  • A1 notation, ranges
  • Batch updates
查看references/sheets-api.md
  • 单元格读取/写入
  • A1表示法、范围
  • 批量更新

Chat API

Chat API

See references/chat-api.md
  • Bots, webhooks
  • Cards v2, interactive forms
  • Spaces, members, reactions
(Additional API references added as MCP servers are built)

查看references/chat-api.md
  • 机器人、Webhook
  • Cards v2、交互式表单
  • 空间、成员、反应
(随着MCP服务器的构建,将添加更多API文档)

Package Versions (Verified 2026-01-09)

包版本(2026-01-09已验证)

json
{
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20260109.0",
    "wrangler": "^4.58.0",
    "jose": "^6.1.3"
  }
}

json
{
  "devDependencies": {
    "@cloudflare/workers-types": "^4.20260109.0",
    "wrangler": "^4.58.0",
    "jose": "^6.1.3"
  }
}

Official Documentation

官方文档

Skill Roadmap

技能路线图

APIs documented as MCP servers are built:
  • Gmail API
  • Calendar API
  • Drive API
  • Sheets API
  • Docs API
  • Chat API (migrated from google-chat-api skill)
  • Meet API
  • Forms API
  • Tasks API
  • Admin SDK
  • People API
随着MCP服务器的构建,将陆续记录以下API:
  • Gmail API
  • Calendar API
  • Drive API
  • Sheets API
  • Docs API
  • Chat API(从google-chat-api技能迁移)
  • Meet API
  • Forms API
  • Tasks API
  • Admin SDK
  • People API