Gmail MCP Server
A self-hostable Model Context Protocol 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
- Go to the Google Cloud Console
- Create a new project (or select an existing one)
- Enable the Gmail API:
- Navigate to APIs & Services > Library
- Search for "Gmail API" and click Enable
- 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
- Copy the Client ID and Client Secret
2. Configure Environment
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
npm install
4. Authenticate with Gmail
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 first, then run
npm run authagain.
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):
{
"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:
{
"mcpServers": {
"gmail": {
"command": "npm",
"args": ["start", "--prefix", "/absolute/path/to/gmail-mcp"]
}
}
}
Connecting to Claude.ai
- Start the HTTP server:
npm run start:http - The server listens on
http://127.0.0.1:3000by default (changePORTin.env) - If you need remote access, use a tunnel (e.g.,
ngrok http 3000or Cloudflare Tunnel) - 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_labelsto get the exact label IDs needed forlabel_messageandlabel_threadoperations.
Security Notes
- The refresh token in
.envgrants access to your Gmail. Never commit.envto version control. - The HTTP server binds to
127.0.0.1only (localhost). Use a tunnel for remote access. - The
gmail.modifyscope is used — this allows reading, labeling, archiving, trashing, and sending, but does not allow permanent message deletion.











