Gmail MCP Server

Gmail MCP Server

A Model Context Protocol server for Gmail that lets AI assistants read, send, search, label, and filter Gmail through natural language, with OAuth2 auto-authentication and full attachment support.

Category
访问服务器

README

Gmail MCP Server

CI License: MIT node semantic-release Checked with Biome

A Model Context Protocol server for Gmail. Lets AI assistants read, send, search, label, and filter Gmail through natural language, with OAuth2 auto-authentication and full attachment support.

Built with TypeScript, Bun, and the googleapis client.

Highlights

  • Structured JSON responses. read_email and search_emails return parseable JSON objects, not pre-formatted text. Easier for downstream tools to consume without fragile string parsing. (See Structured responses below.)
  • Full attachment support. Send files, read attachment metadata, and download attachments to disk. Path traversal is blocked at the download boundary.
  • HTML-first email reading. When a message has both plain text and HTML parts, both are returned so the client can pick.
  • Comprehensive label management. Create, update, delete, list, and get-or-create labels. System labels are protected from deletion.
  • Gmail filter management. Full CRUD on filters plus six templates (fromSender, withSubject, withAttachments, largeEmails, containingText, mailingList).
  • Batch operations. Modify or delete many messages in one call, with graceful per-item fallback if a batch fails.
  • RFC 2047 subject encoding for international characters.
  • Typed input validation via Zod schemas on every tool.
  • Error responses set isError: true so MCP clients can distinguish failures from successes.
  • Automated releases via semantic-release on every push to main.

Installation

1. Clone and build

git clone https://github.com/simiancraft/Gmail-MCP-Server.git
cd Gmail-MCP-Server
bun install
bun run build

2. Create Google Cloud OAuth credentials

  1. Go to the Google Cloud Console and create (or select) a project.
  2. Enable the Gmail API for the project.
  3. Under APIs & Services → Credentials, click Create Credentials → OAuth client ID.
  4. Choose Desktop app or Web application. For Web application, add http://localhost:3000/oauth2callback to the authorized redirect URIs.
  5. Download the JSON, rename it to gcp-oauth.keys.json.

3. Authenticate

mkdir -p ~/.gmail-mcp
mv gcp-oauth.keys.json ~/.gmail-mcp/
bun dist/index.js auth

The auth command:

  • Looks for gcp-oauth.keys.json in the current directory or ~/.gmail-mcp/.
  • Opens your browser to the Google consent screen.
  • Saves the resulting token to ~/.gmail-mcp/credentials.json.

Credentials can be overridden with environment variables:

  • GMAIL_OAUTH_PATH — path to the client keys JSON
  • GMAIL_CREDENTIALS_PATH — path to the stored user token JSON

4. Wire it into your MCP client

Example for Claude Desktop:

{
  "mcpServers": {
    "gmail": {
      "command": "bun",
      "args": ["/absolute/path/to/Gmail-MCP-Server/dist/index.js"]
    }
  }
}

With custom credential paths:

{
  "mcpServers": {
    "gmail": {
      "command": "bun",
      "args": ["/absolute/path/to/Gmail-MCP-Server/dist/index.js"],
      "env": {
        "GMAIL_OAUTH_PATH": "/path/to/gcp-oauth.keys.json",
        "GMAIL_CREDENTIALS_PATH": "/path/to/credentials.json"
      }
    }
  }
}

Structured responses

This is the most important behavioral difference worth calling out: read_email and search_emails return structured JSON rather than pre-formatted text blobs. The JSON is embedded in the MCP content[0].text field, so clients can JSON.parse it directly.

read_email response

{
  "messageId": "182ab45cd67ef",
  "threadId": "182ab45cd67ef",
  "subject": "Project Files",
  "from": "sender@example.com",
  "to": "recipient@example.com",
  "date": "Thu, 19 Jun 2025 10:30:00 -0400",
  "body": {
    "text": "Plain text version of the email...",
    "html": "<html>Rich HTML version...</html>"
  },
  "attachments": [
    {
      "id": "ANGjdJ9fkTs...",
      "filename": "document.pdf",
      "mimeType": "application/pdf",
      "size": 250880
    }
  ]
}

body.text and body.html are independently null when the message does not contain that part. Most transactional/vendor email is HTML-only; some plain-text-only senders only populate text.

search_emails response

[
  {
    "id": "182ab45cd67ef",
    "subject": "Project Files",
    "from": "sender@example.com",
    "date": "Thu, 19 Jun 2025 10:30:00 -0400"
  }
]

All other tools return human-readable status text in content[0].text (e.g. "Email sent successfully with ID: ...").

Tool reference

All 19 tools accept validated JSON input. Required fields are called out explicitly; everything else is optional.

Email

send_email

Sends a new email. Supports plain text, HTML, multipart, attachments, and threading.

{
  "to": ["recipient@example.com"],
  "subject": "Meeting Tomorrow",
  "body": "Hi, reminder about our meeting.",
  "mimeType": "text/plain",
  "cc": ["cc@example.com"],
  "bcc": ["bcc@example.com"],
  "attachments": ["/path/to/file.pdf"],
  "threadId": "182ab45cd67ef",
  "inReplyTo": "<message-id@example.com>"
}
  • mimeType defaults to text/plain. Use text/html for HTML-only, or multipart/alternative with both body and htmlBody for clients that can render either.
  • Attachments are validated for existence before send.

draft_email

Same input as send_email but creates a draft instead of sending.

read_email

Retrieves full content of a message. See Structured responses.

{ "messageId": "182ab45cd67ef" }

search_emails

