Model Context Protocol server for Gmail integration, supporting email reading, sending, drafts management, and OAuth authentication
Gmail MCP server has solid fundamentals with 10 well-named tools using consistent verb_noun patterns (list_, read_, send_, create_, update_, delete_). All tools have descriptions (10-80 chars each, mostly adequate). Input schemas are present with type definitions for all parameters. However, there are moderate gaps: (1) descriptions are terse and lack context about when to use each tool vs similar alternatives, (2) output schemas are not documented, callers cannot see what fields to expect from responses, (3) no error handling guidance or recovery paths, (4) no tool annotations (readOnlyHint/destructiveHint) despite having both read-only and destructive tools, (5) missing security pattern details like scope declarations.
Create a draft email (not sent) with support for plain text or HTML body, CC, BCC recipients
Delete a draft email permanently
Exchange OAuth authorization code for refresh token and store credentials
Get the OAuth authorization URL for user authentication with Gmail
List all draft emails with optional pagination and metadata
List emails from Gmail with optional filtering by labels, query, read status, and pagination
Read the full content of a specific draft email including subject, recipients, and body
Output schemas not documented. LLMs cannot determine what fields to expect from tool responses (e.g., read_email returns message object, what fields? attachments structure? plaintext vs HTML body?). This forces agents to make assumptions and wastes tokens on parsing unstructured responses.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Destructive tools like delete_draft lack destructiveHint flag, preventing agents from recognizing irreversible operations and applying extra caution. Read-only tools lack readOnlyHint, preventing agents from safely retrying.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 54 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | - | v1 |
Read the full content of a specific email message including subject, sender, recipients, body, and attachments
Send an email message with support for plain text or HTML body, CC, BCC, and automatic MIME message formatting
Update the content of a draft email with new subject, body, and recipients
Tool descriptions lack actionable context. 'List emails from Gmail with optional filtering' does not explain when to call list_emails vs search via query parameter, what default limit applies, or pagination behavior. Descriptions should answer: what does it do, when to use it, what it returns.
No error handling or recovery guidance. Code shows no error messages that tell LLMs what to do next (e.g., 'Invalid auth code. Request a fresh authorization URL from get_auth_url' or 'Message not found, call list_emails to verify message ID'). Raw API errors provide no recovery path.
Destructive operation (delete_draft) lacks confirmation/dry-run pattern. No evidence of confirmation step before permanent deletion. Agents can delete drafts on hallucinations without safeguards.
No scope declarations visible in tool descriptions. Tools do not explicitly state required OAuth scopes (e.g., 'Requires gmail.readonly' or 'Requires gmail.send'). This prevents agents from understanding least-privilege constraints and complicates permission audits.
Parameter constraints underspecified. 'maxResults' accepts a number with no documented bounds (min/max). Can agents pass 0, 1000000, or negative? This invites invalid API calls. Format of 'query' (Gmail search syntax) not explained in parameter description.
HTML-to-Markdown conversion logic exists (dropUnsupportedNodes, rehypeRemark pipeline) but is not documented. Code shows conversion of HTML email bodies to Markdown, but read_email description does not state whether responses include plain text, HTML, or Markdown representations, critical for agent downstream usage.
OAuth flow tools lack dependency hints. 'exchange_auth_code' description does not say 'Call get_auth_url first to obtain the code' or explain what happens if code is invalid/expired. Agents may attempt to exchange codes before having one.