| # ***`Gmail MCP β GCP Setup (Terraform + Bash)`*** | |
| This folder provisions the minimum GCP infrastructure to run the [Gmail MCP server](https://github.com/theposch/gmail-mcp/tree/main) 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`: | |
| ```python | |
| 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** | |
| ```bash | |
| chmod +x scripts/gcp_setup.sh | |
| ./scripts/gcp_setup.sh | |
| ``` | |
| 2. **Apply Terraform with smart defaults + auto-import** | |
| ```bash | |
| 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: | |
| ```bash | |
| 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: | |
| ```bash | |
| terraform apply \ | |
| -var="project_id=my-mcp-project" \ | |
| -var="project_name=My MCP Project" \ | |
| -var="user_email=you@example.com" | |
| ``` | |
| Or via env vars: | |
| ```bash | |
| 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: | |
| ```text | |
| 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: | |
| ```bash | |
| mkdir -p ~/.gmail-mcp | |
| mv ~/Downloads/client_secret_*.json ~/.gmail-mcp/credentials.json | |
| ``` | |
| ### β οΈ ***Important: Two Different JSONs*** | |
| - The file from: | |
| ```bash | |
| 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: | |
| ```bash | |
| uv --version | |
| ``` | |
| If not, install it: | |
| ```bash | |
| 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. | |
| ```bash | |
| 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: | |
| ```bash | |
| 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. | |
| ```bash | |
| 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: | |
| ```bash | |
| 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: | |
| ```bash | |
| ~/.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: | |
| ```bash | |
| nano ~/Library/Application Support/Claude/claude_desktop_config.json | |
| ``` | |
| 2. Add this block (update paths if necessary): | |
| ```json | |
| { | |
| "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" | |
| ] | |
| } | |
| } | |
| } | |
| ``` | |
| 3. Save the file and restart Claude Desktop. | |
| 4. 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. | |
| ```bash | |
| # 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: | |
| ```bash | |
| ~/.gmail-mcp/token.json | |
| ``` |