Searches using Gmail search syntax. Returns an array of metadata (see Structured responses).

{
  "query": "from:sender@example.com after:2024/01/01 has:attachment",
  "maxResults": 10
}

modify_email

Adds or removes labels on a single message. If both addLabelIds and labelIds are provided, addLabelIds takes precedence.

{
  "messageId": "182ab45cd67ef",
  "addLabelIds": ["IMPORTANT"],
  "removeLabelIds": ["INBOX"]
}

delete_email

Permanently deletes an email. Irreversible.

{ "messageId": "182ab45cd67ef" }

download_attachment

Downloads an attachment to disk. Filenames are sanitized (path.basename) and the resolved output path is verified to stay inside savePath to prevent traversal.

{
  "messageId": "182ab45cd67ef",
  "attachmentId": "ANGjdJ9fkTs...",
  "savePath": "/path/to/downloads",
  "filename": "custom-name.pdf"
}

savePath defaults to the current working directory. filename defaults to the original filename from the message.

Batch

batch_modify_emails

Adds/removes labels on many messages at once. Falls back to per-item retry if a batch fails.

{
  "messageIds": ["id1", "id2", "id3"],
  "addLabelIds": ["IMPORTANT"],
  "removeLabelIds": ["INBOX"],
  "batchSize": 50
}

batch_delete_emails

Permanently deletes many messages in batches.

{
  "messageIds": ["id1", "id2", "id3"],
  "batchSize": 50
}

Labels

list_email_labels

Lists all labels, split into system and user groups.

{}

create_label

{
  "name": "Important Projects",
  "messageListVisibility": "show",
  "labelListVisibility": "labelShow"
}

update_label

{
  "id": "Label_1234567890",
  "name": "Urgent Projects"
}

delete_label

Refuses to delete system labels.

{ "id": "Label_1234567890" }

get_or_create_label

Idempotent. Returns the existing label if one with that name exists; otherwise creates it. The response tells you which happened.

{
  "name": "Project XYZ",
  "messageListVisibility": "show",
  "labelListVisibility": "labelShow"
}

Filters

create_filter

{
  "criteria": {
    "from": "newsletter@company.com",
    "hasAttachment": false
  },
  "action": {
    "addLabelIds": ["Label_Newsletter"],
    "removeLabelIds": ["INBOX"]
  }
}

list_filters, get_filter, delete_filter

{}
{ "filterId": "ANe1Bmj..." }

create_filter_from_template

Six templates: fromSender, withSubject, withAttachments, largeEmails, containingText, mailingList.

{
  "template": "fromSender",
  "parameters": {
    "senderEmail": "notifications@github.com",
    "labelIds": ["Label_GitHub"],
    "archive": true
  }
}

Gmail search syntax

search_emails accepts any standard Gmail search operator:

Operator Example Description
from: from:john@example.com Emails from a specific sender
to: to:mary@example.com Emails to a specific recipient
subject: subject:"meeting notes" Subject match
has:attachment has:attachment Has attachments
after: after:2024/01/01 After a date
before: before:2024/02/01 Before a date
is: is:unread Message state
label: label:work Has a specific label

Combine freely: from:john@example.com after:2024/01/01 has:attachment.

Security

  • OAuth credentials are stored locally in ~/.gmail-mcp/ (or the paths set in env vars). Never commit them.
  • Attachment downloads validate the resolved output path against savePath to block path traversal via crafted filenames.
  • The server requests gmail.modify and gmail.settings.basic scopes — enough to read/send/label/filter, but not to change account settings beyond filters.
  • Offline access is used so the token refreshes without re-consent. Revoke in your Google Account → Security → Third-party access if you want to kill it.
  • Error responses set isError: true so clients can distinguish failures from successes rather than pattern-matching on text.

Development

bun install          # install dependencies
bun run build        # compile TypeScript to dist/
bun test             # run the test suite (53 tests)
bun run lint         # biome check
bun run lint:fix     # biome auto-fix
bun run format       # biome format

Tests live alongside source as src/*.test.ts and use Bun's built-in test runner. Running bun test discovers them automatically — no extra config.

Commit style

This project uses Conventional Commits and semantic-release. Pushes to main with the right prefix automatically bump the version and publish a GitHub Release.

Prefix Bump Example
fix: patch fix: handle missing attachment header
feat: minor feat: add batch label operations
feat!: / BREAKING CHANGE: major feat!: change auth flow
chore:, docs:, ci:, refactor:, test: no release chore: update biome config

Troubleshooting

  1. OAuth keys not found. Make sure gcp-oauth.keys.json is in ~/.gmail-mcp/ (or in your current working directory at auth time).
  2. Invalid credentials format. The keys file must contain either a web or installed block. For web apps, verify http://localhost:3000/oauth2callback is in the authorized redirect URIs.
  3. Port 3000 already in use. Free it before running bun dist/index.js auth — the OAuth callback server listens there.
  4. Batch operation failures. Batches automatically retry per-item; check the returned failure list. If you're hitting rate limits, lower batchSize.
  5. Attachment send fails. Verify paths exist and are readable. Gmail's per-message attachment cap is 25 MB.

License

MIT. See LICENSE.

History

This project started as a clone of gongrzhe/server-gmail-autoauth-mcp in 2025. It has since diverged substantially — rewritten build/runtime to Bun, added semantic-release, restructured source into separate schemas/label/filter modules, added a full test suite, changed read_email and search_emails to return structured JSON, and tightened security, error handling, and type safety. The LICENSE file preserves the original MIT copyright, per the license's requirements.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选