Step-by-step instructions for setting up Google Workspace + Slack MCP servers in Claude Code without AI assistance.
npm install -g @googleworkspace/cli
gws --version # should be 0.7+- Go to https://console.cloud.google.com/projectcreate
- Name it something like
gws-mcp(project ID must be globally unique) - Note the project ID
gcloud services enable \
gmail.googleapis.com \
drive.googleapis.com \
calendar-json.googleapis.com \
sheets.googleapis.com \
docs.googleapis.com \
--project=YOUR_PROJECT_ID- Go to:
https://console.cloud.google.com/apis/credentials/consent?project=YOUR_PROJECT_ID - Select External user type
- Fill in:
- App name: "Claude MCP" (anything works)
- User support email: your email
- Developer contact: your email
- Skip scopes (they're requested at login time)
- Add test users: Add every Google account you want to connect
- Save
Go to: https://console.cloud.google.com/apis/credentials?project=YOUR_PROJECT_ID
For each Google account you want to connect:
- Click "Create Credentials" → "OAuth client ID"
- Application type: Desktop app
- Name: something descriptive (e.g., "MCP - personal", "MCP - work")
- Click "Create"
- Download the JSON file
- Save it:
mkdir -p ~/.config/gws # Move the downloaded file: mv ~/Downloads/client_secret_*.json ~/.config/gws/client_secret_ACCOUNTNAME.json
Why separate clients? Using the same OAuth client ID for two Google accounts causes the second login to invalidate the first account's refresh token. This is an OAuth2 behavior, not a bug.
For each account (e.g., "personal" and "work"):
# Set this account's client secret as active
cp ~/.config/gws/client_secret_personal.json ~/.config/gws/client_secret.json
# Login — browser will open, sign in with the CORRECT Google account
gws auth login -s drive,gmail,calendar,sheets,docs
# Export the credentials (includes refresh token)
gws auth export --unmasked > ~/.config/gws/personal.jsonRepeat for each additional account, swapping the client secret file each time.
cp scripts/gws-token-wrapper.sh ~/.config/gws/gws-token-wrapper.sh
chmod +x ~/.config/gws/gws-token-wrapper.shWhat this does: The gws CLI can only hold one account's credentials at a time. The wrapper script reads the exported credential file, mints a fresh OAuth access token using the refresh token, and passes it to gws mcp via the GOOGLE_WORKSPACE_CLI_TOKEN environment variable (the highest-priority auth method).
The GCP project owner's account works automatically. For accounts on other domains (e.g., a work Google Workspace), you need to grant API access:
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="user:you@workdomain.com" \
--role="roles/serviceusage.serviceUsageConsumer"- Go to https://api.slack.com/apps
- "Create New App" → "From scratch"
- Name: "Claude MCP" (anything)
- Select your workspace
Go to "OAuth & Permissions" → "User Token Scopes" → Add these scopes:
Required (read-only):
channels:history— read public channel messageschannels:read— list public channelsgroups:history— read private channel messagesgroups:read— list private channelsim:history— read DMsim:read— list DMsmpim:history— read group DMsmpim:read— list group DMssearch:read— search messagesusers:read— list usersusers:read.email— see user emailsusergroups:read— list user groups
Optional (for posting):
chat:write— send messages
- "OAuth & Permissions" → "Install to Workspace"
- Authorize
- Copy the User OAuth Token (
xoxp-...)
In the root of the project where you want these MCP servers available, create .mcp.json:
{
"mcpServers": {
"gws-personal": {
"command": "/Users/YOUR_USERNAME/.config/gws/gws-token-wrapper.sh",
"args": [
"/Users/YOUR_USERNAME/.config/gws/personal.json",
"-s", "gmail,drive,calendar,sheets,docs"
]
},
"gws-work": {
"command": "/Users/YOUR_USERNAME/.config/gws/gws-token-wrapper.sh",
"args": [
"/Users/YOUR_USERNAME/.config/gws/work.json",
"-s", "gmail,drive,calendar,sheets,docs"
]
},
"slack": {
"command": "npx",
"args": ["-y", "slack-mcp-server@latest"],
"env": {
"SLACK_MCP_XOXP_TOKEN": "xoxp-your-token-here"
}
}
}
}Replace paths and tokens with your actual values.
To make these available in ALL projects, add the mcpServers config to ~/.claude.json instead.
.mcp.json contains tokens — never commit it.
echo ".mcp.json" >> .gitignoreMCP servers only load at session launch. You must restart after creating/editing .mcp.json.
After restarting Claude Code, test each server:
# Gmail — list recent emails
ToolSearch: "+gws gmail messages list"
mcp__gws-personal__gmail_users_messages_list(params: {"userId": "me", "maxResults": 3})
# Drive — search files
ToolSearch: "+gws drive files"
mcp__gws-personal__drive_files_list(params: {"q": "modifiedTime > '2024-01-01'", "pageSize": 5})
# Slack — list channels
ToolSearch: "+slack channels"
mcp__slack__channels_list(channel_types: "public_channel")
If tools don't appear in ToolSearch, check:
.mcp.jsonis at the project root (not inside.claude/)- You restarted Claude Code after creating it
- The wrapper script is executable (
chmod +x) - Credential files exist at the paths specified
See the README for a full list of known gotchas.
"Access blocked" during OAuth login: → Add the Google account as a test user on the OAuth consent screen
Wrong account's emails showing up:
→ Each account needs its own OAuth client ID. Check that client_id differs between credential files.
MCP servers not starting (no error):
→ mcpServers in settings.local.json is silently ignored. Must be in .mcp.json (project root) or ~/.claude.json (global).
API calls fail with "permission denied":
→ For work accounts on a different domain, grant IAM access (see Step 8 above).
→ Also check: gcloud auth application-default set-quota-project YOUR_PROJECT_ID