Announcing CIMD support for MCP Client registration
Learn more

Gmail MCP Server: Connect Claude to Gmail, MCP vs API (2026)

Diagram: Claude, Claude Code and Cursor connect to Google's Gmail MCP server, while a product's agent reaches the Gmail API per user through Scalekit

To connect Claude to Gmail via MCP, use Google's official remote Gmail MCP server at https://gmailmcp.googleapis.com/mcp/v1, or Anthropic's own Gmail connector inside Claude. Google's server is in Developer Preview, uses Streamable HTTP and signs each user in with OAuth 2.0, so the agent acts as that user. It can search, read, label, trash and draft mail, but it cannot send. Sending, sync and push notifications stay on the Gmail API.

A product whose agent works in many customers' inboxes needs per-user OAuth, token storage and an audit trail, the problem behind most MCP integrations. For the general difference, see MCP vs API.

TL;DR

  • You enable Google's Gmail MCP server in your own Google Cloud project, add the gmail.readonly and gmail.compose scopes, create an OAuth client, and add the server to Claude, Claude Code, Cursor or Codex with that client.
  • The server has no send tool. create_draft puts a draft in the user's Drafts folder to review and send from Gmail. Sending, attachment downloads, settings, history sync and push through users.watch are on the Gmail REST API only.
  • Both paths use restricted Gmail scopes, so a public app needs Google's restricted-scope verification and, if it handles the data on its own servers, a CASA security assessment. For a product serving many users, Scalekit AgentKit's Gmail connector runs each user's OAuth flow, stores and refreshes the tokens, and serves Gmail tools, send included, from one MCP server URL.

What Gmail MCP and Gmail API actually are

The Gmail MCP server

Google's Gmail MCP server is a remote server that Google hosts at https://gmailmcp.googleapis.com/mcp/v1. It is one of the Google Workspace MCP servers: Drive, Docs, Sheets, Slides, Calendar, Chat, People and Classroom each have their own. Google opened the Workspace MCP server to public developer preview on May 1, 2026, and the setup guide lists membership in the Google Workspace Developer Preview Program as a prerequisite.

Setup happens in a Google Cloud project you own. You enable the Gmail API (gmail.googleapis.com) and the Gmail MCP API (gmailmcp.googleapis.com), configure the OAuth consent screen with the gmail.readonly and gmail.compose scopes, and create an OAuth client of type Web application with Use this client for an AI-powered agent selected. Google's troubleshooting checks that setting first.

Google's tool reference documents search, thread and message reads, drafts and labels. The server's own tools/list response, which answers without sign-in, returned 23 tools in October 2026, adding get_draft, trash_thread, trash_message and spam tools. None of them sends mail. Read tools/list from your client for the current list.

The Gmail REST API

The Gmail REST API at gmail.googleapis.com/gmail/v1 exposes the full mailbox: messages, drafts, threads, labels, history, attachments, and settings such as filters, forwarding, send-as aliases, vacation responders and delegates. It also offers users.watch for push notifications through Cloud Pub/Sub.

It accepts OAuth 2.0 tokens from a user's consent, or from a service account with domain-wide delegation in a Workspace organization.

How to connect Claude to Gmail via MCP

Every client below needs the Google Cloud project, consent screen and an OAuth client. Google does not support dynamic client registration, so each client needs your client ID and secret, and Google requires an exact match on the redirect URI you register.

Claude.ai and Claude Desktop

Google's server goes in as a custom connector. On Team and Enterprise plans, an Owner adds it under Organization settings > Connectors, and members then connect to it.

  1. In Google Auth Platform > Clients, create a Web application client, add https://claude.ai/api/mcp/auth_callback as an authorized redirect URI, select Use this client for an AI-powered agent, and copy the client ID and secret.
  2. In Claude, go to Customize > Connectors, click + Add, then Add custom connector.
  3. Name it Gmail, enter https://gmailmcp.googleapis.com/mcp/v1 as the remote MCP server URL and click Continue. Under OAuth client, choose Use your own OAuth client, enter the client ID and secret, and click Add.

