gmail-read-emails
Retrieve and list Gmail messages using search queries, label filters, and result limits to manage your email inbox efficiently.
Instructions
Read/list emails from Gmail with optional search query
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| labelIds | No | Array of label IDs to filter by | |
| maxResults | No | Maximum number of emails to return | |
| query | No | Gmail search query (e.g., 'is:unread', 'from:example@gmail.com') |
Input Schema (JSON Schema)
{
"properties": {
"labelIds": {
"description": "Array of label IDs to filter by",
"items": {
"type": "string"
},
"type": "array"
},
"maxResults": {
"default": 10,
"description": "Maximum number of emails to return",
"maximum": 100,
"minimum": 1,
"type": "number"
},
"query": {
"description": "Gmail search query (e.g., 'is:unread', 'from:example@gmail.com')",
"type": "string"
}
},
"type": "object"
}
Implementation Reference
- src/index.ts:191-198 (registration)Registration of the 'gmail-read-emails' tool in the MCP server, which calls the readEmails handler from gmail.jsserver.tool( "gmail-read-emails", "Read/list emails from Gmail with optional search query", readEmailsSchema.shape, async (params) => { return await readEmails(params); } );
- src/gmail.ts:214-290 (handler)The main handler function readEmails that lists and formats Gmail emails using the Google Gmail API, supports query and label filters, fetches metadata for details, and formats output as Markdown.export async function readEmails(params: z.infer<typeof readEmailsSchema>) { try { const auth = createGmailAuth(); const gmail = google.gmail({ version: "v1", auth }); const listParams: any = { userId: "me", maxResults: params.maxResults, }; if (params.query) listParams.q = params.query; if (params.labelIds) listParams.labelIds = params.labelIds; const response = await gmail.users.messages.list(listParams); if (!response.data.messages || response.data.messages.length === 0) { return { content: [ { type: "text" as const, text: "# No Emails Found\n\nNo emails found matching your search criteria.", }, ], }; } // Get detailed information for each message const emailDetails = await Promise.all( response.data.messages .slice(0, params.maxResults) .map(async (message) => { const detail = await gmail.users.messages.get({ userId: "me", id: message.id!, format: "metadata", metadataHeaders: ["From", "To", "Subject", "Date"], }); const headers = detail.data.payload?.headers || []; const getHeader = (name: string) => headers.find((h) => h.name?.toLowerCase() === name.toLowerCase()) ?.value || ""; return { id: message.id, threadId: message.threadId, from: getHeader("From"), to: getHeader("To"), subject: getHeader("Subject"), date: getHeader("Date"), snippet: detail.data.snippet, labelIds: detail.data.labelIds, }; }) ); return { content: [ { type: "text" as const, text: formatEmailListToMarkdown(emailDetails), }, ], }; } catch (error) { return { content: [ { type: "text" as const, text: `Error reading emails: ${ error instanceof Error ? error.message : String(error) }`, }, ], }; } }
- src/gmail.ts:13-30 (schema)Zod schema defining input parameters for the gmail-read-emails tool: optional query string, maxResults (1-100, default 10), optional labelIds array.export const readEmailsSchema = z.object({ query: z .string() .optional() .describe( "Gmail search query (e.g., 'is:unread', 'from:example@gmail.com')" ), maxResults: z .number() .min(1) .max(100) .default(10) .describe("Maximum number of emails to return"), labelIds: z .array(z.string()) .optional() .describe("Array of label IDs to filter by"), });
- src/gmail.ts:49-73 (helper)Helper function to format the list of email details into a Markdown table-like structure for the tool response.function formatEmailListToMarkdown(emails: any[]): string { if (!emails.length) return "No emails found."; let markdown = `# Inbox (${emails.length} emails)\n\n`; emails.forEach((email, index) => { const date = new Date(email.date).toLocaleDateString(); const from = email.from.replace(/[<>]/g, ''); const subject = email.subject || '(No Subject)'; const snippet = email.snippet || ''; markdown += `## ${index + 1}. ${subject}\n`; markdown += `From: ${from} \n`; markdown += `Date: ${date} \n`; markdown += `ID: \`${email.id}\`\n\n`; if (snippet) { markdown += `${snippet}\n\n`; } markdown += `---\n\n`; }); return markdown; }
- src/gmail.ts:134-165 (helper)OAuth2 authentication helper for Gmail API using environment variables for tokens.function createGmailAuth() { const clientId = process.env.GOOGLE_CLIENT_ID; const clientSecret = process.env.GOOGLE_CLIENT_SECRET; const redirectUri = process.env.GOOGLE_REDIRECT_URI || "http://localhost:3000/oauth2callback"; if (!clientId || !clientSecret) { throw new Error( "GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are required. Run oauth-setup.js to configure." ); } const oauth2Client = new google.auth.OAuth2( clientId, clientSecret, redirectUri ); const accessToken = process.env.GOOGLE_ACCESS_TOKEN; const refreshToken = process.env.GOOGLE_REFRESH_TOKEN; if (!accessToken || !refreshToken) { throw new Error("OAuth2 tokens missing. Run oauth-setup.js to get tokens."); } oauth2Client.setCredentials({ access_token: accessToken, refresh_token: refreshToken, }); return oauth2Client; }