โ† All articles
Dev Jain

Gmail MCP Server: How to Connect AI Agents to Gmail and Automate Email Tasks

Learn how a Gmail MCP server connects AI agents to Gmail, how to build and configure one with Python and OAuth, and how to automate common email tasks.

A Gmail MCP server is what lets an AI agent search, read, draft, and send email through your Gmail account instead of just talking about it. Rather than wiring a one off integration into a single chatbot, an MCP server exposes Gmail as a small set of standardized tools that any MCP compatible client, including Claude Code, Claude Desktop, and Cursor, can discover and call. This guide covers what a Gmail MCP server actually is, the different ways to connect one, and how to build your own in Python from a blank file to a working server your agent can call.

What Is an MCP Server?

An MCP server is a program that exposes tools, data, and prompts to an AI application using the Model Context Protocol, a standardized JSON-RPC contract that lets an AI client discover what a service can do and call it directly. Instead of an AI model guessing at an API's shape or a developer hardcoding one integration per app, the client asks the server what tools exist, reads their descriptions, and calls the right one when a task needs it.

Think of it as a translation layer. On one side sits your AI client, Claude Code for example. On the other sits an external system, in this case Gmail. The MCP server sits in the middle, holding the credentials, defining the available actions, and turning a tool call into an actual API request. For a broader walkthrough of how this pattern applies across GitHub, Slack, and Notion as well as Gmail, the complete guide to MCP servers covers the underlying protocol in more depth.

What Is a Gmail MCP Server, and What Is It Used For?

A Gmail MCP server is an MCP server that exposes Gmail specific tools, things like searching messages, reading a thread, sending a reply, or creating a draft, so an AI agent can act on a Gmail inbox instead of only describing what it would do. It authenticates once with Google using OAuth, then handles every subsequent Gmail request on the agent's behalf.

It gets used anywhere an agent needs to touch email as part of a larger task, not just answer questions about it. That includes:

  • Searching an inbox for messages matching a query, a sender, or a label
  • Reading the full content of a specific email or thread
  • Drafting or sending a reply without a human copying text between windows
  • Creating labels or moving messages as part of an inbox organization workflow
  • Pulling structured details out of email, like an invoice amount or a meeting time, for use somewhere else

The keyword variants people search for, gmail mcp, gmail mcp server, and mcp server gmail, all point at the same underlying thing: a bridge that turns Gmail into something an AI agent can operate directly rather than something a human has to relay information from.

How a Gmail MCP Server Enables AI Agents to Interact With Your Gmail Account

A Gmail MCP server enables this interaction by exposing a fixed set of callable tools, each backed by a real Gmail API request, and by holding the OAuth credentials so the AI client never needs direct access to your Google account.

The flow looks like this in practice: you send a prompt like "find yesterday's email from the design team and summarize it." Your AI client recognizes this as a Gmail task and calls a tool such as search_emails with a query string. The MCP server receives that call, translates it into an actual Gmail API request, authenticates using a stored OAuth token, and sends the request to Google. Gmail returns the matching messages, the server formats that response, and the client reads it back to you or acts on it, all within the same reasoning step.

A few things make this reliable rather than fragile:

  • Tools are typed and described, so the AI client knows exactly what arguments each one expects and what it returns
  • Credentials live only on the server, never inside the AI client itself
  • Each tool call maps to one specific action, which keeps the agent from improvising requests Gmail's API was never designed to handle

This is also what separates an MCP server for Gmail from calling the Gmail API directly inside your own application code. The protocol layer means the same server works with any MCP compatible client without rewriting the integration for each one.

Different Options for Connecting AI Agents to Gmail