Claude also has its own Gmail connector, under Customize > Connectors, where each user signs in with Google. It can send, reply and forward, and by default asks for approval before each of those actions. Google's server is the better fit when your organization wants its own OAuth client and scopes in its own Google Cloud project.

Claude Code

Register http://localhost:8080/callback as a redirect URI on a Web application client. Then add the server with the two Gmail scopes pinned, using the pre-configured credentials options:

claude mcp add-json gmail '{ "type": "http", "url": "https://gmailmcp.googleapis.com/mcp/v1", "oauth": { "clientId": "YOUR_CLIENT_ID", "callbackPort": 8080, "scopes": "https://www.googleapis.com/auth/gmail.readonly https://www.googleapis.com/auth/gmail.compose" } }' --client-secret

Claude Code prompts for the secret and keeps it out of your config. Run /mcp, select gmail and sign in. The server's metadata advertises wider scopes, including gmail.modify, gmail.send and https://mail.google.com/, and oauth.scopes makes Claude Code request only the two that Google's setup lists.

If you have connected Anthropic's Gmail connector on claude.ai, it appears in Claude Code automatically when you sign in with a claude.ai subscription. For sign-in loops, scope errors and 401s in the CLI, see Claude Code MCP OAuth.

Cursor

Register http://localhost:8787/callback for the desktop app and, if people sign in from the web or Cursor Agents, https://www.cursor.com/agents/mcp/oauth/callback. Then add the server to ~/.cursor/mcp.json or a project's .cursor/mcp.json with static OAuth credentials, read from environment variables:

{ "mcpServers": { "gmail": { "url": "https://gmailmcp.googleapis.com/mcp/v1", "auth": { "CLIENT_ID": "${env:GMAIL_MCP_CLIENT_ID}", "CLIENT_SECRET": "${env:GMAIL_MCP_CLIENT_SECRET}", "scopes": [ "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.compose" ] } } } }

Codex

Codex takes a pre-registered client. Google matches the redirect URI exactly, port included, so first give Codex a fixed callback in ~/.codex/config.toml:

mcp_oauth_callback_url = "http://localhost:8765/callback" mcp_oauth_callback_port = 8765

Register that URL on your Web application client, then add the server and sign in:

codex mcp add gmail --url https://gmailmcp.googleapis.com/mcp/v1 \ --oauth-client-id "$GMAIL_MCP_CLIENT_ID" \ --oauth-client-secret "$GMAIL_MCP_CLIENT_SECRET" codex mcp login gmail

Check that codex mcp add prints the callback URL you registered. Codex stores the secret in config.toml, so keep it private. Codex prefers the scopes a server advertises, and Gmail's list includes https://mail.google.com/, so read the consent screen before you approve.

Google's guide also covers Antigravity, through ~/.gemini/config/mcp_config.json. Any other client needs the server URL, Streamable HTTP as the transport, and OAuth 2.0 with your client.

Comparing them where it matters for agents

What your agent can actually do

The MCP server reads, organizes and drafts. The API owns everything that sends mail or runs without a person in the loop.

Capability
Gmail MCP server (preview)
Gmail REST API
Search threads
Yes: search_threads
Yes: users.threads.list
Read a thread or message
Yes: get_thread, get_message
Yes: users.threads.get, users.messages.get
Create a draft
Yes: create_draft
Yes: users.drafts.create
List and read drafts
Yes: list_drafts, get_draft
Yes: users.drafts.list, users.drafts.get
Send a message or a draft
No
Yes: users.messages.send, users.drafts.send
List, create and apply labels
Yes: list_labels, create_label, label_thread, label_message
Yes: users.labels.*, users.messages.modify
Move to Trash
Yes: trash_thread, trash_message
Yes: users.messages.trash, users.threads.trash
Delete permanently
No
Yes: users.messages.delete, needs the https://mail.google.com/ scope
Attachments
Metadata only: get_message
Yes: users.messages.attachments.get
Incremental sync
No
Yes: users.history.list
Push on mailbox change
No
Yes: users.watch via Pub/Sub
Settings (filters, forwarding, send-as, delegates)
No
Yes: users.settings.*

