list_messages
Retrieve and filter email messages from your Gmail mailbox using search queries, labels, and pagination controls.
Instructions
List messages in the user's mailbox with optional filtering
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| maxResults | No | Maximum number of messages to return. Accepts values between 1-500 | |
| pageToken | No | Page token to retrieve a specific page of results | |
| q | No | Only return messages matching the specified query. Supports the same query format as the Gmail search box | |
| labelIds | No | Only return messages with labels that match all of the specified label IDs | |
| includeSpamTrash | No | Include messages from SPAM and TRASH in the results | |
| includeBodyHtml | No | Whether to include the parsed HTML in the return for each body, excluded by default because they can be excessively large |
Implementation Reference
- src/index.ts:580-608 (handler)The complete implementation of the 'list_messages' tool, including registration, input schema validation with Zod, and the handler logic that invokes the Gmail API to list messages, optionally processes message payloads to decode bodies, and formats the response as JSON text content.server.tool("list_messages", "List messages in the user's mailbox with optional filtering", { maxResults: z.number().optional().describe("Maximum number of messages to return. Accepts values between 1-500"), pageToken: z.string().optional().describe("Page token to retrieve a specific page of results"), q: z.string().optional().describe("Only return messages matching the specified query. Supports the same query format as the Gmail search box"), labelIds: z.array(z.string()).optional().describe("Only return messages with labels that match all of the specified label IDs"), includeSpamTrash: z.boolean().optional().describe("Include messages from SPAM and TRASH in the results"), includeBodyHtml: z.boolean().optional().describe("Whether to include the parsed HTML in the return for each body, excluded by default because they can be excessively large"), }, async (params) => { return handleTool(config, async (gmail: gmail_v1.Gmail) => { const { data } = await gmail.users.messages.list({ userId: 'me', ...params }) if (data.messages) { data.messages = data.messages.map((message: Message) => { if (message.payload) { message.payload = processMessagePart( message.payload, params.includeBodyHtml ) } return message }) } return formatResponse(data) }) }
- src/index.ts:50-66 (helper)Shared helper function 'handleTool' used by list_messages (and other tools) to handle OAuth2 authentication, credential validation, Gmail client creation, API call execution, and error handling.const handleTool = async (queryConfig: Record<string, any> | undefined, apiCall: (gmail: gmail_v1.Gmail) => Promise<any>) => { try { const oauth2Client = queryConfig ? createOAuth2Client(queryConfig) : defaultOAuth2Client if (!oauth2Client) throw new Error('OAuth2 client could not be created, please check your credentials') const credentialsAreValid = await validateCredentials(oauth2Client) if (!credentialsAreValid) throw new Error('OAuth2 credentials are invalid, please re-authenticate') const gmailClient = queryConfig ? google.gmail({ version: 'v1', auth: oauth2Client }) : defaultGmailClient if (!gmailClient) throw new Error('Gmail client could not be created, please check your credentials') const result = await apiCall(gmailClient) return result } catch (error: any) { return `Tool execution failed: ${error.message}` } }
- src/index.ts:80-94 (helper)Recursive helper 'processMessagePart' used in list_messages to decode base64 message bodies (text/plain and optionally html), filter headers to common ones, and process nested parts.const processMessagePart = (messagePart: MessagePart, includeBodyHtml = false): MessagePart => { if ((messagePart.mimeType !== 'text/html' || includeBodyHtml) && messagePart.body) { messagePart.body = decodedBody(messagePart.body) } if (messagePart.parts) { messagePart.parts = messagePart.parts.map(part => processMessagePart(part, includeBodyHtml)) } if (messagePart.headers) { messagePart.headers = messagePart.headers.filter(header => RESPONSE_HEADERS_LIST.includes(header.name || '')) } return messagePart }
- src/index.ts:48-49 (helper)Utility helper 'formatResponse' used by list_messages to wrap API response in MCP content format as JSON string.const formatResponse = (response: any) => ({ content: [{ type: "text", text: JSON.stringify(response) }] })