Gmail MCP Server

Gmail MCP Server

Enables AI assistants to read, search, organize, and draft emails in Gmail inboxes with support for multiple accounts, OAuth authentication, and 26 comprehensive tools for email management.

Category
Visit Server

README

Gmail MCP Server

An MCP (Model Context Protocol) server that exposes Gmail tools via Streamable HTTP transport. Enables AI assistants to read, search, organize, and draft emails in your Gmail inbox.

Quickstart

git clone https://github.com/shcallaway/gmail-mcp-server.git
cd gmail-mcp-server

# Generate secrets and create .env
npm run bin:generate-secrets
# Edit .env to add your Google OAuth credentials

# Start the server
npm run docker:up

Server runs at http://localhost:3000. Connect your Gmail at /oauth/start.

Features

  • 26 Gmail tools for comprehensive inbox management
  • Multi-inbox support: Connect multiple Gmail accounts per user
  • Two-layer OAuth: MCP-level JWT authentication + Google OAuth for Gmail access
  • Secure token storage: SQLite with AES-256-GCM encryption for refresh tokens
  • Streamable HTTP transport: Stateless mode for easy deployment
  • Automatic token refresh: Proactive refresh 5 minutes before expiry

Requirements

  • Node.js >= 20.0.0
  • Google Cloud project with Gmail API enabled
  • OAuth 2.0 credentials (Web application type)

Google Cloud Setup

  1. Create a project at console.cloud.google.com

  2. Enable the Gmail API

    • Go to APIs & Services → Library
    • Search for "Gmail API" and enable it
  3. Configure OAuth consent screen

    • Go to APIs & Services → OAuth consent screen
    • Choose "External" user type
    • Fill in app name and support email
    • Add scopes: gmail.readonly, gmail.labels, gmail.modify, gmail.compose
    • Add your email as a test user
  4. Create OAuth credentials

    • Go to APIs & Services → Credentials
    • Click "Create Credentials" → "OAuth client ID"
    • Choose "Web application"
    • Add authorized redirect URI: http://localhost:3000/oauth/callback
    • Copy the Client ID and Client Secret
  5. Add to .env

    GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=your-client-secret
    OAUTH_REDIRECT_URI=http://localhost:3000/oauth/callback
    

Installation

git clone <repository-url>
cd gmail-mcp
npm install
npm run build

Configuration

Copy .env.example to .env and configure:

cp .env.example .env

Required Environment Variables