There are four practical paths to connecting an AI agent to Gmail today, and the right one depends mostly on how much control you need versus how much maintenance you want to take on.

  1. Google's official Workspace MCP server for Gmail. Google now ships a first party Gmail MCP endpoint as part of its Workspace MCP rollout. It runs as a remote server you add as a custom connector, so there is no code to host or credentials file to manage yourself, though the available tools and documentation are still comparatively limited next to community options.
  2. Community built Gmail MCP servers. Several open source Gmail MCP servers exist on GitHub and npm, typically covering search, send, drafts, labels, and attachments. They run locally over stdio, give you full visibility into the code touching your OAuth tokens, and are a fast way to get started without writing a server yourself.
  3. A custom Gmail MCP server you build. Writing your own server gives you full control over exactly which tools exist, how errors are handled, and how the OAuth flow fits into your own infrastructure. It takes more upfront work than the first two options, and it is what the rest of this guide walks through.
  4. A hosted integration layer. If Gmail is one of several apps your agent needs, running a separate MCP server per app gets repetitive fast. Platforms like Corsair handle OAuth, token storage, and multi tenant credential isolation across Gmail alongside Slack, GitHub, Notion, and dozens of other services through one standardized interface. If you are weighing a hosted layer against a self managed MCP setup, Corsair vs Composio compares two approaches to that decision in more detail.

None of these four are mutually exclusive forever. Many teams start with a custom or community server to learn how the pieces fit together, then move to a hosted layer once they are managing Gmail plus five other integrations at once.

Setting Up a Custom Gmail MCP Server

The rest of this guide builds a working Gmail MCP server in Python, from Google Cloud setup through connecting it to an AI client. The server below implements four tools: searching messages, reading a message body, sending an email, and creating a draft, which covers the core of what most AI agents need from Gmail.

Configure Google OAuth Credentials and Gmail API Access

Before writing any server code, you need a Google Cloud project with the Gmail API enabled and OAuth credentials to authenticate against it.

  1. Go to console.cloud.google.com and create a new project, or select an existing one dedicated to this integration.
  2. Open APIs & Services, then Library, search for "Gmail API," and click Enable.
  3. Open APIs & Services, then OAuth consent screen. Choose External as the user type, fill in an app name, support email, and developer contact email. While your project is in Testing mode, add your own Google account under Test Users.
  4. Open APIs & Services, then Credentials. Click Create Credentials, then OAuth client ID, and choose Desktop app as the application type. Download the resulting JSON file and save it as credentials.json in your project folder.

Scope selection matters more here than it might seem. Gmail's API groups permissions into scopes like gmail.readonly, gmail.send, gmail.modify, and gmail.compose, and Google classifies the more powerful ones as restricted, which triggers a verification review before your app can be used outside a small group of test users. For a server you are running for yourself or a small team, Testing mode with your own account added as a test user is enough to get started without going through that review. A typical set for the tools built below looks like this:

SCOPES = [

"https://www.googleapis.com/auth/gmail.readonly",

"https://www.googleapis.com/auth/gmail.send",

"https://www.googleapis.com/auth/gmail.modify",

]

Request only what the tools you are building actually need. If your agent only ever reads mail, drop gmail.send and gmail.modify entirely. For a deeper look at choosing scopes under the principle of least privilege across Gmail, Drive, and Calendar, see Google API scopes for AI agents. If you want the fuller picture of what production grade Gmail OAuth involves, including token refresh and multi user scaling, this practical OAuth walkthrough covers that ground in detail. The setup here stays focused on what an MCP server specifically needs.

Build a Gmail MCP Server in Python

Install the packages the server depends on:

pip install fastmcp google-auth google-auth-oauthlib google-api-python-client

Then create gmail_mcp_server.py with the following:

import base64

import os

from email.mime.text import MIMEText

from fastmcp import FastMCP

from google.auth.transport.requests import Request

from google.oauth2.credentials import Credentials

from google_auth_oauthlib.flow import InstalledAppFlow

from googleapiclient.discovery import build

SCOPES = [

"https://www.googleapis.com/auth/gmail.readonly",

"https://www.googleapis.com/auth/gmail.send",

"https://www.googleapis.com/auth/gmail.modify",

]

TOKEN_PATH = "token.json"

