Gmail MCP
NPM · MCP-GOOGLE-GMAIL
MCP server for the Gmail API: search, read and send email, manage drafts, labels and the trash.
Available components
Last scanned (7 hours ago)
Scores higher than 58% of npm servers
Category Communication
How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. How we score → Why this is hard to score →
Supply Chain Security81
- No malware found by supply-chain analysis.Pass
- CVE check failed: a known high-severity CVE affects zod 3.25.76, a direct dependency. A fixed version is available. View diagnostics → Fail
- No install/post-install scripts declared.Pass
- 30 of 94 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency45
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Provenance check failed: no build-provenance attestation is published. See how to fix → View diagnostics → Fail
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 0 days ago).Pass
- Disclosure check failed: no security disclosure policy was found in the source repository. See how to fix → Fail
Schema Quality & AI Usability72
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 4630 tokens (~192/item across 24 items; 24 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 4 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 25 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 4 Nov 26 0
- Stability: pass → unverified ▼ security
- Tool safety: pass → unverified ▼ security
- Capabilities: pass → unverified ▼ functional
- Tool coverage: 100 → unverified ▼ functional
- First check of Schema quality: unverified functional
- Package version: 1.1.1 → 1.1.2 functional
- 1 Nov 26 +20
- Known CVEs: unverified → fail ▼ security
- Malware scan: unverified → pass ▲ security
- Dependency health: unverified → 0.86 ▲ functional
- 31 Oct 26 −20
- Known CVEs: fail → unverified ▼ security
- Malware scan: pass → unverified ▼ security
- Stability: 0.97 → pass security
- Security disclosure: unverified → fail ▼ functional
- Dependency health: 0.86 → unverified ▼ functional
- Package version: 1.0.0 → 1.1.1 functional
- Package version: 1.0.0 → 1.1.0 functional
- 30 Oct 26 +1
- Security disclosure: fail → unverified ▼ functional
- 29 Oct 26 −1
- Stability: pass → 0.93 functional
- 24 Oct 26 −5
- CVE-2023-54404 affects this package: high ▼ security
- Known CVEs: pass → fail ▼ security
- 20 Oct 26 0
- Stability: 0.97 → pass security
- 19 Oct 26 0
- Stability: pass → 0.97 functional
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed npm/mcp-google-gmail@1.1.2
Provenance No attestation
The registry publishes no build provenance for this version, so there is nothing to verify.
| Result | No attestation |
|---|---|
| Ecosystem | npm |
Background: How many MCP packages publish verified provenance →
Vulnerabilities 1 finding
| ID | CVE | Severity | Vector | Fix available |
|---|---|---|---|---|
| GHSA-mrhx-c7xc-m3w5 | CVE-2023-54404 | high | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H | yes |
Background: What a vulnerability scan can and cannot prove →
Dependencies 94 packages
| Packages resolved | 94 |
|---|---|
| Stale | 30 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
auth_status Google connection status ~81
Shows whether this server is connected to Google: token presence and source (env variables or a stored in-chat login), expiry, the Google account email, granted vs missing OAuth scopes, where the credentials file lives and where the OAuth client comes from. Makes no network calls and never returns the token itself. Call it first when other tools report the server is not connected.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
create_draft Create a draft ~276
Creates a draft email in the mailbox without sending anything. All fields are optional — an empty draft is legal — but a useful one carries to[], subject and a body. For a reply draft set thread_id, in_reply_to (headers.messageId of the message being answered, via get_message) and the original subject with "Re: ". Returns the draft id (needed by update_draft/send_draft/delete_draft) and the underlying message id/threadId. Drafting first and sending with send_draft after a human look is the safe path for consequential mail — prefer it over send_message when in doubt.
| Name | Type | Req | Description |
|---|---|---|---|
| bcc | array | – | Blind-copy recipients. |
| body_html | string | – | HTML body (multipart/alternative when body_text is also set). |
| body_text | string | – | Plain-text body. |
| cc | array | – | Carbon-copy recipients. |
| in_reply_to | string | – | RFC Message-ID of the message being replied to (headers.messageId from get_message). |
| references | string | – | Explicit References header chain (defaults to in_reply_to). |
| subject | string | – | The subject line. |
| thread_id | string | – | Make it a reply draft in this thread (pair with in_reply_to and a matching subject). |
| to | array | – | Primary recipients (optional for a draft). |
No output schema declared.
No examples provided.
delete_draft Delete a draft ~73
PERMANENTLY deletes a draft — drafts skip the trash, so there is no undo and no manage_trash recovery. Confirm with get_draft before deleting anything the user might still want. Returns empty on success.
| Name | Type | Req | Description |
|---|---|---|---|
| draft_id | string | yes | The draft id from list_drafts or create_draft output. |
No output schema declared.
No examples provided.
finish_login Finish the Google login ~123
Second step: waits up to 20 s for the browser consent to finish, saves the tokens to an owner-only file and verifies the login with a read-only identity call, returning the account email and the granted scopes. After success every tool works immediately — no client restart. If the user granted only part of the requested permissions, the login is still saved and missingScopes lists what will not work. Logging in under a different Google account replaces the previous login (its refresh token is revoked best-effort) and the response carries previousAccountEmail so the change never goes unnoticed.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_draft Read a draft ~147
Fetches one draft with its message decoded like get_message: headers (to, cc, subject, ...), text body, HTML only on request, attachment metadata. Use it to show the user what send_draft would send, or to read the current content before update_draft (updates REPLACE the whole draft).
| Name | Type | Req | Description |
|---|---|---|---|
| draft_id | string | yes | The draft id from list_drafts or create_draft output. |
| include_html | boolean | – | Return the decoded HTML body even when a text body exists (default false). |
| max_body_chars | integer | – | Truncate each decoded body at this many characters (default 50000; a truncation flag is set when cut). |
No output schema declared.
No examples provided.
get_message Read a message ~249
Fetches one message fully decoded: headers (from, to, cc, subject, date, messageId, inReplyTo, references — RFC 2047 words decoded), the plain-text body (base64/charset decoded), the HTML body when there is no text part or include_html=true, and attachment METADATA (filename, mimeType, sizeBytes, attachmentId — never the content; download bytes via raw_request users/me/messages/<id>/attachments/<attachmentId> if truly needed). Bodies are truncated at max_body_chars (default 50000) with textTruncated/htmlTruncated flags. metadata_only=true skips bodies entirely. To reply later, keep headers.messageId (for in_reply_to) and threadId.
| Name | Type | Req | Description |
|---|---|---|---|
| include_html | boolean | – | Return the decoded HTML body even when a text body exists (default false). |
| max_body_chars | integer | – | Truncate each decoded body at this many characters (default 50000; a truncation flag is set when cut). |
| message_id | string | yes | The message id from list_messages/get_thread output (not the RFC Message-ID header). |
| metadata_only | boolean | – | Headers and structure only, no body content. |
No output schema declared.
No examples provided.
get_profile Get the mailbox profile ~58
Returns the authenticated mailbox's profile: emailAddress (the user's own address — useful for send-to-self checks and for recognizing the user's messages in threads), messagesTotal, threadsTotal and historyId. The cheapest way to verify that the OAuth credentials work.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
get_thread Read a whole conversation ~188
Fetches a conversation with every message decoded like get_message: headers, text bodies (HTML only when a message has no text part or include_html=true), attachment metadata and truncation flags. Messages come oldest-first. To reply to the conversation, take the LAST message's threadId, headers.messageId and subject and pass them to send_message (thread_id, in_reply_to, subject with "Re: "). Long threads can be large — lower max_body_chars (it applies per message) when only the gist is needed.
| Name | Type | Req | Description |
|---|---|---|---|
| include_html | boolean | – | Return decoded HTML bodies even when a text body exists (default false). |
| max_body_chars | integer | – | Truncate each decoded body at this many characters (default 50000; a truncation flag is set when cut). |
| thread_id | string | yes | The thread id from list_threads or from a message's threadId field. |
No output schema declared.
No examples provided.
list_drafts List drafts ~139
Lists the mailbox's drafts: draft id plus the underlying message's id and threadId (no subjects — read one with get_draft). query filters with Gmail query syntax (e.g. subject:invoice); paginate with page_token from nextPageToken.
| Name | Type | Req | Description |
|---|---|---|---|
| page_size | integer | – | Drafts per page (1..500, API default 100). |
| page_token | string | – | nextPageToken from the previous page. |
| query | string | – | Gmail query syntax, e.g. "from:amy@example.com is:unread newer_than:7d has:attachment subject:invoice". Same operators as the Gmail search box. |
No output schema declared.
No examples provided.
list_labels List labels ~120
Without label_id: lists every label in the mailbox — system labels (INBOX, SENT, DRAFT, SPAM, TRASH, UNREAD, STARRED, IMPORTANT, CATEGORY_*) and user labels with their ids — the vocabulary that list_messages label_ids and modify_message add/remove_label_ids speak. With label_id: fetches that one label including its counts (messagesTotal, messagesUnread, threadsTotal, threadsUnread), which the plain list does not carry.
| Name | Type | Req | Description |
|---|---|---|---|
| label_id | string | – | Fetch one label with counts instead of listing all. |
No output schema declared.
No examples provided.
list_messages Search and list messages ~352
Searches the mailbox with Gmail query syntax and returns one summary per message: id, threadId, labelIds, snippet, from, to, subject, date, internalDate. Filter with query (same operators as the Gmail search box: from:, to:, subject:, is:unread, is:starred, has:attachment, label:, newer_than:7d, before:/after:) and/or label_ids (all must match). Spam and trash are excluded unless include_spam_trash=true. Paginate with page_token from nextPageToken; page_size defaults to 25 (max 100 — each summary costs one metadata read, throttled to a few at a time). A message deleted between the search and its metadata read is skipped, so a page can hold slightly fewer summaries than page_size. Set include_metadata=false to get bare ids only (cheapest). resultSizeEstimate is an estimate, not an exact count. Read a full body with get_message; read a whole conversation with get_thread.
| Name | Type | Req | Description |
|---|---|---|---|
| include_metadata | boolean | – | false = bare ids only, no per-message metadata reads (default true). |
| include_spam_trash | boolean | – | Also search SPAM and TRASH (default false). |
| label_ids | array | – | Only messages carrying ALL of these label ids (see list_labels). |
| page_size | integer | – | Messages per page (1..100, default 25). |
| page_token | string | – | nextPageToken from the previous page. |
| query | string | – | Gmail query syntax, e.g. "from:amy@example.com is:unread newer_than:7d has:attachment subject:invoice". Same operators as the Gmail search box. |
No output schema declared.
No examples provided.
list_threads Search and list threads ~216
Searches conversations (threads) with the same Gmail query syntax as list_messages and returns id, snippet (of the latest message) and historyId per thread. Use this instead of list_messages when the unit of work is a conversation — triaging an inbox, finding a discussion to reply into. Filter with query and/or label_ids; paginate with page_token from nextPageToken (page_size max 500). Read the full conversation with get_thread.
| Name | Type | Req | Description |
|---|---|---|---|
| include_spam_trash | boolean | – | Also search SPAM and TRASH (default false). |
| label_ids | array | – | Only threads carrying ALL of these label ids (see list_labels). |
| page_size | integer | – | Threads per page (1..500, API default 100). |
| page_token | string | – | nextPageToken from the previous page. |
| query | string | – | Gmail query syntax, e.g. "from:amy@example.com is:unread newer_than:7d has:attachment subject:invoice". Same operators as the Gmail search box. |
No output schema declared.
No examples provided.
logout Disconnect from Google ~62
Revokes the stored token at Google (oauth2.googleapis.com/revoke) and deletes the local credentials file. Tokens supplied via env variables are NOT touched — remove them from the MCP client config manually; envTokenStillSet in the response says whether any are still in effect.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
manage_labels Create, rename or delete a label ~257
Manages user labels. action=create needs name (nest with "/", e.g. "Clients/Acme" — the parent must already exist). action=update needs label_id plus at least one of name, label_list_visibility (show | show_if_unread | hide — the label in the sidebar) or message_list_visibility (show | hide — its messages in the list); only the provided fields change. action=delete needs label_id and removes the label from EVERY message it was applied to — the messages survive, the label and its message-associations do not; this cannot be undone. System labels (INBOX, STARRED, ...) cannot be created, renamed or deleted. To apply/remove labels on mail, use modify_message or modify_thread, not this tool.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | What to do with the label. |
| label_id | string | – | update/delete: the user label to target. |
| label_list_visibility | string | – | Sidebar visibility of the label itself. |
| message_list_visibility | string | – | Whether the label's messages show in the message list. |
| name | string | – | create (required) / update: the label name, e.g. "Invoices" or nested "Clients/Acme". |
No output schema declared.
No examples provided.
manage_trash Trash or restore mail ~183
Moves a message or a whole thread to the Gmail trash, or restores it. action=trash is REVERSIBLE: Gmail keeps trashed mail for about 30 days, then deletes it permanently; action=untrash restores it before that happens. target=message (default) uses a message id, target=thread trashes/restores every message in the thread. This server intentionally has no permanent-delete tool — the trash is the safety net. Note: untrash does not re-add INBOX; follow up with modify_message archived=false if it should reappear in the inbox.
| Name | Type | Req | Description |
|---|---|---|---|
| action | string | yes | trash = move to trash (reversible), untrash = restore. |
| id | string | yes | The message id (target=message) or thread id (target=thread). |
| target | string | – | What the id refers to (default message). |
No output schema declared.
No examples provided.
modify_message Change message labels / state ~216
Changes a message's state via Gmail labels: read=true/false marks read/unread, starred=true/false stars/unstars, archived=true removes it from the inbox (archived=false moves it back), and add_label_ids/remove_label_ids apply or strip any labels from list_labels (e.g. a user label, or IMPORTANT). At least one change is required; applying the same change twice is harmless. This never deletes anything — use manage_trash for the trash. Returns the message's new id/labelIds.
| Name | Type | Req | Description |
|---|---|---|---|
| add_label_ids | array | – | Label ids to add. |
| archived | boolean | – | true = archive (remove from inbox), false = move back to inbox. |
| message_id | string | yes | The message id from list_messages/get_thread output (not the RFC Message-ID header). |
| read | boolean | – | true = mark read, false = mark unread. |
| remove_label_ids | array | – | Label ids to remove. |
| starred | boolean | – | true = star, false = unstar. |
No output schema declared.
No examples provided.
modify_thread Change thread labels / state ~195
Applies the same normalized state changes as modify_message — read/unread, starred, archived, add_label_ids/remove_label_ids — to EVERY message in a conversation at once. Use it to mark a whole conversation read or archive it in one call instead of looping over messages. At least one change is required; repeating the same change is harmless. Returns the thread's new id and message label state.
| Name | Type | Req | Description |
|---|---|---|---|
| add_label_ids | array | – | Label ids to add to every message. |
| archived | boolean | – | true = archive (remove from inbox), false = move back to inbox. |
| read | boolean | – | true = mark the whole thread read, false = unread. |
| remove_label_ids | array | – | Label ids to remove from every message. |
| starred | boolean | – | true = star, false = unstar. |
| thread_id | string | yes | The thread id from list_threads or from a message's threadId field. |
No output schema declared.
No examples provided.
raw_request Raw Gmail API call ~219
Escape hatch to call any Gmail API v1 path directly, for requests the typed tools don't cover — e.g. downloading attachment content ("gmail/v1/users/me/messages/<messageId>/attachments/<attachmentId>", returns base64url data), history.list for incremental sync ("gmail/v1/users/me/history?startHistoryId=..."), batchModify, or settings endpoints (filters, forwarding, vacation). The path may carry a query string. The Bearer token is added automatically; the method defaults to GET. CAUTION: this bypasses the typed tools' guard rails — users/me/messages/<id> DELETE is a PERMANENT delete that skips the trash (needs the full https://mail.google.com/ scope); prefer manage_trash.
| Name | Type | Req | Description |
|---|---|---|---|
| body | object | – | JSON request body (POST/PUT/PATCH). |
| method | string | – | HTTP method. Defaults to GET. |
| path | string | yes | API path relative to https://gmail.googleapis.com, e.g. "gmail/v1/users/me/history?startHistoryId=123". |
No output schema declared.
No examples provided.
send_draft Send a draft ~139
Sends an existing draft exactly as it is stored, immediately and irreversibly; the draft disappears from the drafts list and becomes a sent message (returned id/threadId). Verify the content with get_draft before calling this. NEVER retried after a timeout or 5xx (a duplicate email cannot be unsent): if the outcome is unclear, check list_drafts (the draft is gone if it was sent) or list_messages in:sent before considering anything else. Daily sending limits apply (~500/day consumer, ~2000/day Workspace).
| Name | Type | Req | Description |
|---|---|---|---|
| draft_id | string | yes | The draft id from list_drafts or create_draft output. |
No output schema declared.
No examples provided.
send_message Send an email ~361
Sends an email from the authenticated mailbox, immediately and irreversibly. Requires at least one recipient across to/cc/bcc (a bcc-only send is fine — to may be omitted) and at least a subject or a body; body_text and body_html together become multipart/alternative. TO REPLY IN A THREAD: call get_message on the message being answered first, then pass its threadId as thread_id, its headers.messageId as in_reply_to, and the same subject prefixed with "Re: " — Gmail threads the reply only when all three line up. Returns the sent message's id, threadId and labelIds. NEVER retried after a timeout or 5xx (a duplicate email cannot be unsent): if the outcome is unclear, search list_messages with in:sent before considering a re-send. Everyday accounts can send ~500 emails/day (Workspace ~2000); exceeding it disables sending for hours.
| Name | Type | Req | Description |
|---|---|---|---|
| bcc | array | – | Blind-copy recipients. |
| body_html | string | – | HTML body (sent as multipart/alternative when body_text is also set). |
| body_text | string | – | Plain-text body. |
| cc | array | – | Carbon-copy recipients. |
| in_reply_to | string | – | RFC Message-ID of the message being replied to (headers.messageId from get_message). |
| references | string | – | Explicit References header chain (defaults to in_reply_to). |
| subject | string | – | The subject line. For replies use the original subject with "Re: ". |
| thread_id | string | – | Reply into this thread (pair with in_reply_to and a matching subject). |
| to | array | – | Primary recipients. Optional when cc or bcc carries at least one recipient (bcc-only send). |
No output schema declared.
No examples provided.
set_client Save the OAuth client ~111
Saves the OAuth client credentials from the JSON file downloaded from Google Cloud Console ('Download JSON' on a Desktop-app client). Pass the file PATH — the secret must never be pasted into the chat. The client is stored once in the shared ~/.config/mcp-google-auth/client.json (owner-only) and reused by every mcp-google-* server; tokens stay per-server. After this, call start_login.
| Name | Type | Req | Description |
|---|---|---|---|
| path | string | yes | Absolute path to the client_secret_*.json file downloaded from Google Cloud Console. |
No output schema declared.
No examples provided.
setup_instructions Setup instructions ~109
Step-by-step checklist for connecting this server to Google: creating a Google Cloud project and a Desktop-app OAuth client, publishing the consent screen (mandatory — Testing-mode refresh tokens die after 7 days), downloading the client JSON and handing its PATH to set_client. Works without any credentials; the checklist shortens to 'enable the API + log in' when an OAuth client is already configured (one client serves the whole mcp-google-* line). Never asks the user to paste secrets into the chat.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
start_login Start the Google login ~114
First step of connecting from the chat, without editing config files or restarting the client. Returns authorizeUrl — show it to the user as a clickable link and ask them to open it in the browser ON THIS MACHINE, pick the Google account and approve access. A one-shot listener on 127.0.0.1 catches Google's redirect; the code is exchanged locally and never passes through the chat. Does not open the browser itself. The attempt lives 10 minutes; when the browser shows the success page, call finish_login.
Input schema present but exposes no named parameters.
No output schema declared.
No examples provided.
update_draft Update a draft ~252
REPLACES a draft's entire message — the Gmail API has no partial draft edit, so omitted fields are dropped, not kept. Read the current content with get_draft first, then pass the complete new state (recipients, subject, body, and thread_id/in_reply_to for reply drafts). The draft id stays the same; the underlying message id changes. Returns the updated draft.
| Name | Type | Req | Description |
|---|---|---|---|
| bcc | array | – | Blind-copy recipients. |
| body_html | string | – | HTML body (multipart/alternative when body_text is also set). |
| body_text | string | – | Plain-text body. |
| cc | array | – | Carbon-copy recipients. |
| draft_id | string | yes | The draft id from list_drafts or create_draft output. |
| in_reply_to | string | – | RFC Message-ID of the message being replied to (headers.messageId from get_message). |
| references | string | – | Explicit References header chain (defaults to in_reply_to). |
| subject | string | – | The subject line. |
| thread_id | string | – | Make it a reply draft in this thread (pair with in_reply_to and a matching subject). |
| to | array | – | Primary recipients (optional for a draft). |
No output schema declared.
No examples provided.
How do I install the Gmail MCP server?
Gmail MCP runs locally as an npm package, launched with npx -y mcp-google-gmail. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
npm · mcp-google-gmail
claude mcp add a1-x-tech-mcp-google-gmail -- npx -y mcp-google-gmail
What is the Gmail MCP server?
Gmail MCP is listed in the public MCP registry as io.github.A1-x-Tech/mcp-google-gmail. MCP server for the Gmail API: search, read and send email, manage drafts, labels and the trash. This page covers its npm package (mcp-google-gmail).
Is the Gmail MCP server safe to use?
Gmail MCP scores 78 out of 100 on VerifyMCP. We recorded 1 known advisory against it as of 5 November 2026. It declares no install or post-install scripts. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Gmail MCP server expose?
Gmail MCP exposes 24 tools: auth_status, setup_instructions, set_client, start_login, finish_login, and 19 more. Their descriptions and schemas cost roughly 4,240 tokens of context every time the server is loaded.
Is the Gmail MCP server still maintained?
Gmail MCP is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the Gmail MCP server under?
Gmail MCP declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.