Skip to content

read_emails

Read Gmail messages or count matches through the configured delegated mailbox. See Configuration for setup and startup validation.

MCP usage

Tool name: read_emails. Example tool arguments:

{
  "to": "me",
  "sender": "amy OR david",
  "subject": "verification code",
  "after": "5m",
  "limit": 10
}

Parameters

Name Type Default Description
to string Required Gmail recipient search expression, 1–1024 characters after trimming.
sender string or null null Gmail sender search expression, up to 1024 characters.
subject string or null null Subject phrase, up to 1024 characters; quoted and escaped when composing the query.
after string or null null Look-back duration: nonnegative integer plus lowercase s, m, h or d, such as 30s, 5m, 1h, 1d. The value must fit the supported date range.
latest boolean false Request one result: the first matching message returned by Gmail.
count boolean false Count matches across all pages. Takes precedence over latest.
limit integer 10 Normal-mode page size, 1–100. Ignored in latest and count modes.
page_token string or null null Opaque cursor from a normal-mode response. Incompatible with latest or count.
max_body_chars integer 20000 Maximum body characters per message, 1–100000.

Search values are not restricted to email addresses. Gmail accepts names, addresses, me, and grouped expressions, as described in Google's search operators. For example, sender: "amy OR david" becomes from:(amy OR david). The server wraps to and sender in their field groups; supply the values without adding a leading to: or from:. Quotes, parentheses and braces must balance, and embedded control characters are rejected. Empty optional filters are omitted.

Queries include Spam and Trash. after becomes an absolute UTC epoch cutoff; the same cutoff is retained when following a page cursor. Gmail API searches can differ from the UI, including alias expansion; see Google's filtering guide. latest follows Gmail's result order and does not perform a separate global sort.

Responses

A successful normal read returns:

{
  "status": "ok",
  "data": {
    "emails": [
      {
        "id": "message-id",
        "thread_id": "thread-id",
        "internal_date": "1775988000000",
        "from": "[email protected]",
        "to": "[email protected]",
        "subject": "Verification code",
        "date": "Sun, 12 Apr 2026 10:00:00 +0000",
        "body": "Your code is 123456",
        "body_truncated": false,
        "warnings": []
      }
    ],
    "partial": false,
    "failed_ids": [],
    "next_page_token": null
  }
}

internal_date is Gmail's millisecond timestamp represented as a string. Missing headers are empty strings. Body extraction prefers plain text among alternatives, skips file attachments, honors MIME charsets, and converts HTML into text with line breaks and link URLs. External text-body parts are fetched through Gmail's attachments endpoint; file attachments are not downloaded.

partial means some content could not be returned completely. Inspect failed_ids for failed message fetches, and each message's warnings and body_truncated for extraction problems or limits. Examples of warnings include body_fetch_failed, invalid_body_encoding, unknown_charset, and related_root_missing. If every message fetch fails, the call returns an error. A successful page may be empty but still contain a continuation cursor.

Bodies are limited to max_body_chars, with an additional 2 MB decoding ceiling. Headers are limited to 4096 characters each. The total serialized response is limited to 1 MiB; RESULT_TOO_LARGE asks the caller to lower limit or max_body_chars. A truncated message can be retried with a larger body limit.

Pagination and count

When next_page_token is non-null, pass it as page_token together with the same to, sender, subject, and after values. You may adjust limit and max_body_chars. Cursors belong to the current server session; restart the search after a server restart. They preserve the query cutoff but do not freeze the mailbox: newly arriving or deleted messages can affect subsequent pages. partial: false describes the returned page, not the end of the search.

Count mode walks every page rather than trusting Gmail's estimate:

{"status": "ok", "data": {"count": 47}}

No matches returns count 0. A failed or timed-out count returns an error, never a partial total. Large searches can reach the operation deadline; narrow the filters when that happens.

Errors

{"status": "error", "error": "NO_EMAILS_FOUND: no matching emails found"}
Prefix Meaning
INVALID Invalid arguments, grouping, duration or page cursor.
NO_EMAILS_FOUND No matching messages in a content read; an OTP may not have arrived yet.
AUTH_ERROR Authentication, delegation or access was rejected.
NETWORK_ERROR A network/protocol request failed or reached its socket timeout.
API_ERROR Another Gmail failure, invalid response or all message fetches failed.
TIMEOUT The operation exhausted its budget, including queue time.
RESULT_TOO_LARGE Lower limit or max_body_chars and retry.

Configuration errors prevent startup; they are not deferred until a tool call. MCP itself may reject arguments with incompatible JSON types before invoking the tool. The server uses only gmail.readonly and does not mark messages read, modify labels, send mail or delete messages.