CREDENTIALS_PATH = "credentials.json"

def get_gmail_service():

creds = None

if os.path.exists(TOKEN_PATH):

creds = Credentials.from_authorized_user_file(TOKEN_PATH, SCOPES)

if not creds or not creds.valid:

if creds and creds.expired and creds.refresh_token:

creds.refresh(Request())

else:

flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_PATH, SCOPES)

creds = flow.run_local_server(port=0)

with open(TOKEN_PATH, "w") as token_file:

token_file.write(creds.to_json())

return build("gmail", "v1", credentials=creds)

mcp = FastMCP("gmail-mcp")

@mcp.tool()

def search_emails(query: str, max_results: int = 10) -> list[dict]:

"""Search Gmail using Gmail query syntax, such as from:someone@example.com or is:unread."""

service = get_gmail_service()

results = service.users().messages().list(

userId="me", q=query, maxResults=max_results

).execute()

summaries = []

for msg in results.get("messages", []):

detail = service.users().messages().get(

userId="me", id=msg["id"], format="metadata",

metadataHeaders=["From", "Subject", "Date"],

).execute()

headers = {h["name"]: h["value"] for h in detail["payload"]["headers"]}

summaries.append({

"id": msg["id"],

"from": headers.get("From"),

"subject": headers.get("Subject"),

"date": headers.get("Date"),

"snippet": detail.get("snippet"),

})

return summaries

@mcp.tool()

def read_email(message_id: str) -> str:

"""Retrieve the plain text body of a single email by its message ID."""

service = get_gmail_service()

message = service.users().messages().get(

userId="me", id=message_id, format="full"

).execute()

parts = message["payload"].get("parts", [message["payload"]])

for part in parts:

if part.get("mimeType") == "text/plain":

return base64.urlsafe_b64decode(part["body"]["data"]).decode("utf-8")

return message.get("snippet", "")

@mcp.tool()

def send_email(to: str, subject: str, body: str) -> str:

"""Send an email from the authenticated Gmail account."""

service = get_gmail_service()

message = MIMEText(body)

message["to"] = to

message["subject"] = subject

encoded = base64.urlsafe_b64encode(message.as_bytes()).decode()

sent = service.users().messages().send(

userId="me", body={"raw": encoded}

).execute()

return f"Email sent, message id {sent['id']}"

@mcp.tool()

def create_draft(to: str, subject: str, body: str) -> str:

"""Create a draft email without sending it."""

service = get_gmail_service()

message = MIMEText(body)

message["to"] = to

message["subject"] = subject

encoded = base64.urlsafe_b64encode(message.as_bytes()).decode()

draft = service.users().drafts().create(

userId="me", body={"message": {"raw": encoded}}

).execute()

return f"Draft created, draft id {draft['id']}"

if __name__ == "__main__":

mcp.run()

A few points on how this fits together: each function decorated with @mcp.tool() becomes a tool your AI client can discover automatically, and its docstring is what the model reads to decide when that tool is the right one to call, so write those descriptions as precisely as you would document a public API. The get_gmail_service function handles the OAuth exchange the first time it runs, then reuses the stored token.json on every call after that, so the browser consent screen only appears once. Calling mcp.run() at the bottom starts the server over stdio by default, which is the transport local clients like Claude Code and Claude Desktop expect.

Connect the MCP Server to Your AI Client

With gmail_mcp_server.py, credentials.json, and your dependencies in place, the last step is registering the server with your AI client.

For Claude Code, run this from your project directory:

claude mcp add gmail-mcp -- python3 gmail_mcp_server.py

This is the same claude code gmail mcp setup pattern used for any local Python server: the command after -- is what Claude Code launches as a subprocess, and it communicates with your script over stdin and stdout. If you prefer to edit configuration directly instead, add the equivalent entry to .mcp.json in your project or ~/.claude.json for a global setup:

{

"mcpServers": {

"gmail-mcp": {

"command": "python3",

"args": ["gmail_mcp_server.py"]

}

}

}