The draft-only ceiling

In Google's own example, the client uses create_draft to put a message in the user's Drafts folder so they can review and send it from Gmail. An agent that must send a follow-up or an autonomous reply needs users.messages.send or users.drafts.send on the REST API. For an interactive assistant that is a sensible default, since a person sees every message first.

The auth path each one puts you on

MCP: OAuth per user

Each user signs in through a browser and grants the scopes, and the agent inherits what that user can see and do. Google's setup covers one sign-in model: user OAuth through a client you create.

The headless gap

Access tokens last about an hour, so a client needs a refresh token, which Google issues only for requests with access_type=offline. After the first consent, a process holding that refresh token can keep working without the user present, so a headless job such as a scheduled digest needs one interactive sign-in per user first. What MCP does not give you is a way to act for users who never signed in.

REST API: per-user or domain-wide

The authorization code flow is per-user consent, the same identity model as MCP. A service account with domain-wide delegation lets a Google Workspace administrator authorize one client to act as users in the organization without prompts. It does not apply to consumer @gmail.com accounts, and because it reaches every user's data, Google recommends reviewing those service accounts regularly.

Verification applies to both paths

gmail.readonly and gmail.compose are restricted scopes whichever path requests them. A public app that requests them needs restricted-scope verification, and an app that accesses the data from or through a third-party server also needs a security assessment by a Google-approved assessor under the CASA framework, repeated at least every 12 months. Apps used only inside your own Workspace organization with an Internal consent screen are exempt, and Google's setup guide has you pick Internal when you can.

What each path cannot do

The MCP server is preview software, so its tools can change. The API has no LLM-ready tool schemas: you build requests, parse MIME messages, handle pagination and map errors yourself. The MCP server returns tool definitions with input and output schemas and read-only hints a client can use directly, which is faster for an interactive assistant.

Quotas and cost

Gmail API usage limits for projects created on or after May 1, 2026 are 1,200,000 quota units per minute per project and 6,000 per minute per user per project. Usage under 80,000,000 units per day per project is not billed. messages.send and drafts.send cost 100 units each, against 5 for messages.list, and a message can have at most 500 recipients. The MCP server has its own quota, counted in query cost: 1,200,000 per minute per project and 6,000 per minute per user per project, with get_thread at 40 and search_threads at 10. Google applies the same tiering model to Workspace APIs and the MCP servers.

What you own in production

On the MCP path

Google hosts the server and maintains the tool schemas. You own the Google Cloud project, OAuth client, scopes and verification, plus token storage if your software holds the tokens. Indirect prompt injection is the main risk: Google warns that untrusted email can carry hidden instructions and requires you to screen prompts and responses, with its Model Armor service or your own documented solution.

On the REST API path

You own requests, MIME handling, retries, pagination, the token lifecycle and push infrastructure. A users.watch registration must be renewed at least every 7 days, and Google recommends once a day. Each watched user gets at most one notification per second; Google drops the rest.

When to use MCP, when to use the API

Use the Gmail MCP server when

  • Your agent is interactive and a user is present to consent.
  • The job is to search, read, summarize, label and draft for human review.
  • The users are you or your own Workspace organization, so an Internal consent screen avoids verification.

Use the Gmail REST API when

  • Your agent must send mail, delete messages, or manage filters, forwarding and other settings.
  • You need incremental sync through users.history.list or real-time reaction through users.watch and Pub/Sub.
  • You serve a Workspace organization through domain-wide delegation, or run jobs for users who will never open a consent screen.

Official, self-hosted or managed

