Google 最近開源了一個統一的命令列工具 gws,可以用一支 CLI 操作 Drive、Gmail、Calendar、Sheets 等所有 Google Workspace 服務。更吸引我的是它能當 MCP 伺服器跑,讓 AI agent 直接操作 Google Workspace API。

我在 Windows 上裝它,結果踩了三個坑,花了不少時間才搞定。紀錄一下。

gws 是什麼

gws 用 Rust 寫的,最特別的地方是它的命令不是寫死的——而是從 Google Discovery Service 動態建構。Google 新增 API 端點時,gws 自動就能用,不需要更新軟體。

目前支援的服務:

  • Drive — 檔案管理
  • Spreadsheets — 試算表
  • Gmail — 郵件讀寫
  • Calendar — 行事曆
  • Documents — 文件
  • Presentations — 簡報
  • Tasks — 待辦事項

所有回應都是 JSON 格式,很適合寫腳本或讓 AI agent 呼叫。

安裝:npm 裝不起來

官方文件說用 npm 裝:

1
npm install -g @googleworkspace/cli

在 Windows 上直接炸了:

1
2
Error fetching release: An error occurred untarring the artifact:
stderr: tar: Cannot connect to C: resolve failed

npm 的安裝腳本會從 GitHub Releases 下載 .tar.gz,但 Windows 的 tar 處理路徑有問題,解壓失敗。

解法:手動下載二進位檔

1
2
3
4
5
6
7
8
9
# 下載 Windows 版本
curl -sL -o gws.tar.gz https://github.com/googleworkspace/cli/releases/download/v0.4.2/gws-x86_64-pc-windows-msvc.tar.gz

# 解壓
tar xzf gws.tar.gz

# 把 gws.exe 丟到 PATH 裡的任何目錄
# 我放在 Node.js 目錄,因為它已經在 PATH 中
cp gws-x86_64-pc-windows-msvc/gws.exe "/c/Program Files/nodejs/gws.exe"

注意:如果你之前 npm 安裝失敗,它會留下壞掉的 shim 檔案(gwsgws.cmdgws.ps1)。這些 shim 會攔截你的指令,導致 Cannot find module run-gws.js 錯誤。先刪掉它們,再放你的 gws.exe

1
2
3
4
# 清掉 npm 留下的殘骸
rm "/c/Program Files/nodejs/gws"
rm "/c/Program Files/nodejs/gws.cmd"
rm "/c/Program Files/nodejs/gws.ps1"

驗證:

1
2
gws --version
# gws 0.4.2

認證設定:需要手動建 OAuth Client

gws 提供了 gws auth setup 自動設定,但它依賴 gcloud CLI。如果你沒裝 gcloud,它會提示你安裝。

就算裝了 gcloud 跑 auth setup,在 Step 5 建立 OAuth Client 時也會失敗——因為 Google Cloud 不允許 API 自動建立 OAuth Client ID,必須手動操作。

手動建立 OAuth 憑證

  1. Google Cloud Console 選擇或建立專案

  2. 設定 OAuth 同意畫面:

    • APIs & Services → OAuth consent screen
    • User Type 選 External
    • App name 填 gws CLI
    • 填入你的 email,一路 Save and Continue
  3. 建立 OAuth Client ID:

    • APIs & Services → Credentials
    • Create Credentials → OAuth client ID
    • Application type 選 Desktop app
    • Name 填 gws CLI
    • 點 Create,記下 Client ID 和 Client Secret
  4. 設定環境變數後登入:

1
2
3
export GOOGLE_WORKSPACE_CLI_CLIENT_ID="你的-client-id.apps.googleusercontent.com"
export GOOGLE_WORKSPACE_CLI_CLIENT_SECRET="你的-client-secret"
gws auth login

瀏覽器會跳出 Google 登入頁面,授權後回到終端機會看到:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"status": "success",
"message": "Authentication successful. Encrypted credentials saved.",
"scopes": [
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/documents",
"https://www.googleapis.com/auth/presentations",
"https://www.googleapis.com/auth/tasks"
]
}

看到 success 就以為搞定了?我也是。

最大的坑:加密憑證在 Git Bash 下失效

登入成功後,執行任何 API 呼叫:

1
gws drive files list --params '{"pageSize": 3}'

結果:

1
2
3
4
5
6
7
{
"error": {
"code": 401,
"message": "Access denied. No credentials provided.",
"reason": "authError"
}
}