The same command and args pattern works for Claude Desktop as well, added to claude_desktop_config.json, and for any other MCP compatible client that supports stdio servers.

Restart your client after adding the server, then send a test prompt such as "search my inbox for unread emails from the last three days and summarize them." The first tool call will open a browser window for the Google OAuth consent screen. Approve it, and the server stores a refresh token locally so you will not need to reauthorize on future runs, unless your Google Cloud project is still in Testing mode, in which case tokens expire after seven days until you move the consent screen to Production.

Email Tasks You Can Automate With AI Agents

Once a Gmail MCP server is connected, the practical value shows up in the tasks it removes from your day rather than in the setup itself. Some of the most common ones:

  • Inbox triage: have the agent scan unread messages, group them by sender or topic, and flag anything that looks time sensitive
  • Drafting replies: point the agent at a thread and ask it to draft a response in a specific tone, ready for you to review before it sends
  • Summarizing long threads: turn a fifteen message back and forth into a three line summary before a meeting
  • Extracting structured data: pull a total, a due date, or a tracking number out of an email and hand it to another tool or spreadsheet
  • Following up automatically: search for threads with no reply after a set number of days and draft a follow up message
  • Label based organization: apply labels or archive messages that match a recurring pattern, like receipts or newsletters
  • Meeting coordination: read a scheduling email and draft a reply proposing times, or hand the details off to a calendar tool
  • Daily or weekly digests: search for messages matching a set of criteria each morning and generate a short briefing instead of you opening the inbox first

Every one of these maps directly to the tools built above: search_emails and read_email cover triage, summarizing, and extraction, while send_email and create_draft cover replies and follow ups. Chaining them together in a single prompt, search a thread, read it, draft a reply, is what makes the difference between a chatbot that talks about your inbox and an agent that actually clears it.

Building a Gmail MCP server from scratch is a good way to see exactly how MCP tool calls, OAuth tokens, and Gmail API requests fit together, and the server above is enough to run in production for a single account. Once your agent needs more than Gmail though, the same OAuth and credential problems repeat for every new app you connect. Corsair handles that layer for you, giving Gmail, Slack, GitHub, Notion, and dozens of other services a single standardized integration surface with OAuth, permissions, and MCP already wired up, so your team can spend time on what the agent does rather than the plumbing underneath it.

Frequently Asked Questions

What is a Gmail MCP server, and how is it different from using the Gmail API directly?
A Gmail MCP server sits between an AI client and the Gmail API, exposing a fixed set of typed tools like search or send instead of the full API surface. Calling the Gmail API directly means writing custom integration code for every AI framework you use, while an MCP server exposes the same tools to any MCP compatible client without rewriting anything.

Can I connect a Gmail MCP server to Claude Code specifically?
Yes. Claude Code supports local stdio MCP servers through the claude mcp add command, which is exactly how the Python server in this guide gets registered. The same server also works with Claude Desktop and other MCP compatible clients using the same command and arguments in their respective configuration files.

Is it safe to let an AI agent send email through Gmail?
It can be, as long as scopes and review steps match the risk. Requesting only the scopes your tools actually use, reviewing drafts before allowing automatic sends, and starting with read only tools before adding send access are the main ways teams reduce the risk of an agent sending something unintended.

Do I need to build my own Gmail MCP server, or can I use an existing one?
Not necessarily. Google's official Workspace MCP server and several community built Gmail MCP servers already cover common tools like search, send, and label management. Building your own makes sense when you need custom tool logic, tighter control over what the agent can do, or want to understand the underlying mechanics before adopting a hosted option.

Which Gmail API scopes should a Gmail MCP server request?
Request the narrowest scope each tool needs: gmail.readonly for search and read tools, gmail.send for sending, and gmail.modify only if the server needs to manage labels or move messages. Combining gmail.readonly with any write scope pushes the whole app into Google's restricted classification, so requesting less up front keeps verification simpler if you later publish the app beyond a small test group.