Option
What it is
Better fit when
Google's Gmail MCP server
Hosted by Google, Developer Preview, user OAuth through your own client; reads, labels, trashes and drafts
One person or one team works in Claude, Claude Code, Cursor or Antigravity and drafts are enough
Anthropic's Gmail connector
Built into Claude; each user signs in with Google; searches and drafts mail, and sends, replies and forwards after approval by default
You need Gmail inside Claude only and do not want to run a Google Cloud project
workspace-mcp (open source)
taylorwilsdon/google_workspace_mcp, MIT licensed, self-hosted, calls Google's REST APIs; Gmail tools include send, attachments and filters; OAuth 2.1 multi-user mode
You want sending and filters in a desktop client and can run, secure and update the server yourself
Composio
Hosted Gmail MCP server with a managed Google OAuth app, so users sign in without your own Google app
You want to start without registering a Google OAuth app
Scalekit AgentKit
MCP gateway over the Gmail REST API with your own Google OAuth app; per-user tokens; one Virtual MCP server URL plus a session token per user
Your product's agent acts in many users' inboxes, including sending, with your brand on the consent screen

The credential problem that exists on both paths

Both paths leave you storing tokens

Whether the token comes from the MCP OAuth flow or a direct API grant, it has to live somewhere: encrypted at rest, isolated per tenant, and revocable when a user disconnects. Google refresh tokens stop working when the user revokes access, changes their password, or leaves the token unused for six months. Google also allows 100 refresh tokens per Google Account per OAuth client ID, and a new one beyond that silently invalidates the oldest.

The N-credential reality

In a multi-tenant agent, fifty customers mean fifty OAuth grants, fifty refresh lifecycles and fifty revocation paths, and a tool call must never pick up the wrong one. Per-user OAuth for MCP integrations covers this design and its failure modes.

Building Gmail agents with Scalekit

AgentKit is an MCP gateway that runs each user's OAuth flow, stores their tokens encrypted with AES-256-GCM under a key per environment, refreshes them and calls tools as that user. Its Gmail connector lists 48 tools: 21 read, 19 write and 8 destructive, including gmail_send_message, gmail_send_draft, gmail_list_history and gmail_watch_mailbox. It uses your own Google OAuth app: paste the Gmail connection's redirect URI into a Web application client in Google Cloud, then enter the client ID, secret and scopes on the connection. The consent screen shows your app.

You create a Virtual MCP server once per agent role, and all users share its URL. Before each run, your back end mints a session token for one user. Scalekit checks the token, finds that user's Gmail account and calls Gmail with it, so your agent never receives a Gmail token.

Once per agent role: create the server.

import os from scalekit import ScalekitClient from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping actions = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ).actions server = actions.mcp.create_config( name="gmail-inbox-assistant", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="gmail", # your Gmail connection tools=[ "gmail_list_threads", "gmail_get_thread_by_id", "gmail_create_draft", "gmail_send_draft", ], ) ], ).config print(server.id, server.mcp_server_url)

Before each run: check the user's account, then mint a token. If the account is not active, send the user the authorization link.

from datetime import timedelta user_id = "user_123" # your app's stable ID for this user accounts = actions.mcp.list_mcp_connected_accounts( config_id=server.id, identifier=user_id, include_auth_link=True ) for account in accounts.connected_accounts: if account.connected_account_status != "ACTIVE": print("Send the user this link:", account.authentication_link) session = actions.mcp.create_session_token( mcp_config_id=server.id, identifier=user_id, expiry=timedelta(minutes=30), )

During the run: connect any MCP client with the server URL and the session token as a bearer header. With the Python MCP SDK (version 2):

import asyncio import httpx2 from mcp import Client from mcp.client.streamable_http import streamable_http_client async def run(): headers = {"Authorization": f"Bearer {session.token}"} async with httpx2.AsyncClient(headers=headers, timeout=30) as http: url = server.mcp_server_url transport = streamable_http_client(url, http_client=http) async with Client(transport) as mcp: tools = await mcp.list_tools() print([tool.name for tool in tools.tools]) result = await mcp.call_tool( "gmail_list_threads", {"query": "is:unread newer_than:1d", "max_results": 5}, ) print(result.is_error, result.content) asyncio.run(run())

How session tokens behave:

  • A token is bound to one user and one server. Sent to any other server URL, it returns 401.
  • It lasts one hour by default, and you can set anything from 60 seconds to 24 hours.
  • It is not refreshed. Mint a new one per run, per chat session, or on a schedule for a long-running host.
  • Add access_level="READ_ONLY" and the run sees only the read tools; gmail_create_draft and gmail_send_draft drop out of tools/list.

The server also lists a connect_account tool. If the user's Gmail account is not connected, a tool call tells the agent to call it for an authorization link. To revoke one user, delete their connected account; other users keep working:

actions.delete_connected_account( connection_name="gmail", identifier=user_id )

Audit logs per tool call

AgentKit keeps tool call logs for 90 days with the tool name, connected account, identifier, status and duration. They never contain a tool's successful response, so message content stays out of them.

Security notes

  • Start with read access. Request gmail.readonly alone or use read-only session tokens for an agent that only reads.
  • Keep sending behind approval. Google's server leaves every message as a draft, and Anthropic's connector asks before it sends by default. Where your own agent can send, require a person to approve gmail_send_draft or gmail_send_message. In Claude Code, an ask rule such as mcp__gmail__create_draft in /permissions makes even drafting wait for you.
  • Treat email as untrusted input. Anyone can put instructions in a message your agent reads, so content from an email should never trigger a write on its own.
  • Know how to revoke. Google's token revocation endpoint is https://oauth2.googleapis.com/revoke. With Scalekit, deleting a connected account removes one user's access without touching anyone else's.

Which one to build against

For an interactive agent that searches, reads, labels and drafts for human review, Google's Gmail MCP server is the faster route, though it is preview software and cannot send. For an agent that sends mail, syncs, reacts to inbound events or acts for users who never signed in, build on the REST API. Many production Gmail agents use both. The per-user credential work is the same either way.

FAQs

Does Google have an official Gmail MCP server?

Yes. Google hosts a remote Gmail MCP server at https://gmailmcp.googleapis.com/mcp/v1, one of the Google Workspace MCP servers, in Developer Preview. Each user signs in with OAuth 2.0 and the agent acts with that user's permissions.

How do I connect Claude to Gmail?

In Claude.ai or Claude Desktop, connect Anthropic's Gmail connector under Customize > Connectors, or add Google's server as a custom connector with your own OAuth client. In Claude Code, add Google's server with your client ID, secret and a fixed callback port, then sign in from /mcp.

Can the Gmail MCP server send email?

No. create_draft leaves the message in the user's Drafts folder to review and send from Gmail. An agent that sends on its own needs users.messages.send or users.drafts.send on the REST API, or a connector that wraps them.

Is the Gmail MCP server free?

Google lists no charge for standard use today. Gmail API usage under 80,000,000 quota units per day per project is not billed, and Google says it will give at least 90 days' notice before billing changes take effect.

Why does the Gmail MCP server return 401 or keep asking me to sign in?

Tool calls without a valid access token get a 401, and Google access tokens last about an hour. If you sign in every hour, your client is not getting a refresh token, which Google issues only for requests with access_type=offline. If you are signed out after a week, your External app is in Testing status, where refresh tokens expire after 7 days.

Does using the Gmail MCP server avoid Google's OAuth app verification?

No. Its gmail.readonly and gmail.compose scopes are restricted scopes, the same ones the REST API uses. A public app needs restricted-scope verification, and apps used only inside your own Workspace organization are exempt.

How does Scalekit AgentKit handle Gmail tokens for multi-tenant agents?

AgentKit runs each user's OAuth flow against your Google OAuth app, stores and refreshes the tokens, and calls Gmail as that user. Your agent connects to one Virtual MCP server URL with a short-lived session token bound to one user, so it never receives a Gmail token.

Details checked October 2026.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Scalekit
Find us on ProductHunt

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.