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.