HR-Assistant / docs /mcp /gmail_mcp_gcp_setup.md
owenkaplinsky
Clean initial commit for HuggingFace
363cda9
|
raw
history blame
10.4 kB

Gmail MCP – GCP Setup (Terraform + Bash)

This folder provisions the minimum GCP infrastructure to run the Gmail MCP server without requiring billing:

  • Creates (or adopts) a GCP project
  • Enables gmail.googleapis.com
  • Grants your user:
  • roles/editor
  • roles/serviceusage.serviceUsageAdmin Prints console links to finish OAuth (consent screen + Desktop client)

    Billing is not required for Gmail API or OAuth Desktop client.

Prerequisites

  • Terraform β‰₯ 1.6
  • gcloud (optional but useful for verifying/importing projects)
  • A Google account (you'll also add it as a Test user on the OAuth consent screen)

Files

  • versions.tf – provider & Terraform version pins
  • providers.tf – Google provider config (uses project_id and region)
  • variables.tf – input variables
  • main.tf – project, Gmail API enablement, IAM bindings
  • outputs.tf – project IDs and console URLs
  • terraform.tfvars – team defaults (simple key = "value" pairs)

Example terraform.tfvars:

project_id   = "gradio-hackathon-25"
project_name = "Gradio Agent MCP Hackathon 25"
user_email   = "hr.cjordan.agent.hack.winter25@gmail.com"
# region    = "europe-west3" # optional

*Quick Start (recommended: use the scripts)

From the repo root:

  1. Authenticate gcloud + ADC
chmod +x scripts/gcp_setup.sh
./scripts/gcp_setup.sh
  1. Apply Terraform with smart defaults + auto-import
chmod +x scripts/terraform_apply.sh
./scripts/terraform_apply.sh
  • The script prompts for project_id, project_name, user_email.
  • Press Enter to use defaults from terraform/terraform.tfvars.
  • If the project already exists, it is auto-imported to avoid 409 alreadyExists.

Manual Usage (alternative)

Run these from this terraform/ directory:

terraform init

# If the project already exists, import it so Terraform manages it:
# terraform import google_project.project <your-project-id>

terraform apply

Override values:

terraform apply \
  -var="project_id=my-mcp-project" \
  -var="project_name=My MCP Project" \
  -var="user_email=you@example.com"

Or via env vars:

export TF_VAR_project_id="my-mcp-project"
export TF_VAR_project_name="My MCP Project"
export TF_VAR_user_email="you@example.com"
terraform apply

Outputs

  • project_id / project_number
  • gmail_api_service β€” "gmail.googleapis.com" (resource present β‡’ enabled)
  • console_oauth_consent_screen_url β€” configure consent (External, Test user, add scope)
  • console_oauth_credentials_url β€” create OAuth 2.0 Client ID (Desktop app)

Final OAuth Setup (one-time, in Console)

Terraform cannot create the OAuth consent screen or Desktop OAuth client, so you'll do these two steps once in the Google Cloud Console.
This setup allows your local Gmail MCP server to access Gmail via OAuth securely.

πŸ’‘ Tip: In the new Google Cloud UI, the old β€œScopes” and β€œTest users” tabs are now under Data access and Audience in the left sidebar.


1️⃣ Configure the OAuth Consent Screen

Purpose: Identify your app to Google and specify who can use it during testing.

  1. Open the link printed in Terraform outputs:
    β†’ console_oauth_consent_screen_url

  2. If prompted, choose User type: External, then click Create.

  3. Fill out App info:

    • App name: Gmail MCP Local
    • User support email: your Gmail address
    • Developer contact email: your Gmail address
    • Click Save and Continue
  4. In the left sidebar, go to Data access

    • Click Add or remove scopes
    • Add the following scopes:
      https://www.googleapis.com/auth/gmail.modify
      openid
      https://www.googleapis.com/auth/userinfo.email
      
      βœ… These provide read, send, and modify access β€” no extra Gmail scopes required.
  5. Go to Audience (left sidebar)

    • Under Test users, click Add users
    • Add your Gmail account address
    • Click Save
  6. Go to Summary and confirm:

    • User type β†’ External
    • Publishing status β†’ Testing
    • Test users β†’ your Gmail account
    • Scopes β†’ shows Gmail modify, openid, userinfo.email

2️⃣ Create a Desktop OAuth Client

Purpose: This provides the credentials your local MCP server uses to initiate the OAuth flow.

  1. Open the second Terraform output link:
    β†’ console_oauth_credentials_url

  2. Click Create credentials β†’ OAuth client ID

  3. Choose:

    • Application type: Desktop app
    • Name: gmail-mcp-desktop
  4. Click Create, then Download JSON, and move it into the expected directory:

mkdir -p ~/.gmail-mcp
mv ~/Downloads/client_secret_*.json ~/.gmail-mcp/credentials.json

⚠️ Important: Two Different JSONs

  • The file from:
gcloud auth application-default login

is your Application Default Credentials (ADC) β€” used by Terraform and gcloud. It is not the same as the Desktop OAuth client JSON. The Gmail MCP server requires the Desktop OAuth client JSON you downloaded. β†’ Place it at ~/.gmail-mcp/credentials.json.

πŸš€ When You Run the MCP Server

The server will open a browser window asking you to sign in and approve access. You'll see your app name (Gmail MCP Local) and the Gmail modify scope. After approving, tokens are cached locally (usually ~/.gmail-mcp/token.json), so you won't need to approve again.


βš™οΈ Install Required Tools

Before testing or running the Gmail MCP server, make sure the following tools are installed:

🟣 1. Install uv

uv is a fast Python package manager used to run the Gmail MCP server.

Check if it's already installed:

uv --version

If not, install it:

curl -LsSf https://astral.sh/uv/install.sh | sh

Verify:

uv --version

🟠 2. Install Node.js (includes npm and npx)

npx is used to run the MCP Inspector, which lets you test your Gmail MCP server locally.

brew install node

πŸ§ͺ Testing Locally with MCP Inspector

Once toBefore connecting to Claude Desktop or a LangGraph agent, you can visually inspect and test your Gmail MCP server using the MCP Inspector web UI.

1️⃣ Run with simple path (direct server entry)

Use this if you're already inside the ``gmail-mcp directory or the script path resolves cleanly:

npx @modelcontextprotocol/inspector uv run /Users/sebastianwefers/Desktop/development/recruitment-agent-mcp-hackathon-winter25/src/mcp_servers/gmail-mcp/src/gmail/server.py \
  --creds-file-path ~/.gmail-mcp/credentials.json \
  --token-path ~/.gmail-mcp/token.json

2️⃣ Run with full project context (recommended)

This variant is more robust and works regardless of your working directory, because it explicitly tells uv which project directory to use and where your binaries are.

npx @modelcontextprotocol/inspector \
  /Users/sebastianwefers/.local/bin/uv \
  --directory /Users/sebastianwefers/Desktop/development/recruitment-agent-mcp-hackathon-winter25/src/mcp_servers/gmail-mcp \
  run gmail \
  --creds-file-path ~/.gmail-mcp/credentials.json \
  --token-path ~/.gmail-mcp/token.json

πŸ” What Happens

When you run either command, you should see output similar to:

Starting MCP inspector...
βš™οΈ Proxy server listening on localhost:6277
πŸ”‘ Session token: 8498939effc01e03c1b879efa72768e45608056ef1ad45e5c80344a7d9362a72
   Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth

πŸš€ MCP Inspector is up and running at:
   http://localhost:6274/?MCP_PROXY_AUTH_TOKEN=8498939effc01e03c1b879efa72768e45608056ef1ad45e5c80344a7d9362a72

🌐 Opening browser...

This automatically opens a local browser window to the MCP Inspector UI, connected to your Gmail MCP server.

βœ… Expected behavior:

  • On first run, a browser window will prompt you to log in and approve access.
  • After successful OAuth, a token file will be created:
~/.gmail-mcp/token.json
  • Subsequent runs reuse this token β€” no re-auth required.
  • You can now explore, invoke, and inspect your Gmail MCP tools visually (e.g., listEmails, sendEmail, modifyLabel, etc.) right from the web UI.

πŸ’» Connecting the Gmail MCP Server to Claude Desktop

  1. Open your Claude Desktop configuration file:
nano ~/Library/Application Support/Claude/claude_desktop_config.json
  1. Add this block (update paths if necessary):
{
  "mcpServers": {
    "gmail": {
      "command": "uv",
      "args": [
        "--directory",
        "/Users/sebastianwefers/Desktop/development/recruitment-agent-mcp-hackathon-winter25/src/mcp_servers/gmail-mcp",
        "run",
        "gmail",
        "--creds-file-path",
        "/Users/sebastianwefers/.gmail-mcp/credentials.json",
        "--token-path",
        "/Users/sebastianwefers/.gmail-mcp/token.json"
      ]
    }
  }
}
  1. Save the file and restart Claude Desktop.

  2. Open Settings β†’ Model Context Protocol β†’ Add Server, then connect to gmail.

Claude will now be able to:

  • πŸ“₯ Read emails
  • βœ‰οΈ Compose drafts
  • 🏷 Send and modify Gmail messages directly from your account.

β€” all directly via your Gmail MCP server.

🧩 Why Deleting token.json Fixes the β€œinvalid_grant” Error

The error occurs because the stored refresh token in token.json is expired or revoked, so Google rejects all refresh attempts. Deleting the file forces the app to start a new OAuth flow, prompting you to log in again and generating a new, valid refresh token β€” which restores access to the Gmail API.

# 1. Remove the invalid cached token
rm /Users/sebastianwefers/Desktop/projects/recruitment-agent-mcp-hackathon-winter25/secrets/gmail-mcp/token.json


# 2. Re-run the Gmail MCP server (which triggers OAuth again)
python -m src.mcp_servers.gmail_mcp

Then, when the script printed a Google sign-in URL, you:

  1. Opened it in your browser,
  2. Logged in to your Google account,
  3. Approved the Gmail API access,
  4. And the new valid token.json was automatically recreated at:
~/.gmail-mcp/token.json