Installation¶
Complete setup of all 8 Google Workspace MCP servers, including the required manual Apps Script web app deployments.
Agent-assisted install
This repo includes a workspace-lite-installer skill for OpenCode agents. Agents can run local setup commands, clasp push, and refresh existing deployments, but the user must review OAuth scopes and verify initial web app deployment settings in the Apps Script GUI.
Prerequisites¶
| Requirement | Version / Command | Notes |
|---|---|---|
| Node.js | 20+ | node --version |
| npm | Bundled with Node.js | npm --version |
| clasp | latest | npm install -g @google/clasp |
| curl | any modern version | Included with macOS and Git Bash; used for token bootstrap |
| Google account | — | With access to the Workspace services you plan to use |
Windows users should run setup from Git Bash or MSYS2. Native PowerShell can run the MCP servers, but the installer and deployment helper scripts expect a bash environment.
On Windows, launch OpenCode from a shell that has the workspace-lite environment variables loaded, or persist .env with the provided PowerShell helper in Step 5. The setup script emits Windows OpenCode commands with the local node_modules\\.bin\\tsx.cmd wrapper because direct process spawning does not always resolve npx tsx.
Step 1: Clone¶
The setup script installs dependencies with npm ci when package-lock.json is present, then builds all 8 service packages. To preview the flow without creating Apps Script projects, bootstrap secrets, or .env entries, run bash ./scripts/setup.sh --dry-run.
Step 2: Run the Setup Script¶
With no arguments, all 8 services are installed. To set up a smaller, intentional subset, pass a profile or an explicit service list:
bash ./scripts/setup.sh --profile core # drive, gmail, calendar
bash ./scripts/setup.sh --services drive,gmail # exactly these services
| Profile | Services |
|---|---|
full | drive, gmail, calendar, sheets, slides, docs, tasks, forms (same as no argument) |
core | drive, gmail, calendar |
authoring | drive, docs, sheets, slides |
planning | calendar, tasks, docs |
forms | drive, sheets, forms |
Every setup phase respects the selection: only selected services get Apps Script projects, deployment prompts, .env entries, and OpenCode config snippets. --dry-run prints exactly which services would be touched. Unknown profile or service names fail immediately with the valid options listed. Setup is idempotent per service, so a partial install is not a dead end — rerun later with --profile full (or a larger list) to add the remaining services; existing services are reused and existing .env tokens are never overwritten. A partial .env is normal and fully supported: wslite doctor and the MCP servers only consider the services whose variables are present.
The script automates:
| Step | What happens |
|---|---|
| 1. Authenticate | Opens a browser for clasp login (one-time) |
| 2. Create projects | Creates or reuses 8 Apps Script standalone projects with correct OAuth scopes |
| 3. Push code | Pushes Auth.gs, Code.gs, Response.gs, and service files to each project |
| 4. Deploy guide | Prints Apps Script editor URLs and manual web app deployment instructions |
| 5. Token bootstrap | Collects deployment URLs, bootstraps auth tokens, appends successful entries to .env |
| 6. Config output | Prints an OpenCode mcp JSON block for the selected services (other clients: see MCP Client Config) |
| 7. Skill setup | Prints symlink commands for the google-workspace and workspace-lite-installer skills |
Step 3: Deploy Web Apps In Apps Script¶
The setup script pauses here and prints an Apps Script editor URL for each of the 8 services, like https://script.google.com/d/<script-id>/edit.
Open each editor URL and create the deployment manually:
- Click Deploy → New deployment.
- Click Select type or the gear icon.
- Choose Web app.
- Set Execute as to Me.
- Set Who has access to Anyone.
- Click Deploy.
- If Google asks for authorization, review permissions and allow the scopes for that service.
- Copy the Web app URL ending in
/exec.
Use these exact settings:
| Field | Value |
|---|---|
| Deploy type | Web app |
| Execute as | Me (USER_DEPLOYING) |
| Who has access | Anyone (anonymous) |
Copy each deployment URL (looks like https://script.google.com/macros/s/.../exec) and paste it back into the script prompt.
GUI step requires the user
Agents and scripts can push code, create Apps Script versions, and refresh an existing deployment with clasp redeploy. The initial deployment still needs the Apps Script editor so the user can verify Web app, Execute as: Me, Who has access: Anyone, and OAuth scopes before approving access.
Step 4: Install the Agent Skills¶
mkdir -p ~/.config/opencode/skills
ln -sf "$(pwd)/skills/google-workspace" ~/.config/opencode/skills/google-workspace
ln -sf "$(pwd)/skills/workspace-lite-installer" ~/.config/opencode/skills/workspace-lite-installer
This makes two repo skills available to OpenCode. google-workspace teaches agents how to use the 218 Workspace tools. workspace-lite-installer teaches agents how to install, push, redeploy, and troubleshoot the MCPs while preserving the user-only Google authorization steps.
Step 5: Configure OpenCode¶
The setup script prints a JSON block. Add it to your opencode.jsonc under mcp:
{
"mcp": {
"google-drive": {
"type": "local",
"command": ["npx", "tsx", "/path/to/workspace-lite/packages/drive/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_DRIVE_PROXY_URL": "{env:GOOGLE_WORKSPACE_DRIVE_PROXY_URL}",
"GOOGLE_WORKSPACE_DRIVE_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_DRIVE_PROXY_TOKEN}"
}
},
// ... repeat for google-gmail, google-calendar, google-sheets, google-slides, google-docs, google-tasks, google-forms
}
}
Source the generated .env file (or copy exports to .zshrc):
On Windows, persist the generated .env values at User scope so native OpenCode can inherit them after restart:
powershell -ExecutionPolicy Bypass -File .\skills\workspace-lite-installer\scripts\persist-env.ps1 -EnvFile .\.env
Restart OpenCode. When all 8 services are configured, all 218 tools are available.
Windows OpenCode command
On Windows, the generated command should point at the local tsx.cmd wrapper, for example:
"command": ["C:\\path\\to\\workspace-lite\\node_modules\\.bin\\tsx.cmd", "C:\\path\\to\\workspace-lite\\packages\\drive\\src\\index.ts"]
This is expected. It avoids -32000: Connection closed failures caused by direct-spawn clients that do not resolve npx through a shell.
If you skipped deployment URLs or bootstrap failed, the script leaves .env unchanged for those services. Deploy the web apps in the Apps Script editor, rerun bash ./scripts/setup.sh, paste the /exec deployment URLs, then source .env and restart OpenCode.
Windows npm install integrity
If MCP servers crash on startup with ERR_MODULE_NOT_FOUND for a .js file inside node_modules such as zod or ajv, run:
A full clean reinstall repairs cases where npm reported success but left package ESM files missing. Incremental reinstalls may not fix this state.
Manual Setup (Alternative)¶
If you prefer to configure each service step-by-step without the setup script.
Environment Variables¶
For each service, two environment variables are required:
| Service | URL variable | Token variable |
|---|---|---|
| Drive | GOOGLE_WORKSPACE_DRIVE_PROXY_URL | GOOGLE_WORKSPACE_DRIVE_PROXY_TOKEN |
| Gmail | GOOGLE_WORKSPACE_GMAIL_PROXY_URL | GOOGLE_WORKSPACE_GMAIL_PROXY_TOKEN |
| Calendar | GOOGLE_WORKSPACE_CALENDAR_PROXY_URL | GOOGLE_WORKSPACE_CALENDAR_PROXY_TOKEN |
| Sheets | GOOGLE_WORKSPACE_SHEETS_PROXY_URL | GOOGLE_WORKSPACE_SHEETS_PROXY_TOKEN |
| Slides | GOOGLE_WORKSPACE_SLIDES_PROXY_URL | GOOGLE_WORKSPACE_SLIDES_PROXY_TOKEN |
| Docs | GOOGLE_WORKSPACE_DOCS_PROXY_URL | GOOGLE_WORKSPACE_DOCS_PROXY_TOKEN |
| Tasks | GOOGLE_WORKSPACE_TASKS_PROXY_URL | GOOGLE_WORKSPACE_TASKS_PROXY_TOKEN |
| Forms | GOOGLE_WORKSPACE_FORMS_PROXY_URL | GOOGLE_WORKSPACE_FORMS_PROXY_TOKEN |
Deploying Manually¶
- Create each Apps Script project with
clasp create --type standalone, or reuse the matching project fromclasp list --json - Push code with
clasp push - Deploy as a web app in the Apps Script GUI and copy the deployment URL. The user must verify scopes and web app access settings here.
- Read the setup key from the generated, untracked
BootstrapSecret.gsfile and write the bootstrapped token directly to your environment file:
TOKEN_RESPONSE="$(curl -sL -X POST -H 'Content-Type: application/json' -d '{"setupKey":"<bootstrap-setup-key>"}' "https://script.google.com/macros/s/<deployment-id>/exec")"
TOKEN_RESPONSE="$TOKEN_RESPONSE" node -e 'const fs = require("fs"); const r = JSON.parse(process.env.TOKEN_RESPONSE); if (!r.success) throw new Error(r.error?.message || "Bootstrap failed"); fs.appendFileSync(".env", `export GOOGLE_WORKSPACE_<SERVICE>_PROXY_TOKEN=${JSON.stringify(r.data.token)}\n`)'
- Set the matching
GOOGLE_WORKSPACE_<SERVICE>_PROXY_URLin.zshrcor.env
OpenCode Config (Manual)¶
{
"mcp": {
"google-drive": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/drive/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_DRIVE_PROXY_URL": "{env:GOOGLE_WORKSPACE_DRIVE_PROXY_URL}",
"GOOGLE_WORKSPACE_DRIVE_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_DRIVE_PROXY_TOKEN}"
}
},
"google-gmail": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/gmail/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_GMAIL_PROXY_URL": "{env:GOOGLE_WORKSPACE_GMAIL_PROXY_URL}",
"GOOGLE_WORKSPACE_GMAIL_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_GMAIL_PROXY_TOKEN}"
}
},
"google-calendar": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/calendar/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_CALENDAR_PROXY_URL": "{env:GOOGLE_WORKSPACE_CALENDAR_PROXY_URL}",
"GOOGLE_WORKSPACE_CALENDAR_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_CALENDAR_PROXY_TOKEN}"
}
},
"google-sheets": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/sheets/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_SHEETS_PROXY_URL": "{env:GOOGLE_WORKSPACE_SHEETS_PROXY_URL}",
"GOOGLE_WORKSPACE_SHEETS_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_SHEETS_PROXY_TOKEN}"
}
},
"google-slides": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/slides/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_SLIDES_PROXY_URL": "{env:GOOGLE_WORKSPACE_SLIDES_PROXY_URL}",
"GOOGLE_WORKSPACE_SLIDES_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_SLIDES_PROXY_TOKEN}"
}
},
"google-docs": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/docs/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_DOCS_PROXY_URL": "{env:GOOGLE_WORKSPACE_DOCS_PROXY_URL}",
"GOOGLE_WORKSPACE_DOCS_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_DOCS_PROXY_TOKEN}"
}
},
"google-tasks": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/tasks/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_TASKS_PROXY_URL": "{env:GOOGLE_WORKSPACE_TASKS_PROXY_URL}",
"GOOGLE_WORKSPACE_TASKS_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_TASKS_PROXY_TOKEN}"
}
},
"google-forms": {
"type": "local",
"command": ["npx", "tsx", "/path/to/packages/forms/src/index.ts"],
"environment": {
"GOOGLE_WORKSPACE_FORMS_PROXY_URL": "{env:GOOGLE_WORKSPACE_FORMS_PROXY_URL}",
"GOOGLE_WORKSPACE_FORMS_PROXY_TOKEN": "{env:GOOGLE_WORKSPACE_FORMS_PROXY_TOKEN}"
}
}
}
}
Token Lifecycle¶
| Phase | Description |
|---|---|
| Bootstrap | JSON POST with setupKey triggers one-time token generation. The token is generated from Utilities.getUuid() plus a second UUID with dashes removed, stored in PropertiesService.getScriptProperties() under PROXY_AUTH_TOKEN, returned once, and then PROXY_BOOTSTRAPPED=true is set. |
| Storage | Token lives in Apps Script properties — durable across deployments, survives code pushes. |
| Rotation | JSON POST with setupKey and rotate:true validates the local setup key, replaces the primary token, marks bootstrap complete, and returns the new token once. |
| Usage | Every POST request includes token in the JSON body. Auth.gs validates against the stored token. |
Bootstrap is one-shot
The bootstrap endpoint only works once per deployment. Save the token immediately. If lost, rerun setup interactively and accept the rotation prompt.