Skip to content

Latest commit

 

History

History
169 lines (130 loc) · 4.39 KB

File metadata and controls

169 lines (130 loc) · 4.39 KB

MCP Gmail Server

A Python MCP server that gives AI assistants (Cursor, Claude Desktop, etc.) read-only access to Gmail: list labels, list messages, and fetch full message content. No send, delete, or modify operations.

Tools

Tool Description
gmail_list_labels List all Gmail labels (INBOX, SENT, DRAFT, TRASH, SPAM, UNREAD, STARRED, custom labels, …)
gmail_list_messages List message IDs filtered by labels, search query, and pagination
gmail_get_message Fetch a single message by ID — full headers, plain text, and HTML body

gmail_list_messages parameters

Parameter Type Default Description
label_ids list[str] all mail Filter by label IDs, e.g. ["INBOX"], ["SENT"]. Use gmail_list_labels to get IDs.
query str Gmail search query, e.g. from:user@example.com, is:unread, newer_than:7d. Syntax reference
max_results int 50 Max messages to return (1–500)
page_token str Page token from a previous call for pagination

Quick Start

1. Prerequisites

  • Python 3.10+
  • uv (recommended) or pip

2. Install

cd mcp-gmail
uv sync

3. Configure

cp .env.example .env
# Edit .env: set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET

4. Enable Gmail API & OAuth

  1. Go to Google Cloud ConsoleAPIs & ServicesLibrary.
  2. Search for Gmail API and click Enable.
  3. Go to CredentialsCreate CredentialsOAuth 2.0 Client ID.
  4. Choose Desktop app as the application type; give it a name.
  5. Copy client_id and client_secret into .env.
GOOGLE_CLIENT_ID=1234567890-abc.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-...
GMAIL_TOKEN_FILE=tokens/gmail_token.json

Scope used: https://www.googleapis.com/auth/gmail.readonly (read-only; no send/modify/delete).

On first run the server opens a browser tab for you to sign in. The token is saved to tokens/gmail_token.json (or GMAIL_TOKEN_FILE) and refreshed automatically.

Tip: You can reuse the same Google Cloud OAuth client as MCP Calendar. Just keep a separate GMAIL_TOKEN_FILE so the Gmail token is scoped only to gmail.readonly.

5. Run

uv run mcp run src/mcp_gmail/server.py

Or via the installed entry point:

uv run mcp-gmail

Connecting to Cursor

Add to your Cursor MCP config (via Cursor → Settings → MCP):

{
  "mcpServers": {
    "mcp-gmail": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "C:/Users/Ryzen/Projects/mcp-servers/mcp-gmail",
        "mcp",
        "run",
        "src/mcp_gmail/server.py"
      ],
      "env": {}
    }
  }
}

Or using the installed entry point:

{
  "mcpServers": {
    "mcp-gmail": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "C:/Users/Ryzen/Projects/mcp-servers/mcp-gmail",
        "mcp-gmail"
      ]
    }
  }
}

Connecting to Claude Desktop

Edit %APPDATA%\Claude\claude_desktop_config.json (Windows) or ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):

{
  "mcpServers": {
    "mcp-gmail": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "C:/Users/Ryzen/Projects/mcp-servers/mcp-gmail",
        "mcp",
        "run",
        "src/mcp_gmail/server.py"
      ]
    }
  }
}

Project Structure

mcp-gmail/
├── pyproject.toml
├── .env.example
├── .gitignore
├── tokens/                    # OAuth token cache (gitignored)
└── src/
    └── mcp_gmail/
        ├── server.py          # FastMCP entry point — 3 read-only tools
        ├── config.py          # Loads .env, builds Gmail client
        ├── models.py          # GmailLabel, GmailMessageRef, GmailMessage
        └── providers/
            └── gmail.py       # Gmail API (read-only)

Security

  • Never commit .env or the tokens/ directory (both are in .gitignore).
  • This server only requests gmail.readonly — it cannot send, delete, or modify mail.
  • The OAuth token is stored locally in tokens/ and refreshed automatically.