hey_list_label_emails
List emails from a specific label with pagination. Use force_refresh to get fresh data bypassing cache.
Instructions
List emails with a specific label. Returns cached results unless force_refresh=true.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| label_id | Yes | The label/folder ID to list emails from | |
| limit | No | Maximum number of emails to return (default: 25) | |
| page | No | Page number for pagination (default: 1) | |
| force_refresh | No | Bypass cache and fetch fresh data (default: false) |
Implementation Reference
- src/index.ts:269-296 (registration)Tool definition/input schema registration for 'hey_list_label_emails' - defines the MCP tool metadata including name, description, readOnlyHint, openWorldHint, and inputSchema (requires label_id, optional limit/page/force_refresh).
{ name: "hey_list_label_emails", annotations: { readOnlyHint: true, openWorldHint: true }, description: "List emails with a specific label. Returns cached results unless force_refresh=true.", inputSchema: { type: "object" as const, properties: { label_id: { type: "string", description: "The label/folder ID to list emails from", }, limit: { type: "number", description: "Maximum number of emails to return (default: 25)", }, page: { type: "number", description: "Page number for pagination (default: 1)", }, force_refresh: { type: "boolean", description: "Bypass cache and fetch fresh data (default: false)", }, }, required: ["label_id"], }, }, - src/index.ts:1132-1150 (handler)Tool handler/dispatch for 'hey_list_label_emails' - validates label_id via validateId(), clamps limit/page, then calls listLabelEmails() with the label ID and options.
case "hey_list_label_emails": { const labelId = validateId(args?.label_id) const limit = clampNumber(args?.limit, 25, 1, 100) const page = clampNumber(args?.page, 1, 1, 1000) const forceRefresh = (args?.force_refresh as boolean) ?? false if (!labelId) { return { content: [ { type: "text", text: "Error: label_id is required and must be valid", }, ], isError: true, } } result = await listLabelEmails(labelId, { limit, page, forceRefresh }) break } - src/tools/read.ts:884-889 (handler)The actual implementation function listLabelEmails() - delegates to the generic listFolder() helper with cache key 'label_{labelId}' and fetches from '/folders/{labelId}'.
export async function listLabelEmails( labelId: string, options: ListOptions = {}, ): Promise<CachedResult<Email[]>> { return listFolder(`label_${labelId}`, `/folders/${labelId}`, options) } - src/tools/read.ts:677-713 (helper)The shared listFolder() helper function used by listLabelEmails - handles cache check, network fetch, email HTML parsing, and cache update logic.
async function listFolder( folder: string, path: string, options: ListOptions = {}, ): Promise<CachedResult<Email[]>> { const { limit = 25, page = 1, forceRefresh = false } = options // Check cache first (only for first page) if (!forceRefresh && page === 1 && !needsRefresh(folder)) { const cached = getCachedMessages(folder, limit) if (cached) { return { data: cached.messages, _cache: cached.metadata, } } } // Fetch from network const fullPath = page > 1 ? `${path}?page=${page}` : path const html = await heyClient.fetchHtml(fullPath) const emails = extractEmailsFromHtml(html).slice(0, limit) // Update cache (only for first page) if (page === 1) { cacheMessages(folder, emails) // Cache raw HTML for imbox (enables summary extraction without network) if (folder === "imbox") { cacheFolderHtml(folder, html) } } return { data: emails, _cache: createNetworkMetadata(), } } - src/index.ts:95-108 (schema)The validateId() helper used to validate the label_id parameter - ensures it's a 1-100 char alphanumeric string with hyphens/underscores.
function validateId(value: unknown): string | null { if (typeof value !== "string") { return null } const trimmed = value.trim() // IDs should be 1-100 chars, alphanumeric with hyphens/underscores if (trimmed.length === 0 || trimmed.length > 100) { return null } if (!/^[a-zA-Z0-9_-]+$/.test(trimmed)) { return null } return trimmed }