auth status 明明顯示 token_valid: true,但 API 呼叫就是 401。

問題出在 gws 用 AES-256-GCM 加密 儲存憑證(credentials.enc),解密依賴 OS Keyring。在 Windows 的 Git Bash 環境下,Keyring 的路徑解析跟原生 Windows 不一致,導致 API 呼叫時找不到憑證。

解法:解密憑證,改用明文 JSON

gws 有 auth export 指令,但它輸出的值是被遮蔽的(GOCS...XEca),沒辦法直接用。

得自己解密 credentials.enc。加密金鑰存在 ~/.config/gws/.encryption_key,用 Python 解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import base64, json
from cryptography.hazmat.primitives.ciphers.aead import AESGCM

# 讀取加密金鑰
with open('C:/Users/你的使用者/.config/gws/.encryption_key') as f:
key = base64.b64decode(f.read().strip())

# 讀取加密憑證
with open('C:/Users/你的使用者/.config/gws/credentials.enc', 'rb') as f:
data = f.read()

# AES-256-GCM 解密:前 12 bytes 是 nonce
nonce = data[:12]
ciphertext = data[12:]
aesgcm = AESGCM(key)
plaintext = aesgcm.decrypt(nonce, ciphertext, None)

# 寫入明文 credentials.json
creds = json.loads(plaintext)
with open('C:/Users/你的使用者/.config/gws/credentials.json', 'w') as f:
json.dump(creds, f, indent=2)

需要先裝 cryptography 套件:pip install cryptography

解密後,設定環境變數指向明文檔案(注意要用 Windows 風格路徑):

1
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE="C:\Users\你的使用者\.config\gws\credentials.json"

再試一次:

1
gws drive files list --params '{"pageSize": 3}'
1
2
3
4
5
6
7
8
9
10
{
"files": [
{
"id": "1G8UvtYMIIR5gFAqC...",
"kind": "drive#file",
"mimeType": "application/vnd.google-apps.spreadsheet",
"name": "我的試算表"
}
]
}

終於正常了。

永久設定

為了避免每次開終端都要手動設定,把環境變數寫進 ~/.bashrc

1
2
3
4
# Google Workspace CLI
export GOOGLE_WORKSPACE_CLI_CLIENT_ID="你的-client-id.apps.googleusercontent.com"
export GOOGLE_WORKSPACE_CLI_CLIENT_SECRET="你的-client-secret"
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE="C:\Users\你的使用者\.config\gws\credentials.json"

如果你用 PowerShell,改設定系統環境變數:

1
[Environment]::SetEnvironmentVariable("GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE", "C:\Users\你的使用者\.config\gws\credentials.json", "User")

基本用法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 列出 Drive 檔案
gws drive files list --params '{"pageSize": 5}'

# 列出 Gmail 郵件
gws gmail users.messages list --params '{"userId": "me", "maxResults": 5}'

# 列出行事曆
gws calendar calendarList list

# 建立 Google 試算表
gws sheets spreadsheets create --json '{"properties": {"title": "新試算表"}}'

# 預覽請求但不實際執行
gws drive files list --dry-run

當 MCP 伺服器

gws 可以直接當 MCP 伺服器跑,讓 Claude Code 或其他 AI agent 操作 Google Workspace:

1
gws mcp -s drive,gmail,calendar

這代表你可以在 AI 對話中直接說「幫我列出 Drive 上的檔案」或「寫封信給某某」,AI agent 會透過 gws MCP 伺服器直接執行。

踩坑總結

原因 解法
npm 安裝失敗 Windows tar 路徑解析問題 手動下載二進位檔
npm 殘留 shim 攔截指令 失敗的安裝留下壞檔案 刪掉 gws/gws.cmd/gws.ps1
auth setup 無法建 OAuth Client Google 不允許 API 自動建立 手動到 Cloud Console 建立
登入成功但 API 401 Git Bash 下 OS Keyring 路徑不一致 解密 credentials.enc 改用明文 JSON
auth export 值被遮蔽 安全設計,不輸出完整 token 用 Python + AES-256-GCM 自行解密

gws 還在 v0.4.2,離 v1.0 有段距離。Windows 上的體驗明顯比 macOS/Linux 粗糙。但它的動態 API 建構和 MCP 伺服器功能確實有前景,值得持續關注。