Gmail MCP Server
README.md
# Gmail MCP Server — Complete Setup Guide
A Model Context Protocol (MCP) server that gives Claude full access to any Gmail account: read, search, send, label, and trash emails — no browser, no passwords after initial setup. Tokens refresh automatically forever.
---
## What This Does
Once installed, Claude can:
- Read your inbox
- Search emails (`from:someone`, `subject:invoice`, etc.)
- Send email on your behalf
- Mark emails as read
- Move emails to trash
- List all your Gmail labels/folders
---
## Prerequisites
- Node.js 18+ (install via [nvm](https://github.com/nvm-sh/nvm))
- A Google account (Gmail)
- Claude Code CLI installed
---
## Step 1 — Create a Google Cloud Project
1. Go to [console.cloud.google.com](https://console.cloud.google.com)
2. Click the project dropdown at the top → **New Project**
3. Name it anything (e.g. `my-gmail-mcp`) → **Create**
4. Wait ~30 seconds for it to be created, then select it
---
## Step 2 — Enable the Gmail API
1. In the left menu: **APIs & Services → Library**
2. Search for **Gmail API** → click it → **Enable**
---
## Step 3 — Configure OAuth Consent Screen
1. Go to **APIs & Services → OAuth consent screen** (or search "Auth Platform")
2. Click **Get Started**
3. Fill in:
- **App name**: anything (e.g. `Claude Gmail`)
- **User support email**: your Gmail address
- **Developer contact**: your Gmail address
4. Click through: **Audience → External** → **Create**
5. Under **Data Access**, click **Add or remove scopes** and add:
- `https://www.googleapis.com/auth/gmail.modify`
- `https://www.googleapis.com/auth/gmail.send`
- `https://www.googleapis.com/auth/gmail.readonly`
6. Save
7. Under **Audience**, scroll to **Test users** → **Add users** → enter your Gmail address → Save
> **Why test users?** Google requires your Gmail to be on the test users list while the app is in "Testing" mode. Without it you get "Access blocked." This is free and permanent.
---
## Step 4 — Create OAuth Credentials
1. Go to **APIs & Services → Credentials**
2. Click **+ Create Credentials → OAuth client ID**
3. Application type: **Desktop app**
4. Name: anything → **Create**
5. Click **Download JSON** on the credential that appears
6. Save the file as `credentials.json` in this project folder
The file looks like this (values will be different for you):
```json
{
"installed": {
"client_id": "YOUR_CLIENT_ID.apps.googleusercontent.com",
"client_secret": "YOUR_SECRET",
"project_id": "your-project-id",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"redirect_uris": ["http://localhost"]
}
}
```
---
## Step 5 — Install Dependencies
```bash
npm install
```
---
## Step 6 — Run the OAuth Flow (One Time Only)
```bash
node auth.js
```
This opens a browser, asks you to sign in with Google, shows a permission screen, and when you click Allow it writes `token.json` to your project folder. You never need to do this again — the token auto-refreshes.
> **Save `token.json` somewhere safe.** If you delete it you'll need to run `node auth.js` again.
---
## Step 7 — Register with Claude Code
Run this command (replace the path with where you cloned this repo):
```bash
claude mcp add gmail node /full/path/to/gmail-mcp/index.js
```
Or add it manually to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"gmail": {
"command": "node",
"args": ["/full/path/to/gmail-mcp/index.js"]
}
}
}
```
Then restart Claude Code. Run `claude mcp list` — you should see `gmail: ✔ Connected`.
---
## Step 8 — Test It
In a Claude Code session, ask:
> "Check my Gmail inbox"
Claude will call `gmail_list_emails` and return your recent emails.
---
## Files in This Repo
| File | Purpose |
|------|---------|
| `index.js` | The MCP server — handles all Gmail API calls |
| `package.json` | Node.js dependencies |
| `.gitignore` | Keeps `credentials.json` and `token.json` out of git |
| `auth.js` | One-time OAuth flow to generate `token.json` |
---
## Security
- `credentials.json` — contains your Google OAuth client secret. **Never commit this.**
- `token.json` — contains your access + refresh tokens. **Never commit this.**
- Both are in `.gitignore` by default.
- The tokens only have Gmail access (read/send/modify). They cannot access Drive, Calendar, or anything else.
- If you ever want to revoke access: [myaccount.google.com/permissions](https://myaccount.google.com/permissions) → find your app → Remove Access.
---
## Available MCP Tools
| Tool | What it does |
|------|-------------|
| `gmail_list_emails` | List recent inbox emails. Optional: `limit`, `unreadOnly`, `folder`, `query` |
| `gmail_read_email` | Read full email by `id` |
| `gmail_send_email` | Send email. Required: `to`, `subject`, `body`. Optional: `cc` |
| `gmail_search_emails` | Search with Gmail syntax. Required: `query`. Optional: `limit` |
| `gmail_mark_as_read` | Mark email as read by `id` |
| `gmail_move_to_trash` | Trash email by `id` |
| `gmail_list_folders` | List all Gmail labels |
---
## Troubleshooting
**"Access blocked: App has not completed the Google verification process"**
Your Gmail is not on the test users list. Go to GCP Console → Auth Platform → Audience → Add your Gmail under Test Users.
**"Token has been expired or revoked"**
Delete `token.json` and run `node auth.js` again.
**"credentials.json not found"**
Download your OAuth credentials from GCP Console → Credentials → your OAuth client → Download JSON, save as `credentials.json`.
**"gmail: Failed to connect" in Claude**
Make sure the path in `~/.claude/settings.json` is the absolute path to `index.js`. Run `node /full/path/index.js` manually to see any errors.
**Gmail API quota errors**
The free Gmail API quota is 250 units/second and 1 billion units/day. Normal use never hits this.
---
## How the Auth Flow Works (Technical)
```
You run auth.js
→ Opens browser to Google's OAuth URL
→ You sign in and click Allow
→ Google redirects to http://localhost:3000/callback with ?code=...
→ auth.js exchanges the code for access_token + refresh_token
→ Saves both to token.json
Later, index.js starts:
→ Reads credentials.json (client_id, client_secret)
→ Reads token.json (access_token, refresh_token)
→ Sets credentials on OAuth2 client
→ Listens for "tokens" event — auto-saves new tokens when refreshed
→ Every API call uses userId: "me" — Google resolves this to the authenticated user
```
Access tokens expire after 1 hour. The `googleapis` library automatically uses the refresh token to get a new one. This happens silently in the background.
---
## auth.js — One-Time Setup Script
Save this as `auth.js` in the project folder:
```js
import { google } from "googleapis";
import http from "http";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { exec } from "child_process";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const CREDS_PATH = path.join(__dirname, "credentials.json");
const TOKEN_PATH = path.join(__dirname, "token.json");
const REDIRECT = "http://localhost:3000/callback";
const SCOPES = [
"https://www.googleapis.com/auth/gmail.modify",
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.readonly",
];
const creds = JSON.parse(fs.readFileSync(CREDS_PATH)).installed;
const oauth2 = new google.auth.OAuth2(creds.client_id, creds.client_secret, REDIRECT);
const url = oauth2.generateAuthUrl({ access_type: "offline", scope: SCOPES, prompt: "consent" });
console.log("Opening browser...");
exec(`open "${url}"`); // macOS — use 'xdg-open' on Linux, 'start' on Windows
const server = http.createServer(async (req, res) => {
const code = new URL(req.url, "http://localhost:3000").searchParams.get("code");
res.end("<h1>Done! You can close this tab.</h1>");
server.close();
const { tokens } = await oauth2.getToken(code);
fs.writeFileSync(TOKEN_PATH, JSON.stringify(tokens, null, 2));
console.log("token.json saved. Gmail MCP is ready.");
process.exit(0);
});
server.listen(3000);
```
---
## What "MCP" Means
MCP (Model Context Protocol) is an open standard from Anthropic that lets Claude talk to external services. This server speaks MCP over stdio — Claude Code starts it as a subprocess, calls tools over JSON-RPC, and gets structured responses back. No HTTP server, no ports, no API keys for Claude itself.
---
## License
MIT — use freely, modify freely, no attribution required.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing