Gmail MCP Server
by brentdemark
README.md
# Gmail MCP Server
A self-hostable [Model Context Protocol](https://modelcontextprotocol.io) server that exposes Gmail read and write tools. Connect it to Claude Code or Claude.ai to let Claude manage your email.
## Prerequisites
- Node.js 20+
- A Google Cloud project with Gmail API enabled
- OAuth 2.0 credentials (Desktop app type)
## Setup
### 1. Create Google Cloud Credentials
1. Go to the [Google Cloud Console](https://console.cloud.google.com/)
2. Create a new project (or select an existing one)
3. Enable the **Gmail API**:
- Navigate to **APIs & Services > Library**
- Search for "Gmail API" and click **Enable**
4. Create OAuth credentials:
- Navigate to **APIs & Services > Credentials**
- Click **Create Credentials > OAuth client ID**
- Select **Desktop app** as the application type
- Name it (e.g., "Gmail MCP Server")
- Click **Create**
5. Copy the **Client ID** and **Client Secret**
### 2. Configure Environment
```bash
cd gmail-mcp
cp .env.example .env
```
Edit `.env` and fill in your credentials:
```
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
```
### 3. Install Dependencies
```bash
npm install
```
### 4. Authenticate with Gmail
```bash
npm run auth
```
This opens your browser for Google's OAuth consent screen. After granting access, the refresh token is automatically saved to `.env`.
> **Note:** If you've previously authorized and need to re-authenticate, revoke access at [Google Account Permissions](https://myaccount.google.com/permissions) first, then run `npm run auth` again.
### 5. Start the Server
**For Claude Code (stdio transport):**
```bash
npm start
```
**For Claude.ai (HTTP/SSE transport):**
```bash
npm run start:http
```
## Connecting to Claude Code
Add to your Claude Code MCP config (`~/.claude.json` or project `.mcp.json`):
```json
{
"mcpServers": {
"gmail": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/gmail-mcp/src/index.ts"],
"env": {
"GOOGLE_CLIENT_ID": "your-client-id",
"GOOGLE_CLIENT_SECRET": "your-client-secret",
"GOOGLE_REFRESH_TOKEN": "your-refresh-token"
}
}
}
}
```
Or if you prefer it to read from `.env` automatically, use a wrapper:
```json
{
"mcpServers": {
"gmail": {
"command": "npm",
"args": ["start", "--prefix", "/absolute/path/to/gmail-mcp"]
}
}
}
```
## Connecting to Claude.ai
1. Start the HTTP server: `npm run start:http`
2. The server listens on `http://127.0.0.1:3000` by default (change `PORT` in `.env`)
3. If you need remote access, use a tunnel (e.g., `ngrok http 3000` or Cloudflare Tunnel)
4. In Claude.ai, add the SSE endpoint URL as a custom MCP server: `http://localhost:3000/sse`
## Available Tools
### Read Tools
| Tool | Description |
|------|-------------|
| `search_messages` | Search Gmail using Gmail search syntax. Params: `q` (required), `maxResults`, `pageToken` |
| `read_message` | Read a full message with decoded body. Params: `messageId` |
| `read_thread` | Read all messages in a thread. Params: `threadId` |
| `list_labels` | List all Gmail labels (system + user) with IDs |
| `get_profile` | Get email address and message/thread counts |
### Write Tools (all marked MUTATING)
| Tool | Description |
|------|-------------|
| `label_message` | Add/remove labels on a message. Params: `messageId`, `addLabelIds[]`, `removeLabelIds[]` |
| `label_thread` | Add/remove labels on a thread. Params: `threadId`, `addLabelIds[]`, `removeLabelIds[]` |
| `archive_message` | Archive a message (removes INBOX label). Params: `messageId` |
| `archive_thread` | Archive a thread. Params: `threadId` |
| `trash_message` | Move to Trash (auto-deleted after 30 days). Params: `messageId` |
| `create_label` | Create a new label. Params: `name` |
| `send_message` | Send an email (or reply). Params: `to`, `subject`, `body`, `replyToMessageId?` |
| `create_draft` | Create a draft (or reply draft). Params: `to`, `subject`, `body`, `replyToMessageId?` |
## Gmail Search Syntax Examples
```
from:alice@example.com # Messages from a specific sender
to:bob@example.com # Messages to a specific recipient
subject:meeting # Subject contains "meeting"
has:attachment # Messages with attachments
is:unread # Unread messages
is:starred # Starred messages
label:INBOX # Messages in Inbox
label:Subscriptions # Messages with a user label
after:2025/01/01 # Messages after a date
before:2025/06/01 # Messages before a date
newer_than:7d # Messages from the last 7 days
from:alice subject:project # Combine multiple criteria
```
## Your Labels
System labels: INBOX, SENT, DRAFT, TRASH, SPAM, STARRED, IMPORTANT, CATEGORY_PERSONAL, CATEGORY_SOCIAL, CATEGORY_PROMOTIONS, CATEGORY_UPDATES, CATEGORY_FORUMS
User labels: Subscriptions, My Finance, Receipts, My Travel, Taxes, DFL, Integral Function, PV 2025, Scotland, mini-split, eclips
> **Tip:** Use `list_labels` to get the exact label IDs needed for `label_message` and `label_thread` operations.
## Security Notes
- The refresh token in `.env` grants access to your Gmail. **Never commit `.env` to version control.**
- The HTTP server binds to `127.0.0.1` only (localhost). Use a tunnel for remote access.
- The `gmail.modify` scope is used — this allows reading, labeling, archiving, trashing, and sending, but does **not** allow permanent message deletion.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues