Skip to main content
Glama

gmail-read-emails

Retrieve and filter emails from Gmail using search queries, label IDs, and a customizable number of results. Integrates with the MCP Server Boilerplate for enhanced functionality.

Instructions

Read/list emails from Gmail with optional search query

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
labelIdsNoArray of label IDs to filter by
maxResultsNoMaximum number of emails to return
queryNoGmail search query (e.g., 'is:unread', 'from:example@gmail.com')

Implementation Reference

  • The main handler function for the 'gmail-read-emails' tool. It authenticates with Gmail API, lists messages based on query/label/maxResults, fetches metadata for each, formats into Markdown, and returns as text content.
    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) }`, }, ], }; } }
  • Zod schema defining input parameters for the readEmails 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/index.ts:191-198 (registration)
    Registration of the 'gmail-read-emails' tool on the MCP server, using readEmailsSchema and delegating to the readEmails handler.
    server.tool( "gmail-read-emails", "Read/list emails from Gmail with optional search query", readEmailsSchema.shape, async (params) => { return await readEmails(params); } );
  • Helper function to format the list of email details into a structured Markdown string 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; }
  • Helper function to create OAuth2 authentication client for Gmail API using environment variables.
    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; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CaptainCrouton89/maps-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server