Skip to main content
Glama

gmail-read-emails

Retrieve and list emails from Gmail accounts using search queries, label filters, and result limits for email management.

Instructions

Read/list emails from Gmail with optional search query

Input Schema

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

Implementation Reference

  • Main handler function that fetches emails from Gmail API using search query or labels, retrieves metadata, formats to markdown, and returns structured content or error.
    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 the input parameters for the gmail-read-emails tool: optional query, maxResults (default 10), optional labelIds.
    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)
    Registers the 'gmail-read-emails' tool on the MCP server using the readEmails handler and readEmailsSchema.
    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 create authenticated Gmail client using environment variables for OAuth2.
    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; }
  • Helper function to format the list of retrieved emails into a 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; }

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