Variable Description
PORT Server port (default: 3000)
BASE_URL Public URL of the server
GOOGLE_CLIENT_ID Google OAuth client ID
GOOGLE_CLIENT_SECRET Google OAuth client secret
OAUTH_REDIRECT_URI OAuth callback URL (e.g., http://localhost:3000/oauth/callback)
TOKEN_ENCRYPTION_KEY 32-byte key for encrypting stored tokens
JWT_SECRET Secret for signing MCP-level JWTs

Optional Variables

Variable Description
DB_URL SQLite database path (default: ./data/gmail-mcp.db)
ALLOWED_ORIGINS Comma-separated CORS origins

Generating Secrets

# Generate and optionally save to .env
./bin/generate-secrets.sh

# Or use npm
npm run bin:generate-secrets

Running the Server

# Production
npm run build
npm start

# Development (with hot reload)
npm run dev

Docker

The easiest way to deploy anywhere:

npm run docker:up       # Start the server
npm run docker:down     # Stop the server
npm run docker:logs     # Tail logs
npm run docker:restart  # Restart container
npm run docker:build    # Rebuild image

The SQLite database persists in ./data/ via volume mount.

The server exposes:

  • POST /mcp - MCP protocol endpoint
  • GET /healthz - Health check
  • GET /oauth/start - Initiate Gmail OAuth flow
  • GET /oauth/callback - OAuth callback handler
  • GET /.well-known/oauth-protected-resource - OAuth discovery

Available Tools

All tools accept an optional email parameter to target a specific connected account. If omitted, the default account is used.

Authentication & Accounts

Tool Description
gmail.status Check connection status and list connected accounts
gmail.authorize Initiate OAuth flow to connect Gmail
gmail.listAccounts List all connected Gmail accounts
gmail.setDefaultAccount Set which account is used by default
gmail.removeAccount Disconnect a Gmail account

Reading Messages

Tool Description
gmail.searchMessages Search using Gmail query syntax
gmail.getMessage Get a single message by ID
gmail.listThreads List conversation threads
gmail.getThread Get all messages in a thread
gmail.getAttachmentMetadata Get attachment info (filename, size, MIME type)

Labels

Tool Description Scope Required
gmail.listLabels List all labels with counts -
gmail.getLabelInfo Get label details -
gmail.addLabels Add labels to messages/threads gmail.labels
gmail.removeLabels Remove labels from messages/threads gmail.labels
gmail.createLabel Create a custom label gmail.labels

Message Organization

Tool Description Scope Required
gmail.archiveMessages Archive messages/threads (thread-aware by default) gmail.modify
gmail.unarchiveMessages Move back to inbox (thread-aware by default) gmail.modify
gmail.markAsRead Mark as read gmail.labels
gmail.markAsUnread Mark as unread gmail.labels
gmail.starMessages Add star gmail.labels
gmail.unstarMessages Remove star gmail.labels

Thread-Aware Archiving: By default, archiveMessages and unarchiveMessages will archive the entire thread when given a messageId. This ensures conversations leave your inbox. Set archiveEntireThread: false to archive individual messages only.

Drafts

Tool Description Scope Required
gmail.createDraft Create a new draft gmail.compose
gmail.listDrafts List all drafts -
gmail.getDraft Get draft content -
gmail.updateDraft Update existing draft gmail.compose
gmail.deleteDraft Delete a draft gmail.compose

OAuth Scopes

Request scopes when calling gmail.authorize:

Scope Permissions
gmail.readonly Read messages, threads, labels
gmail.labels Manage labels, star, mark read/unread
gmail.modify Archive/unarchive messages and threads
gmail.compose Create, update, and delete drafts

Example:

{
  "scopes": ["gmail.readonly", "gmail.modify", "gmail.compose"]
}

Multi-Inbox Support

Users can connect multiple Gmail accounts. The first connected account becomes the default.

Connecting Additional Accounts

Call gmail.authorize again to connect another Gmail account. Each account can have different scopes.

Targeting Specific Accounts

All tools accept an optional email parameter:

{
  "query": "is:unread",
  "email": "work@example.com"
}

If email is omitted, the default account is used.

Managing Accounts

// List all connected accounts
{ "tool": "gmail.listAccounts" }

// Change default account
{ "tool": "gmail.setDefaultAccount", "email": "work@example.com" }

// Disconnect an account
{ "tool": "gmail.removeAccount", "email": "old@example.com" }

Architecture

MCP Client → Fastify HTTP (/mcp) → MCP Server → Gmail Client → Google APIs
                    ↓
            Token Store (SQLite) ← encrypted credentials

Key Components

  • src/index.ts - Entry point
  • src/config.ts - Zod-validated configuration
  • src/http/server.ts - Fastify HTTP server
  • src/mcp/server.ts - MCP server with all tools
  • src/gmail/client.ts - Gmail API wrapper with token refresh
  • src/auth/mcpOAuth.ts - MCP-level JWT authentication
  • src/auth/googleOAuth.ts - Google OAuth flow with PKCE
  • src/store/sqlite.ts - SQLite token storage with encryption (composite key for multi-account)

Development

# Run tests
npm test

# Run tests with coverage
npm run test:coverage

# Type checking
npm run typecheck

# Linting
npm run lint

# Run single test file
npx vitest run tests/unit/crypto.test.ts

Claude Code Integration

Install MCP Server

Add the Gmail MCP server to your Claude Code configuration:

npm run bin:cc-install-mcp-server

This adds the server to ~/.claude.json. Make sure the server is running first.

Install Subagents

Install custom Claude Code subagents for enhanced Gmail workflows:

npm run bin:cc-install-subagents

This installs 12 specialized Gmail agents that provide intelligent email management capabilities.

Available Subagents

Agent Description Example Prompt
gmail-inbox-explorer Analyzes inbox structure, labels, and activity "Explore my Gmail inbox"
gmail-email-triage Prioritizes unread emails by urgency "Help me triage my inbox"
gmail-email-summarizer Summarizes emails matching search criteria "Summarize emails from John this week"
gmail-draft-composer Helps write professional email drafts "Help me write an email to my boss"
gmail-inbox-cleanup Archives old emails and reduces clutter "Clean up my inbox"
gmail-follow-up-finder Finds emails needing response or follow-up "What emails need follow-up?"
gmail-action-item-extractor Extracts tasks and deadlines from emails "What action items are in my emails?"
gmail-project-email-collector Gathers all emails about a project/topic "Find all emails about the redesign project"
gmail-newsletter-manager Manages newsletter subscriptions "What newsletters am I subscribed to?"
gmail-contact-insights Analyzes communication with a contact "Show my email history with sarah@company.com"
gmail-multi-inbox-dashboard Unified view across multiple accounts "Overview of all my email accounts"
gmail-email-reply-drafter Drafts contextual replies to threads "Help me reply to the project deadline email"

Example Usage

Ask Claude Code naturally and it will automatically use the appropriate agent:

"I have 50 unread emails, what needs my attention first?"
→ Uses gmail-email-triage

"Summarize the email thread about Q4 planning"
→ Uses gmail-email-summarizer

"Help me write a follow-up email to the client"
→ Uses gmail-draft-composer

"What tasks are buried in my recent emails?"
→ Uses gmail-action-item-extractor

Error Handling

The server uses JSON-RPC error codes:

Code Type Description
-32001 NOT_AUTHORIZED User not authenticated, token revoked, or insufficient scope
-32602 INVALID_ARGUMENT Invalid input parameters or account not found
-32000 GMAIL_API_ERROR Gmail API error or rate limit

When invalid_grant is returned from Google (token revoked), stored tokens are cleared and the user must re-authorize.

Security

  • Refresh tokens encrypted with AES-256-GCM before storage
  • MCP-level JWTs (HS256) with 1-hour lifetime
  • Google OAuth with PKCE support
  • CSRF protection via state parameter

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured