This guide deploys the gdrive MCP server to Cloudflare Workers, giving any MCP client (Claude Code, Claude Desktop, etc.) access to your Google Workspace via a permanent URL.
After setup, token refresh is automatic — you authenticate once and it works forever.
Run: node --version
- If the output is
v18.x.xor higher: proceed. - If lower than 18 or not found: tell the user they need Node.js 18+ and link to https://nodejs.org — pause until they confirm it is installed.
Run: npx wrangler --version
- If it prints a version: proceed.
- If not found: run
npm install -g wrangler, then verify withnpx wrangler --version.
Run: npx wrangler whoami
- If it shows an account name: note the account name and proceed to Phase 2.
- If it says "not authenticated": run
npx wrangler login. This opens a browser for Cloudflare OAuth. Tell the user to complete it, then re-runnpx wrangler whoamito confirm.
ASK: "Do you already have a Google Cloud project with OAuth credentials (gcp-oauth.keys.json)?"
Options:
- "Yes — I have the credentials file ready"
- "No — I need to set up a Google Cloud project"
ASK: "What is the full path to your gcp-oauth.keys.json file?"
Run:
mkdir -p credentials
cp "[path from user]" credentials/gcp-oauth.keys.jsonVerify it is valid JSON:
node -e "JSON.parse(require('fs').readFileSync('credentials/gcp-oauth.keys.json')); console.log('Valid credentials file')"Skip to Phase 3.
USER ACTION: Open https://console.cloud.google.com/projectcreate
Tell the user:
"Create a new project with any name (e.g.
gdrive-mcp). Click Create and wait for it to finish. Then make sure the new project is selected in the top dropdown. Tell me when you're on the project dashboard."
USER ACTION: Tell the user to open each link below and click Enable for each API:
- Google Drive API — https://console.cloud.google.com/apis/library/drive.googleapis.com
- Google Sheets API — https://console.cloud.google.com/apis/library/sheets.googleapis.com
- Google Docs API — https://console.cloud.google.com/apis/library/docs.googleapis.com
- Google Forms API — https://console.cloud.google.com/apis/library/forms.googleapis.com
- Gmail API — https://console.cloud.google.com/apis/library/gmail.googleapis.com
- Google Calendar API — https://console.cloud.google.com/apis/library/calendar-json.googleapis.com
"Open each link, click Enable, and wait for the status to show 'API enabled'. Come back and tell me when all 6 are done."
USER ACTION: Open https://console.cloud.google.com/apis/credentials/consent
Tell the user:
"Configure the OAuth consent screen:
- User type: choose External (unless you have a Google Workspace org, then Internal)
- App name:
Google Drive MCP Server- User support email: your email address
- Developer contact: your email address
- Click Save and Continue
- On the Scopes page, click Add or Remove Scopes and add these exact scopes:
https://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/spreadsheetshttps://www.googleapis.com/auth/documentshttps://www.googleapis.com/auth/forms.bodyhttps://www.googleapis.com/auth/gmail.modifyhttps://www.googleapis.com/auth/calendar- Click Save and Continue
- On the Test users page, click Add Users and add your Google email
- Click Save and Continue, then Back to Dashboard Tell me when done."
USER ACTION: Open https://console.cloud.google.com/apis/credentials
Tell the user:
"Create OAuth credentials:
- Click Create Credentials → OAuth client ID
- Application type: Desktop application
- Name:
gdrive-mcp-server- Click Create
- In the popup, click Download JSON
- Save the file — you'll need to tell me the path"
ASK: "What is the full path to the JSON file you just downloaded?"
Run:
mkdir -p credentials
cp "[path from user]" credentials/gcp-oauth.keys.jsonVerify:
node -e "const k=JSON.parse(require('fs').readFileSync('credentials/gcp-oauth.keys.json')); console.log('Type:', k.installed ? 'Desktop app (correct)' : k.web ? 'Web app (wrong type)' : 'Unknown')"If the output says "Web app (wrong type)": tell the user they need to go back and create a Desktop application credential, not a Web application. Walk them through it again.
This step authenticates with Google locally. The tokens are saved to .tokens.json,
then uploaded to Cloudflare KV so the Worker can use them.
npm run buildIf the build fails: check the error, fix TypeScript issues, and retry.
GDRIVE_TOKEN_ENCRYPTION_KEY=$(openssl rand -base64 32)
echo "GDRIVE_TOKEN_ENCRYPTION_KEY=$GDRIVE_TOKEN_ENCRYPTION_KEY" > .env
echo "Encryption key generated and saved to .env"node ./dist/index.js authUSER ACTION: Tell the user:
"A browser window should have opened. Sign in with your Google account and grant all the requested permissions (Drive, Sheets, Docs, Forms, Gmail, Calendar). After approving, you'll see a success message in the terminal. Come back and tell me when it's done."
ls -la .tokens.json 2>/dev/null && echo "Tokens saved successfully" || echo "ERROR: .tokens.json not found — auth may have failed"If .tokens.json is missing: ask the user what error appeared in the terminal and
diagnose the auth failure before proceeding.
npx wrangler kv:namespace create GDRIVE_KV --preview falseParse the output. It will contain a line like:
{ binding = "GDRIVE_KV", id = "abc123..." }
Extract the namespace ID from the output.
Read the current wrangler.toml, find the [[kv_namespaces]] section,
and replace the id value with the namespace ID you just created.
Verify:
grep "id" wrangler.tomlThe id should match what wrangler printed.
NAMESPACE_ID=$(grep -A2 '\[\[kv_namespaces\]\]' wrangler.toml | grep '^id' | awk -F'"' '{print $2}')
npx wrangler kv:key put --namespace-id="$NAMESPACE_ID" "gdrive:oauth:tokens" "$(cat .tokens.json)"If this fails because $NAMESPACE_ID is empty: read wrangler.toml directly and use
the literal ID value from the file.
CLIENT_ID=$(node -e "const k=JSON.parse(require('fs').readFileSync('credentials/gcp-oauth.keys.json')); console.log(k.installed?.client_id || k.web?.client_id)")
CLIENT_SECRET=$(node -e "const k=JSON.parse(require('fs').readFileSync('credentials/gcp-oauth.keys.json')); console.log(k.installed?.client_secret || k.web?.client_secret)")
echo "Client ID: $CLIENT_ID"echo "$CLIENT_ID" | npx wrangler secret put GDRIVE_CLIENT_ID
echo "$CLIENT_SECRET" | npx wrangler secret put GDRIVE_CLIENT_SECRETVerify both are set:
npx wrangler secret listShould show GDRIVE_CLIENT_ID and GDRIVE_CLIENT_SECRET.
npx wrangler deployNote the URL printed in the output — it looks like https://gdrive-mcp.[account].workers.dev.
Verify the worker is alive:
WORKER_URL=$(npx wrangler deployments list 2>/dev/null | grep -o 'https://[^ ]*' | head -1)
if [ -z "$WORKER_URL" ]; then
# Fallback: ask the user for the URL from the deploy output
echo "Please tell me the URL from the deploy output above."
else
curl -s "$WORKER_URL" && echo "Worker is responding"
fiASK: "How would you like to connect this MCP server to Claude Code?"
Options:
- "User scope — available in all my projects (Recommended)"
- "Project scope — only this project"
Use the worker URL from Phase 5 deploy output.
For user scope:
claude mcp add --scope user --transport http gdrive [WORKER_URL]/mcpFor project scope:
claude mcp add --scope project --transport http gdrive [WORKER_URL]/mcpVerify it was added:
claude mcp listShould show gdrive with the worker URL.
Summarize for the user what was set up:
- Worker URL: [URL from Phase 5]
- KV namespace: [ID from Phase 4]
- Claude Code scope: [user/project from Phase 6]
- Token refresh: Automatic — the Worker refreshes tokens as needed
Next step: Start a new Claude Code session. The gdrive MCP tool is now available.
Try: "List my Google Drive files" or "What's on my calendar today?"