@mcp-z/mcp-gmail 1.1.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/email/messages/fetch-message.d.cts +1 -1
- package/dist/cjs/email/messages/fetch-message.d.ts +1 -1
- package/dist/cjs/email/messages/fetch-message.js.map +1 -1
- package/dist/cjs/email/messages/messages.d.cts +1 -1
- package/dist/cjs/email/messages/messages.d.ts +1 -1
- package/dist/cjs/email/messages/messages.js.map +1 -1
- package/dist/cjs/email/parsing/html-processing.d.cts +1 -1
- package/dist/cjs/email/parsing/html-processing.d.ts +1 -1
- package/dist/cjs/email/parsing/html-processing.js.map +1 -1
- package/dist/cjs/email/querying/execute-query.d.cts +1 -1
- package/dist/cjs/email/querying/execute-query.d.ts +1 -1
- package/dist/cjs/email/querying/execute-query.js.map +1 -1
- package/dist/cjs/email/querying/pagination.d.cts +1 -1
- package/dist/cjs/email/querying/pagination.d.ts +1 -1
- package/dist/cjs/email/querying/pagination.js.map +1 -1
- package/dist/cjs/email/querying/search-execution.d.cts +1 -1
- package/dist/cjs/email/querying/search-execution.d.ts +1 -1
- package/dist/cjs/email/querying/search-execution.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/labels/gmail-labels.d.cts +1 -1
- package/dist/cjs/labels/gmail-labels.d.ts +1 -1
- package/dist/cjs/labels/gmail-labels.js.map +1 -1
- package/dist/cjs/lib/google-auth.d.cts +9 -0
- package/dist/cjs/lib/google-auth.d.ts +9 -0
- package/dist/cjs/lib/google-auth.js +16 -0
- package/dist/cjs/lib/google-auth.js.map +1 -0
- package/dist/cjs/mcp/prompts/draft-email.d.cts +2 -3
- package/dist/cjs/mcp/prompts/draft-email.d.ts +2 -3
- package/dist/cjs/mcp/prompts/draft-email.js.map +1 -1
- package/dist/cjs/mcp/prompts/query-syntax.d.cts +2 -3
- package/dist/cjs/mcp/prompts/query-syntax.d.ts +2 -3
- package/dist/cjs/mcp/prompts/query-syntax.js.map +1 -1
- package/dist/cjs/mcp/resources/email.d.cts +6 -5
- package/dist/cjs/mcp/resources/email.d.ts +6 -5
- package/dist/cjs/mcp/resources/email.js +6 -5
- package/dist/cjs/mcp/resources/email.js.map +1 -1
- package/dist/cjs/mcp/tools/categories-list.js +6 -5
- package/dist/cjs/mcp/tools/categories-list.js.map +1 -1
- package/dist/cjs/mcp/tools/label-add.js +7 -6
- package/dist/cjs/mcp/tools/label-add.js.map +1 -1
- package/dist/cjs/mcp/tools/label-delete.js +10 -9
- package/dist/cjs/mcp/tools/label-delete.js.map +1 -1
- package/dist/cjs/mcp/tools/labels-list.d.cts +3 -3
- package/dist/cjs/mcp/tools/labels-list.d.ts +3 -3
- package/dist/cjs/mcp/tools/labels-list.js +6 -5
- package/dist/cjs/mcp/tools/labels-list.js.map +1 -1
- package/dist/cjs/mcp/tools/message-get.js +7 -7
- package/dist/cjs/mcp/tools/message-get.js.map +1 -1
- package/dist/cjs/mcp/tools/message-mark-read.js +7 -6
- package/dist/cjs/mcp/tools/message-mark-read.js.map +1 -1
- package/dist/cjs/mcp/tools/message-move-to-trash.js +10 -9
- package/dist/cjs/mcp/tools/message-move-to-trash.js.map +1 -1
- package/dist/cjs/mcp/tools/message-respond.js +8 -7
- package/dist/cjs/mcp/tools/message-respond.js.map +1 -1
- package/dist/cjs/mcp/tools/message-search.js +6 -6
- package/dist/cjs/mcp/tools/message-search.js.map +1 -1
- package/dist/cjs/mcp/tools/message-send.js +7 -6
- package/dist/cjs/mcp/tools/message-send.js.map +1 -1
- package/dist/cjs/mcp/tools/messages-export-csv.js +5 -5
- package/dist/cjs/mcp/tools/messages-export-csv.js.map +1 -1
- package/dist/cjs/setup/http.d.cts +0 -2
- package/dist/cjs/setup/http.d.ts +0 -2
- package/dist/cjs/setup/http.js +18 -11
- package/dist/cjs/setup/http.js.map +1 -1
- package/dist/cjs/setup/stdio.d.cts +0 -2
- package/dist/cjs/setup/stdio.d.ts +0 -2
- package/dist/cjs/setup/stdio.js +18 -11
- package/dist/cjs/setup/stdio.js.map +1 -1
- package/dist/esm/email/messages/fetch-message.d.ts +1 -1
- package/dist/esm/email/messages/fetch-message.js.map +1 -1
- package/dist/esm/email/messages/messages.d.ts +1 -1
- package/dist/esm/email/messages/messages.js.map +1 -1
- package/dist/esm/email/parsing/html-processing.d.ts +1 -1
- package/dist/esm/email/parsing/html-processing.js.map +1 -1
- package/dist/esm/email/querying/execute-query.d.ts +1 -1
- package/dist/esm/email/querying/execute-query.js.map +1 -1
- package/dist/esm/email/querying/pagination.d.ts +1 -1
- package/dist/esm/email/querying/pagination.js.map +1 -1
- package/dist/esm/email/querying/search-execution.d.ts +1 -1
- package/dist/esm/email/querying/search-execution.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/labels/gmail-labels.d.ts +1 -1
- package/dist/esm/labels/gmail-labels.js.map +1 -1
- package/dist/esm/lib/google-auth.d.ts +9 -0
- package/dist/esm/lib/google-auth.js +11 -0
- package/dist/esm/lib/google-auth.js.map +1 -0
- package/dist/esm/mcp/prompts/draft-email.d.ts +2 -3
- package/dist/esm/mcp/prompts/draft-email.js.map +1 -1
- package/dist/esm/mcp/prompts/query-syntax.d.ts +2 -3
- package/dist/esm/mcp/prompts/query-syntax.js.map +1 -1
- package/dist/esm/mcp/resources/email.d.ts +6 -5
- package/dist/esm/mcp/resources/email.js +5 -4
- package/dist/esm/mcp/resources/email.js.map +1 -1
- package/dist/esm/mcp/tools/categories-list.js +6 -5
- package/dist/esm/mcp/tools/categories-list.js.map +1 -1
- package/dist/esm/mcp/tools/label-add.js +7 -6
- package/dist/esm/mcp/tools/label-add.js.map +1 -1
- package/dist/esm/mcp/tools/label-delete.js +10 -9
- package/dist/esm/mcp/tools/label-delete.js.map +1 -1
- package/dist/esm/mcp/tools/labels-list.d.ts +3 -3
- package/dist/esm/mcp/tools/labels-list.js +6 -5
- package/dist/esm/mcp/tools/labels-list.js.map +1 -1
- package/dist/esm/mcp/tools/message-get.js +8 -8
- package/dist/esm/mcp/tools/message-get.js.map +1 -1
- package/dist/esm/mcp/tools/message-mark-read.js +7 -6
- package/dist/esm/mcp/tools/message-mark-read.js.map +1 -1
- package/dist/esm/mcp/tools/message-move-to-trash.js +10 -9
- package/dist/esm/mcp/tools/message-move-to-trash.js.map +1 -1
- package/dist/esm/mcp/tools/message-respond.js +8 -7
- package/dist/esm/mcp/tools/message-respond.js.map +1 -1
- package/dist/esm/mcp/tools/message-search.js +6 -5
- package/dist/esm/mcp/tools/message-search.js.map +1 -1
- package/dist/esm/mcp/tools/message-send.js +7 -6
- package/dist/esm/mcp/tools/message-send.js.map +1 -1
- package/dist/esm/mcp/tools/messages-export-csv.js +6 -6
- package/dist/esm/mcp/tools/messages-export-csv.js.map +1 -1
- package/dist/esm/setup/http.d.ts +0 -2
- package/dist/esm/setup/http.js +18 -11
- package/dist/esm/setup/http.js.map +1 -1
- package/dist/esm/setup/stdio.d.ts +0 -2
- package/dist/esm/setup/stdio.js +18 -11
- package/dist/esm/setup/stdio.js.map +1 -1
- package/package.json +8 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/email/querying/pagination.ts"],"sourcesContent":["/** Gmail pagination helpers for single-page operations. */\n\nimport type { gmail_v1 } from 'googleapis';\nimport type { Logger } from '../../types.ts';\n\nexport interface SinglePageResult {\n readonly messages: gmail_v1.Schema$Message[];\n readonly nextPageToken: string | undefined;\n}\n\n/**\n * Fetch a single page of messages from Gmail\n */\nexport interface FetchMessagesPageParams {\n readonly gmailQ: string;\n readonly pageSize?: number;\n readonly pageToken: string | undefined;\n readonly body?: boolean;\n readonly logger: Logger;\n readonly metadataHeaders?: readonly string[];\n}\n\nexport async function fetchMessagesPage(gmail: gmail_v1.Gmail, params: FetchMessagesPageParams): Promise<SinglePageResult> {\n const { gmailQ, pageSize = 50, pageToken, body = false, logger, metadataHeaders } = params;\n\n // Secure resource bounds checking - prevent security bypasses\n const maxPageSize = 500; // Gmail API maximum - enforced for security\n const minPageSize = 1; // Minimum valid page size\n\n // Validate input is a positive number to prevent bypass attempts\n if (!Number.isInteger(pageSize) || pageSize < 0) {\n throw new Error(`Invalid pageSize: must be a positive integer, got ${pageSize}`);\n }\n\n const safePageSize = Math.min(Math.max(minPageSize, pageSize), maxPageSize);\n\n if (pageSize !== safePageSize && logger) {\n logger.info('Page size bounded for API safety', { requested: pageSize, applied: safePageSize });\n // No fallback to console - would corrupt MCP stdio communication\n }\n\n try {\n const listParams = {\n userId: 'me',\n q: gmailQ,\n maxResults: safePageSize,\n };\n const listResponse = pageToken && pageToken.trim().length > 0 ? await gmail.users.messages.list({ ...listParams, pageToken }) : await gmail.users.messages.list(listParams);\n const response = listResponse.data;\n const messages = response.messages || [];\n\n if (messages.length === 0) {\n if (logger) logger.info('No messages found on page');\n return { messages: [], nextPageToken: undefined };\n }\n\n const items = messages.map((m: gmail_v1.Schema$Message) => m.id).filter(Boolean) as string[];\n if (items.length === 0) {\n if (logger) logger.info('No valid message ids on page');\n return { messages: [], nextPageToken: response.nextPageToken && response.nextPageToken.trim().length > 0 ? response.nextPageToken : undefined };\n }\n\n const concurrentArgs: FetchMessagesConcurrentlyParams = {\n items,\n concurrency: 5,\n body,\n ...(logger && { logger }),\n ...(metadataHeaders && { metadataHeaders }),\n };\n const detailedMessages = await fetchMessagesConcurrently(gmail, concurrentArgs);\n\n if (logger) logger.info(`Fetched page with ${detailedMessages.length} messages`);\n return {\n messages: detailedMessages,\n nextPageToken: response.nextPageToken && response.nextPageToken.trim().length > 0 ? response.nextPageToken : undefined,\n };\n } catch (error) {\n // Standardized error handling for pagination pipeline\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (logger)\n logger.error('Gmail pagination: single page fetch failed', {\n error: errorMessage,\n query: gmailQ,\n pageSize: safePageSize,\n hasPageToken: !!pageToken,\n });\n\n // Preserve original error type for upstream handling\n if (error instanceof Error) {\n // Enhance error with pagination context\n error.message = `Gmail pagination fetch failed: ${error.message}`;\n throw error;\n }\n\n // Convert non-Error objects to proper Error instances\n throw new Error(`Gmail pagination fetch failed: ${errorMessage}`);\n }\n}\n\nexport interface FetchMessagesConcurrentlyParams {\n readonly items: readonly string[];\n readonly concurrency?: number;\n readonly body?: boolean;\n readonly logger: Logger;\n readonly metadataHeaders?: readonly string[];\n}\n\nexport async function fetchMessagesConcurrently(gmail: gmail_v1.Gmail, params: FetchMessagesConcurrentlyParams): Promise<gmail_v1.Schema$Message[]> {\n const { items, concurrency = 2, body = false, logger, metadataHeaders } = params;\n\n // Secure resource bounds checking for concurrent operations\n const maxConcurrency = 10; // Conservative limit to prevent rate limiting and resource exhaustion\n const minConcurrency = 1; // Minimum valid concurrency\n\n // Validate input is a positive number to prevent bypass attempts\n if (!Number.isInteger(concurrency) || concurrency < 0) {\n throw new Error(`Invalid concurrency: must be a positive integer, got ${concurrency}`);\n }\n\n const safeConcurrency = Math.min(Math.max(minConcurrency, concurrency), maxConcurrency);\n\n if (concurrency !== safeConcurrency && logger) {\n logger.info('Concurrency bounded for API safety', { requested: concurrency, applied: safeConcurrency });\n // No fallback to console - would corrupt MCP stdio communication\n }\n\n if (items.length === 0) return [];\n\n const results: (gmail_v1.Schema$Message | null)[] = new Array(items.length);\n const format = body ? 'full' : 'metadata';\n // Always pass metadataHeaders if provided - body doesn't replace headers, it's additional content\n const metadataHeadersForRequest = metadataHeaders;\n\n // Pre-build request parameters to avoid repeated object creation\n const requestParams = items.map((id) => {\n const baseParams = {\n userId: 'me' as const,\n id,\n format,\n };\n // Only include metadataHeaders if defined (exactOptionalPropertyTypes compliance)\n return metadataHeadersForRequest ? { ...baseParams, metadataHeaders: [...metadataHeadersForRequest] } : baseParams;\n });\n\n // Optimize concurrent processing using batching\n const batchSize = safeConcurrency;\n const batches: (typeof requestParams)[] = [];\n for (let i = 0; i < requestParams.length; i += batchSize) {\n batches.push(requestParams.slice(i, i + batchSize));\n }\n\n let processedCount = 0;\n for (const batch of batches) {\n const batchPromises = batch.map(async (params, batchIndex) => {\n try {\n const messageResponse = await gmail.users.messages.get(params);\n const globalIndex = processedCount + batchIndex;\n results[globalIndex] = messageResponse.data;\n return messageResponse.data;\n } catch (error) {\n // Log individual message fetch failures but continue processing\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (logger)\n logger.info('Gmail pagination: individual message fetch failed, continuing', {\n error: errorMessage,\n messageId: params.id,\n globalIndex: processedCount + batchIndex,\n });\n return null; // Mark as failed but continue\n }\n });\n\n await Promise.all(batchPromises);\n processedCount += batch.length;\n\n // Progress logging for large batches\n if (items.length > 20) {\n if (logger) logger.info(`Gmail pagination: processed ${processedCount}/${items.length} messages`);\n }\n }\n\n // Filter out any null results from failed individual fetches\n return results.filter((result) => result !== null && result !== undefined);\n}\n"],"names":["fetchMessagesPage","gmail","params","gmailQ","pageSize","pageToken","body","logger","metadataHeaders","maxPageSize","minPageSize","Number","isInteger","Error","safePageSize","Math","min","max","info","requested","applied","listParams","userId","q","maxResults","listResponse","trim","length","users","messages","list","response","data","nextPageToken","undefined","items","map","m","id","filter","Boolean","concurrentArgs","concurrency","detailedMessages","fetchMessagesConcurrently","error","errorMessage","message","String","query","hasPageToken","maxConcurrency","minConcurrency","safeConcurrency","results","Array","format","metadataHeadersForRequest","requestParams","baseParams","batchSize","batches","i","push","slice","processedCount","batch","batchPromises","batchIndex","messageResponse","get","globalIndex","messageId","Promise","all","result"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/email/querying/pagination.ts"],"sourcesContent":["/** Gmail pagination helpers for single-page operations. */\n\nimport type { gmail_v1 } from '@googleapis/gmail';\nimport type { Logger } from '../../types.ts';\n\nexport interface SinglePageResult {\n readonly messages: gmail_v1.Schema$Message[];\n readonly nextPageToken: string | undefined;\n}\n\n/**\n * Fetch a single page of messages from Gmail\n */\nexport interface FetchMessagesPageParams {\n readonly gmailQ: string;\n readonly pageSize?: number;\n readonly pageToken: string | undefined;\n readonly body?: boolean;\n readonly logger: Logger;\n readonly metadataHeaders?: readonly string[];\n}\n\nexport async function fetchMessagesPage(gmail: gmail_v1.Gmail, params: FetchMessagesPageParams): Promise<SinglePageResult> {\n const { gmailQ, pageSize = 50, pageToken, body = false, logger, metadataHeaders } = params;\n\n // Secure resource bounds checking - prevent security bypasses\n const maxPageSize = 500; // Gmail API maximum - enforced for security\n const minPageSize = 1; // Minimum valid page size\n\n // Validate input is a positive number to prevent bypass attempts\n if (!Number.isInteger(pageSize) || pageSize < 0) {\n throw new Error(`Invalid pageSize: must be a positive integer, got ${pageSize}`);\n }\n\n const safePageSize = Math.min(Math.max(minPageSize, pageSize), maxPageSize);\n\n if (pageSize !== safePageSize && logger) {\n logger.info('Page size bounded for API safety', { requested: pageSize, applied: safePageSize });\n // No fallback to console - would corrupt MCP stdio communication\n }\n\n try {\n const listParams = {\n userId: 'me',\n q: gmailQ,\n maxResults: safePageSize,\n };\n const listResponse = pageToken && pageToken.trim().length > 0 ? await gmail.users.messages.list({ ...listParams, pageToken }) : await gmail.users.messages.list(listParams);\n const response = listResponse.data;\n const messages = response.messages || [];\n\n if (messages.length === 0) {\n if (logger) logger.info('No messages found on page');\n return { messages: [], nextPageToken: undefined };\n }\n\n const items = messages.map((m: gmail_v1.Schema$Message) => m.id).filter(Boolean) as string[];\n if (items.length === 0) {\n if (logger) logger.info('No valid message ids on page');\n return { messages: [], nextPageToken: response.nextPageToken && response.nextPageToken.trim().length > 0 ? response.nextPageToken : undefined };\n }\n\n const concurrentArgs: FetchMessagesConcurrentlyParams = {\n items,\n concurrency: 5,\n body,\n ...(logger && { logger }),\n ...(metadataHeaders && { metadataHeaders }),\n };\n const detailedMessages = await fetchMessagesConcurrently(gmail, concurrentArgs);\n\n if (logger) logger.info(`Fetched page with ${detailedMessages.length} messages`);\n return {\n messages: detailedMessages,\n nextPageToken: response.nextPageToken && response.nextPageToken.trim().length > 0 ? response.nextPageToken : undefined,\n };\n } catch (error) {\n // Standardized error handling for pagination pipeline\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (logger)\n logger.error('Gmail pagination: single page fetch failed', {\n error: errorMessage,\n query: gmailQ,\n pageSize: safePageSize,\n hasPageToken: !!pageToken,\n });\n\n // Preserve original error type for upstream handling\n if (error instanceof Error) {\n // Enhance error with pagination context\n error.message = `Gmail pagination fetch failed: ${error.message}`;\n throw error;\n }\n\n // Convert non-Error objects to proper Error instances\n throw new Error(`Gmail pagination fetch failed: ${errorMessage}`);\n }\n}\n\nexport interface FetchMessagesConcurrentlyParams {\n readonly items: readonly string[];\n readonly concurrency?: number;\n readonly body?: boolean;\n readonly logger: Logger;\n readonly metadataHeaders?: readonly string[];\n}\n\nexport async function fetchMessagesConcurrently(gmail: gmail_v1.Gmail, params: FetchMessagesConcurrentlyParams): Promise<gmail_v1.Schema$Message[]> {\n const { items, concurrency = 2, body = false, logger, metadataHeaders } = params;\n\n // Secure resource bounds checking for concurrent operations\n const maxConcurrency = 10; // Conservative limit to prevent rate limiting and resource exhaustion\n const minConcurrency = 1; // Minimum valid concurrency\n\n // Validate input is a positive number to prevent bypass attempts\n if (!Number.isInteger(concurrency) || concurrency < 0) {\n throw new Error(`Invalid concurrency: must be a positive integer, got ${concurrency}`);\n }\n\n const safeConcurrency = Math.min(Math.max(minConcurrency, concurrency), maxConcurrency);\n\n if (concurrency !== safeConcurrency && logger) {\n logger.info('Concurrency bounded for API safety', { requested: concurrency, applied: safeConcurrency });\n // No fallback to console - would corrupt MCP stdio communication\n }\n\n if (items.length === 0) return [];\n\n const results: (gmail_v1.Schema$Message | null)[] = new Array(items.length);\n const format = body ? 'full' : 'metadata';\n // Always pass metadataHeaders if provided - body doesn't replace headers, it's additional content\n const metadataHeadersForRequest = metadataHeaders;\n\n // Pre-build request parameters to avoid repeated object creation\n const requestParams = items.map((id) => {\n const baseParams = {\n userId: 'me' as const,\n id,\n format,\n };\n // Only include metadataHeaders if defined (exactOptionalPropertyTypes compliance)\n return metadataHeadersForRequest ? { ...baseParams, metadataHeaders: [...metadataHeadersForRequest] } : baseParams;\n });\n\n // Optimize concurrent processing using batching\n const batchSize = safeConcurrency;\n const batches: (typeof requestParams)[] = [];\n for (let i = 0; i < requestParams.length; i += batchSize) {\n batches.push(requestParams.slice(i, i + batchSize));\n }\n\n let processedCount = 0;\n for (const batch of batches) {\n const batchPromises = batch.map(async (params, batchIndex) => {\n try {\n const messageResponse = await gmail.users.messages.get(params);\n const globalIndex = processedCount + batchIndex;\n results[globalIndex] = messageResponse.data;\n return messageResponse.data;\n } catch (error) {\n // Log individual message fetch failures but continue processing\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (logger)\n logger.info('Gmail pagination: individual message fetch failed, continuing', {\n error: errorMessage,\n messageId: params.id,\n globalIndex: processedCount + batchIndex,\n });\n return null; // Mark as failed but continue\n }\n });\n\n await Promise.all(batchPromises);\n processedCount += batch.length;\n\n // Progress logging for large batches\n if (items.length > 20) {\n if (logger) logger.info(`Gmail pagination: processed ${processedCount}/${items.length} messages`);\n }\n }\n\n // Filter out any null results from failed individual fetches\n return results.filter((result) => result !== null && result !== undefined);\n}\n"],"names":["fetchMessagesPage","gmail","params","gmailQ","pageSize","pageToken","body","logger","metadataHeaders","maxPageSize","minPageSize","Number","isInteger","Error","safePageSize","Math","min","max","info","requested","applied","listParams","userId","q","maxResults","listResponse","trim","length","users","messages","list","response","data","nextPageToken","undefined","items","map","m","id","filter","Boolean","concurrentArgs","concurrency","detailedMessages","fetchMessagesConcurrently","error","errorMessage","message","String","query","hasPageToken","maxConcurrency","minConcurrency","safeConcurrency","results","Array","format","metadataHeadersForRequest","requestParams","baseParams","batchSize","batches","i","push","slice","processedCount","batch","batchPromises","batchIndex","messageResponse","get","globalIndex","messageId","Promise","all","result"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/email/querying/search-execution.ts"],"sourcesContent":["import type { gmail_v1 } from 'googleapis';\nimport type { GmailQuery as QueryNode } from '../../schemas/gmail-query-schema.ts';\nimport type { Logger } from '../../types.ts';\nimport { type FetchMessagesPageParams, fetchMessagesPage } from './pagination.ts';\nimport { toGmailQuery } from './query-builder.ts';\n\nexport interface GmailSearchOptions {\n readonly query?: QueryNode;\n readonly pageSize?: number;\n readonly includeBody?: boolean;\n readonly pageToken: string | undefined; // For pagination support - explicit undefined allowed\n readonly logger: Logger;\n}\n\nexport interface GmailEmailSummary {\n readonly id: string;\n readonly provider: 'gmail';\n readonly threadId?: string;\n readonly date?: string;\n readonly from?: string;\n readonly fromName?: string;\n readonly to?: string;\n readonly cc?: string;\n readonly bcc?: string;\n readonly subject?: string;\n readonly snippet?: string;\n readonly body?: string;\n}\n\nfunction buildGmailQ(query: QueryNode | undefined): string {\n if (!query) return '';\n const emitted = toGmailQuery(query);\n return emitted?.q ?? '';\n}\n\nexport interface GmailSearchResult {\n readonly messages: gmail_v1.Schema$Message[]; // Raw Gmail API messages for transformation by caller\n readonly nextPageToken: string | undefined;\n}\n\nexport async function searchMessages(gmail: gmail_v1.Gmail, opts: GmailSearchOptions): Promise<GmailSearchResult> {\n const { query, pageSize = 50, includeBody = false, pageToken, logger } = opts;\n const gmailQ = buildGmailQ(query);\n const metadataHeaders = ['Date', 'Subject', 'From', 'To', 'Cc', 'Bcc'];\n // Always fetch metadata headers - body is additional content, not a replacement for headers\n const pageParams: FetchMessagesPageParams = {\n gmailQ,\n pageSize,\n body: includeBody,\n metadataHeaders,\n pageToken,\n logger,\n };\n const result = await fetchMessagesPage(gmail, pageParams);\n\n // Return raw Gmail messages - transformation happens in caller\n return {\n messages: result.messages,\n nextPageToken: result.nextPageToken,\n };\n}\n"],"names":["fetchMessagesPage","toGmailQuery","buildGmailQ","query","emitted","q","searchMessages","gmail","opts","pageSize","includeBody","pageToken","logger","gmailQ","metadataHeaders","pageParams","body","result","messages","nextPageToken"],"mappings":"AAGA,SAAuCA,iBAAiB,QAAQ,kBAAkB;AAClF,SAASC,YAAY,QAAQ,qBAAqB;AAyBlD,SAASC,YAAYC,KAA4B;;IAC/C,IAAI,CAACA,OAAO,OAAO;IACnB,MAAMC,UAAUH,aAAaE;IAC7B,eAAOC,oBAAAA,8BAAAA,QAASC,CAAC,uCAAI;AACvB;AAOA,OAAO,eAAeC,eAAeC,KAAqB,EAAEC,IAAwB;IAClF,MAAM,EAAEL,KAAK,EAAEM,WAAW,EAAE,EAAEC,cAAc,KAAK,EAAEC,SAAS,EAAEC,MAAM,EAAE,GAAGJ;IACzE,MAAMK,SAASX,YAAYC;IAC3B,MAAMW,kBAAkB;QAAC;QAAQ;QAAW;QAAQ;QAAM;QAAM;KAAM;IACtE,4FAA4F;IAC5F,MAAMC,aAAsC;QAC1CF;QACAJ;QACAO,MAAMN;QACNI;QACAH;QACAC;IACF;IACA,MAAMK,SAAS,MAAMjB,kBAAkBO,OAAOQ;IAE9C,+DAA+D;IAC/D,OAAO;QACLG,UAAUD,OAAOC,QAAQ;QACzBC,eAAeF,OAAOE,aAAa;IACrC;AACF"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/email/querying/search-execution.ts"],"sourcesContent":["import type { gmail_v1 } from '@googleapis/gmail';\nimport type { GmailQuery as QueryNode } from '../../schemas/gmail-query-schema.ts';\nimport type { Logger } from '../../types.ts';\nimport { type FetchMessagesPageParams, fetchMessagesPage } from './pagination.ts';\nimport { toGmailQuery } from './query-builder.ts';\n\nexport interface GmailSearchOptions {\n readonly query?: QueryNode;\n readonly pageSize?: number;\n readonly includeBody?: boolean;\n readonly pageToken: string | undefined; // For pagination support - explicit undefined allowed\n readonly logger: Logger;\n}\n\nexport interface GmailEmailSummary {\n readonly id: string;\n readonly provider: 'gmail';\n readonly threadId?: string;\n readonly date?: string;\n readonly from?: string;\n readonly fromName?: string;\n readonly to?: string;\n readonly cc?: string;\n readonly bcc?: string;\n readonly subject?: string;\n readonly snippet?: string;\n readonly body?: string;\n}\n\nfunction buildGmailQ(query: QueryNode | undefined): string {\n if (!query) return '';\n const emitted = toGmailQuery(query);\n return emitted?.q ?? '';\n}\n\nexport interface GmailSearchResult {\n readonly messages: gmail_v1.Schema$Message[]; // Raw Gmail API messages for transformation by caller\n readonly nextPageToken: string | undefined;\n}\n\nexport async function searchMessages(gmail: gmail_v1.Gmail, opts: GmailSearchOptions): Promise<GmailSearchResult> {\n const { query, pageSize = 50, includeBody = false, pageToken, logger } = opts;\n const gmailQ = buildGmailQ(query);\n const metadataHeaders = ['Date', 'Subject', 'From', 'To', 'Cc', 'Bcc'];\n // Always fetch metadata headers - body is additional content, not a replacement for headers\n const pageParams: FetchMessagesPageParams = {\n gmailQ,\n pageSize,\n body: includeBody,\n metadataHeaders,\n pageToken,\n logger,\n };\n const result = await fetchMessagesPage(gmail, pageParams);\n\n // Return raw Gmail messages - transformation happens in caller\n return {\n messages: result.messages,\n nextPageToken: result.nextPageToken,\n };\n}\n"],"names":["fetchMessagesPage","toGmailQuery","buildGmailQ","query","emitted","q","searchMessages","gmail","opts","pageSize","includeBody","pageToken","logger","gmailQ","metadataHeaders","pageParams","body","result","messages","nextPageToken"],"mappings":"AAGA,SAAuCA,iBAAiB,QAAQ,kBAAkB;AAClF,SAASC,YAAY,QAAQ,qBAAqB;AAyBlD,SAASC,YAAYC,KAA4B;;IAC/C,IAAI,CAACA,OAAO,OAAO;IACnB,MAAMC,UAAUH,aAAaE;IAC7B,eAAOC,oBAAAA,8BAAAA,QAASC,CAAC,uCAAI;AACvB;AAOA,OAAO,eAAeC,eAAeC,KAAqB,EAAEC,IAAwB;IAClF,MAAM,EAAEL,KAAK,EAAEM,WAAW,EAAE,EAAEC,cAAc,KAAK,EAAEC,SAAS,EAAEC,MAAM,EAAE,GAAGJ;IACzE,MAAMK,SAASX,YAAYC;IAC3B,MAAMW,kBAAkB;QAAC;QAAQ;QAAW;QAAQ;QAAM;QAAM;KAAM;IACtE,4FAA4F;IAC5F,MAAMC,aAAsC;QAC1CF;QACAJ;QACAO,MAAMN;QACNI;QACAH;QACAC;IACF;IACA,MAAMK,SAAS,MAAMjB,kBAAkBO,OAAOQ;IAE9C,+DAA+D;IAC/D,OAAO;QACLG,UAAUD,OAAOC,QAAQ;QACzBC,eAAeF,OAAOE,aAAa;IACrC;AACF"}
|
package/dist/esm/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import * as _setup from './setup/index.js';
|
|
|
10
10
|
export { _setup as setup };
|
|
11
11
|
export * from './types.js';
|
|
12
12
|
export async function startServer(config) {
|
|
13
|
-
// createHTTPServer/createStdioServer pull in @
|
|
13
|
+
// createHTTPServer/createStdioServer pull in @mcp-z/server and every mcp/tools/*.ts
|
|
14
14
|
// (googleapis included); deferred so a --version/--help run never reaches them.
|
|
15
15
|
const { createHTTPServer } = await import('./setup/http.js');
|
|
16
16
|
const { createStdioServer } = await import('./setup/stdio.js');
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/index.ts"],"sourcesContent":["import { handleVersionHelp } from './setup/version-help.ts';\nimport type { ServerConfig } from './types.ts';\n\nexport { GOOGLE_SCOPE } from './constants.ts';\nexport * as mcp from './mcp/index.ts';\n// Export types and schemas for documentation\nexport type { Input as CategoriesListInput } from './mcp/tools/categories-list.ts';\nexport { inputSchema as CategoriesListInputSchema } from './mcp/tools/categories-list.ts';\nexport type { Input as LabelsListInput } from './mcp/tools/labels-list.ts';\nexport { inputSchema as LabelsListInputSchema } from './mcp/tools/labels-list.ts';\nexport * as schemas from './schemas/index.ts';\nexport * as setup from './setup/index.ts';\nexport * from './types.ts';\n\nexport async function startServer(config: ServerConfig): Promise<void> {\n // createHTTPServer/createStdioServer pull in @
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/index.ts"],"sourcesContent":["import { handleVersionHelp } from './setup/version-help.ts';\nimport type { ServerConfig } from './types.ts';\n\nexport { GOOGLE_SCOPE } from './constants.ts';\nexport * as mcp from './mcp/index.ts';\n// Export types and schemas for documentation\nexport type { Input as CategoriesListInput } from './mcp/tools/categories-list.ts';\nexport { inputSchema as CategoriesListInputSchema } from './mcp/tools/categories-list.ts';\nexport type { Input as LabelsListInput } from './mcp/tools/labels-list.ts';\nexport { inputSchema as LabelsListInputSchema } from './mcp/tools/labels-list.ts';\nexport * as schemas from './schemas/index.ts';\nexport * as setup from './setup/index.ts';\nexport * from './types.ts';\n\nexport async function startServer(config: ServerConfig): Promise<void> {\n // createHTTPServer/createStdioServer pull in @mcp-z/server and every mcp/tools/*.ts\n // (googleapis included); deferred so a --version/--help run never reaches them.\n const { createHTTPServer } = await import('./setup/http.ts');\n const { createStdioServer } = await import('./setup/stdio.ts');\n const { logger, close } = config.transport.type === 'stdio' ? await createStdioServer(config) : await createHTTPServer(config);\n\n process.on('SIGINT', async () => {\n await close();\n process.exit(0);\n });\n\n logger.info(`Server started with ${config.transport.type} transport`);\n await new Promise(() => {});\n}\n\nexport default async function main(): Promise<void> {\n // Check for help/version flags FIRST, before config parsing\n const versionHelpResult = handleVersionHelp(process.argv);\n if (versionHelpResult.handled) {\n console.log(versionHelpResult.output);\n process.exit(0);\n }\n\n // Only parse config if no help/version flags. config.ts's own heavy imports (@mcp-z/oauth-google,\n // @mcp-z/server) are deferred internally, so this static-looking call stays cheap until here.\n const { createConfig } = await import('./setup/config.ts');\n const config = createConfig();\n await startServer(config);\n}\n\nif (process.argv[1] === new URL(import.meta.url).pathname) {\n main();\n}\n"],"names":["handleVersionHelp","GOOGLE_SCOPE","mcp","inputSchema","CategoriesListInputSchema","LabelsListInputSchema","schemas","setup","startServer","config","createHTTPServer","createStdioServer","logger","close","transport","type","process","on","exit","info","Promise","main","versionHelpResult","argv","handled","console","log","output","createConfig","URL","url","pathname"],"mappings":"AAAA,SAASA,iBAAiB,QAAQ,0BAA0B;AAG5D,SAASC,YAAY,QAAQ,iBAAiB;AAC9C,sBAAqB,iBAAiB;AAAtC,SAAO,QAAKC,GAAG,GAAuB;AAGtC,SAASC,eAAeC,yBAAyB,QAAQ,iCAAiC;AAE1F,SAASD,eAAeE,qBAAqB,QAAQ,6BAA6B;AAClF,0BAAyB,qBAAqB;AAA9C,SAAO,YAAKC,OAAO,GAA2B;AAC9C,wBAAuB,mBAAmB;AAA1C,SAAO,UAAKC,KAAK,GAAyB;AAC1C,cAAc,aAAa;AAE3B,OAAO,eAAeC,YAAYC,MAAoB;IACpD,oFAAoF;IACpF,gFAAgF;IAChF,MAAM,EAAEC,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC;IAC1C,MAAM,EAAEC,iBAAiB,EAAE,GAAG,MAAM,MAAM,CAAC;IAC3C,MAAM,EAAEC,MAAM,EAAEC,KAAK,EAAE,GAAGJ,OAAOK,SAAS,CAACC,IAAI,KAAK,UAAU,MAAMJ,kBAAkBF,UAAU,MAAMC,iBAAiBD;IAEvHO,QAAQC,EAAE,CAAC,UAAU;QACnB,MAAMJ;QACNG,QAAQE,IAAI,CAAC;IACf;IAEAN,OAAOO,IAAI,CAAC,CAAC,oBAAoB,EAAEV,OAAOK,SAAS,CAACC,IAAI,CAAC,UAAU,CAAC;IACpE,MAAM,IAAIK,QAAQ,KAAO;AAC3B;AAEA,eAAe,eAAeC;IAC5B,4DAA4D;IAC5D,MAAMC,oBAAoBtB,kBAAkBgB,QAAQO,IAAI;IACxD,IAAID,kBAAkBE,OAAO,EAAE;QAC7BC,QAAQC,GAAG,CAACJ,kBAAkBK,MAAM;QACpCX,QAAQE,IAAI,CAAC;IACf;IAEA,kGAAkG;IAClG,8FAA8F;IAC9F,MAAM,EAAEU,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC;IACtC,MAAMnB,SAASmB;IACf,MAAMpB,YAAYC;AACpB;AAEA,IAAIO,QAAQO,IAAI,CAAC,EAAE,KAAK,IAAIM,IAAI,YAAYC,GAAG,EAAEC,QAAQ,EAAE;IACzDV;AACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { gmail_v1 } from 'googleapis';
|
|
1
|
+
import type { gmail_v1 } from '@googleapis/gmail';
|
|
2
2
|
export declare function ensureLabelId(gmail: gmail_v1.Gmail, userId: string, labelName: string): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/labels/gmail-labels.ts"],"sourcesContent":["import type { gmail_v1 } from 'googleapis';\n\nexport async function ensureLabelId(gmail: gmail_v1.Gmail, userId: string, labelName: string): Promise<string> {\n // Built-in system labels: pass through by name\n const builtInLabels: Record<string, string> = {\n INBOX: 'INBOX',\n SPAM: 'SPAM',\n TRASH: 'TRASH',\n UNREAD: 'UNREAD',\n STARRED: 'STARRED',\n IMPORTANT: 'IMPORTANT',\n SENT: 'SENT',\n DRAFT: 'DRAFT',\n CATEGORY_PERSONAL: 'CATEGORY_PERSONAL',\n CATEGORY_SOCIAL: 'CATEGORY_SOCIAL',\n CATEGORY_PROMOTIONS: 'CATEGORY_PROMOTIONS',\n CATEGORY_UPDATES: 'CATEGORY_UPDATES',\n CATEGORY_FORUMS: 'CATEGORY_FORUMS',\n };\n\n const upper = labelName.toUpperCase();\n if (builtInLabels[upper]) return builtInLabels[upper];\n\n // Try to find an existing user label by name\n const listed = await gmail.users.labels.list({ userId });\n const labels = Array.isArray(listed?.data?.labels) ? listed.data.labels : [];\n const existing = labels.find((l: unknown) => {\n const label = l as { name?: unknown; id?: unknown };\n return label?.name === labelName;\n });\n const existingTyped = existing as { id?: unknown } | undefined;\n if (existingTyped?.id) return String(existingTyped.id);\n\n // Create the label if it doesn't exist\n const created = await gmail.users.labels.create({\n userId,\n requestBody: {\n name: labelName,\n labelListVisibility: 'labelShow',\n messageListVisibility: 'show',\n },\n });\n if (!created?.data?.id) throw new Error('Failed to create label');\n return created.data.id as string;\n}\n"],"names":["ensureLabelId","gmail","userId","labelName","listed","created","builtInLabels","INBOX","SPAM","TRASH","UNREAD","STARRED","IMPORTANT","SENT","DRAFT","CATEGORY_PERSONAL","CATEGORY_SOCIAL","CATEGORY_PROMOTIONS","CATEGORY_UPDATES","CATEGORY_FORUMS","upper","toUpperCase","users","labels","list","Array","isArray","data","existing","find","l","label","name","existingTyped","id","String","create","requestBody","labelListVisibility","messageListVisibility","Error"],"mappings":"AAEA,OAAO,eAAeA,cAAcC,KAAqB,EAAEC,MAAc,EAAEC,SAAiB;QAuB7DC,cAiBxBC;IAvCL,+CAA+C;IAC/C,MAAMC,gBAAwC;QAC5CC,OAAO;QACPC,MAAM;QACNC,OAAO;QACPC,QAAQ;QACRC,SAAS;QACTC,WAAW;QACXC,MAAM;QACNC,OAAO;QACPC,mBAAmB;QACnBC,iBAAiB;QACjBC,qBAAqB;QACrBC,kBAAkB;QAClBC,iBAAiB;IACnB;IAEA,MAAMC,QAAQjB,UAAUkB,WAAW;IACnC,IAAIf,aAAa,CAACc,MAAM,EAAE,OAAOd,aAAa,CAACc,MAAM;IAErD,6CAA6C;IAC7C,MAAMhB,SAAS,MAAMH,MAAMqB,KAAK,CAACC,MAAM,CAACC,IAAI,CAAC;QAAEtB;IAAO;IACtD,MAAMqB,SAASE,MAAMC,OAAO,CAACtB,mBAAAA,8BAAAA,eAAAA,OAAQuB,IAAI,cAAZvB,mCAAAA,aAAcmB,MAAM,IAAInB,OAAOuB,IAAI,CAACJ,MAAM,GAAG,EAAE;IAC5E,MAAMK,WAAWL,OAAOM,IAAI,CAAC,CAACC;QAC5B,MAAMC,QAAQD;QACd,OAAOC,CAAAA,kBAAAA,4BAAAA,MAAOC,IAAI,MAAK7B;IACzB;IACA,MAAM8B,gBAAgBL;IACtB,IAAIK,0BAAAA,oCAAAA,cAAeC,EAAE,EAAE,OAAOC,OAAOF,cAAcC,EAAE;IAErD,uCAAuC;IACvC,MAAM7B,UAAU,MAAMJ,MAAMqB,KAAK,CAACC,MAAM,CAACa,MAAM,CAAC;QAC9ClC;QACAmC,aAAa;YACXL,MAAM7B;YACNmC,qBAAqB;YACrBC,uBAAuB;QACzB;IACF;IACA,IAAI,EAAClC,oBAAAA,+BAAAA,gBAAAA,QAASsB,IAAI,cAAbtB,oCAAAA,cAAe6B,EAAE,GAAE,MAAM,IAAIM,MAAM;IACxC,OAAOnC,QAAQsB,IAAI,CAACO,EAAE;AACxB"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/labels/gmail-labels.ts"],"sourcesContent":["import type { gmail_v1 } from '@googleapis/gmail';\n\nexport async function ensureLabelId(gmail: gmail_v1.Gmail, userId: string, labelName: string): Promise<string> {\n // Built-in system labels: pass through by name\n const builtInLabels: Record<string, string> = {\n INBOX: 'INBOX',\n SPAM: 'SPAM',\n TRASH: 'TRASH',\n UNREAD: 'UNREAD',\n STARRED: 'STARRED',\n IMPORTANT: 'IMPORTANT',\n SENT: 'SENT',\n DRAFT: 'DRAFT',\n CATEGORY_PERSONAL: 'CATEGORY_PERSONAL',\n CATEGORY_SOCIAL: 'CATEGORY_SOCIAL',\n CATEGORY_PROMOTIONS: 'CATEGORY_PROMOTIONS',\n CATEGORY_UPDATES: 'CATEGORY_UPDATES',\n CATEGORY_FORUMS: 'CATEGORY_FORUMS',\n };\n\n const upper = labelName.toUpperCase();\n if (builtInLabels[upper]) return builtInLabels[upper];\n\n // Try to find an existing user label by name\n const listed = await gmail.users.labels.list({ userId });\n const labels = Array.isArray(listed?.data?.labels) ? listed.data.labels : [];\n const existing = labels.find((l: unknown) => {\n const label = l as { name?: unknown; id?: unknown };\n return label?.name === labelName;\n });\n const existingTyped = existing as { id?: unknown } | undefined;\n if (existingTyped?.id) return String(existingTyped.id);\n\n // Create the label if it doesn't exist\n const created = await gmail.users.labels.create({\n userId,\n requestBody: {\n name: labelName,\n labelListVisibility: 'labelShow',\n messageListVisibility: 'show',\n },\n });\n if (!created?.data?.id) throw new Error('Failed to create label');\n return created.data.id as string;\n}\n"],"names":["ensureLabelId","gmail","userId","labelName","listed","created","builtInLabels","INBOX","SPAM","TRASH","UNREAD","STARRED","IMPORTANT","SENT","DRAFT","CATEGORY_PERSONAL","CATEGORY_SOCIAL","CATEGORY_PROMOTIONS","CATEGORY_UPDATES","CATEGORY_FORUMS","upper","toUpperCase","users","labels","list","Array","isArray","data","existing","find","l","label","name","existingTyped","id","String","create","requestBody","labelListVisibility","messageListVisibility","Error"],"mappings":"AAEA,OAAO,eAAeA,cAAcC,KAAqB,EAAEC,MAAc,EAAEC,SAAiB;QAuB7DC,cAiBxBC;IAvCL,+CAA+C;IAC/C,MAAMC,gBAAwC;QAC5CC,OAAO;QACPC,MAAM;QACNC,OAAO;QACPC,QAAQ;QACRC,SAAS;QACTC,WAAW;QACXC,MAAM;QACNC,OAAO;QACPC,mBAAmB;QACnBC,iBAAiB;QACjBC,qBAAqB;QACrBC,kBAAkB;QAClBC,iBAAiB;IACnB;IAEA,MAAMC,QAAQjB,UAAUkB,WAAW;IACnC,IAAIf,aAAa,CAACc,MAAM,EAAE,OAAOd,aAAa,CAACc,MAAM;IAErD,6CAA6C;IAC7C,MAAMhB,SAAS,MAAMH,MAAMqB,KAAK,CAACC,MAAM,CAACC,IAAI,CAAC;QAAEtB;IAAO;IACtD,MAAMqB,SAASE,MAAMC,OAAO,CAACtB,mBAAAA,8BAAAA,eAAAA,OAAQuB,IAAI,cAAZvB,mCAAAA,aAAcmB,MAAM,IAAInB,OAAOuB,IAAI,CAACJ,MAAM,GAAG,EAAE;IAC5E,MAAMK,WAAWL,OAAOM,IAAI,CAAC,CAACC;QAC5B,MAAMC,QAAQD;QACd,OAAOC,CAAAA,kBAAAA,4BAAAA,MAAOC,IAAI,MAAK7B;IACzB;IACA,MAAM8B,gBAAgBL;IACtB,IAAIK,0BAAAA,oCAAAA,cAAeC,EAAE,EAAE,OAAOC,OAAOF,cAAcC,EAAE;IAErD,uCAAuC;IACvC,MAAM7B,UAAU,MAAMJ,MAAMqB,KAAK,CAACC,MAAM,CAACa,MAAM,CAAC;QAC9ClC;QACAmC,aAAa;YACXL,MAAM7B;YACNmC,qBAAqB;YACrBC,uBAAuB;QACzB;IACF;IACA,IAAI,EAAClC,oBAAAA,+BAAAA,gBAAAA,QAASsB,IAAI,cAAbtB,oCAAAA,cAAe6B,EAAE,GAAE,MAAM,IAAIM,MAAM;IACxC,OAAOnC,QAAQsB,IAAI,CAACO,EAAE;AACxB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type GoogleAuthProvider } from '@mcp-z/oauth-google';
|
|
2
|
+
/**
|
|
3
|
+
* A Google API client bound to this request's token provider.
|
|
4
|
+
*
|
|
5
|
+
* `@mcp-z/oauth-google` mints tokens and depends on no Google SDK, so the client
|
|
6
|
+
* is built here, from this package's own `googleapis`. That keeps one copy of
|
|
7
|
+
* `google-auth-library` in the tree by construction rather than by matching pins.
|
|
8
|
+
*/
|
|
9
|
+
export declare function googleAuth(auth: GoogleAuthProvider): import("google-auth-library").OAuth2Client;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { auth as googleAuthPlus } from '@googleapis/gmail';
|
|
2
|
+
import { attachTokenProvider } from '@mcp-z/oauth-google';
|
|
3
|
+
/**
|
|
4
|
+
* A Google API client bound to this request's token provider.
|
|
5
|
+
*
|
|
6
|
+
* `@mcp-z/oauth-google` mints tokens and depends on no Google SDK, so the client
|
|
7
|
+
* is built here, from this package's own `googleapis`. That keeps one copy of
|
|
8
|
+
* `google-auth-library` in the tree by construction rather than by matching pins.
|
|
9
|
+
*/ export function googleAuth(auth) {
|
|
10
|
+
return attachTokenProvider(new googleAuthPlus.OAuth2(), auth);
|
|
11
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/lib/google-auth.ts"],"sourcesContent":["import { auth as googleAuthPlus } from '@googleapis/gmail';\nimport { attachTokenProvider, type GoogleAuthProvider } from '@mcp-z/oauth-google';\n\n/**\n * A Google API client bound to this request's token provider.\n *\n * `@mcp-z/oauth-google` mints tokens and depends on no Google SDK, so the client\n * is built here, from this package's own `googleapis`. That keeps one copy of\n * `google-auth-library` in the tree by construction rather than by matching pins.\n */\nexport function googleAuth(auth: GoogleAuthProvider) {\n return attachTokenProvider(new googleAuthPlus.OAuth2(), auth);\n}\n"],"names":["auth","googleAuthPlus","attachTokenProvider","googleAuth","OAuth2"],"mappings":"AAAA,SAASA,QAAQC,cAAc,QAAQ,oBAAoB;AAC3D,SAASC,mBAAmB,QAAiC,sBAAsB;AAEnF;;;;;;CAMC,GACD,OAAO,SAASC,WAAWH,IAAwB;IACjD,OAAOE,oBAAoB,IAAID,eAAeG,MAAM,IAAIJ;AAC1D"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
1
|
+
import type { ServerContext } from '@mcp-z/server';
|
|
3
2
|
import { z } from 'zod';
|
|
4
3
|
export default function createPrompt(): {
|
|
5
4
|
name: string;
|
|
@@ -12,7 +11,7 @@ export default function createPrompt(): {
|
|
|
12
11
|
};
|
|
13
12
|
handler: (args: {
|
|
14
13
|
[x: string]: unknown;
|
|
15
|
-
}, _extra:
|
|
14
|
+
}, _extra: ServerContext) => Promise<{
|
|
16
15
|
messages: ({
|
|
17
16
|
role: "system";
|
|
18
17
|
content: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/prompts/draft-email.ts"],"sourcesContent":["import type { PromptModule } from '@mcp-z/server';\nimport
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/prompts/draft-email.ts"],"sourcesContent":["import type { PromptModule, ServerContext } from '@mcp-z/server';\nimport { z } from 'zod';\n\nexport default function createPrompt() {\n const argsSchema = z.object({\n context: z.string().min(1).describe('Email context to draft response for'),\n tone: z.string().optional().describe('Email tone (default: professional)'),\n });\n\n const config = {\n description: 'Draft an email response',\n argsSchema: argsSchema.shape,\n };\n\n const handler = async (args: { [x: string]: unknown }, _extra: ServerContext) => {\n const { context, tone } = argsSchema.parse(args);\n return {\n messages: [\n { role: 'system' as const, content: { type: 'text' as const, text: 'You are an expert email assistant.' } },\n { role: 'user' as const, content: { type: 'text' as const, text: `Draft a ${tone || 'professional'} email:\\n\\n${context}` } },\n ],\n };\n };\n\n return {\n name: 'draft-email',\n config,\n handler,\n } satisfies PromptModule;\n}\n"],"names":["z","createPrompt","argsSchema","object","context","string","min","describe","tone","optional","config","description","shape","handler","args","_extra","parse","messages","role","content","type","text","name"],"mappings":"AACA,SAASA,CAAC,QAAQ,MAAM;AAExB,eAAe,SAASC;IACtB,MAAMC,aAAaF,EAAEG,MAAM,CAAC;QAC1BC,SAASJ,EAAEK,MAAM,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;QACpCC,MAAMR,EAAEK,MAAM,GAAGI,QAAQ,GAAGF,QAAQ,CAAC;IACvC;IAEA,MAAMG,SAAS;QACbC,aAAa;QACbT,YAAYA,WAAWU,KAAK;IAC9B;IAEA,MAAMC,UAAU,OAAOC,MAAgCC;QACrD,MAAM,EAAEX,OAAO,EAAEI,IAAI,EAAE,GAAGN,WAAWc,KAAK,CAACF;QAC3C,OAAO;YACLG,UAAU;gBACR;oBAAEC,MAAM;oBAAmBC,SAAS;wBAAEC,MAAM;wBAAiBC,MAAM;oBAAqC;gBAAE;gBAC1G;oBAAEH,MAAM;oBAAiBC,SAAS;wBAAEC,MAAM;wBAAiBC,MAAM,CAAC,QAAQ,EAAEb,QAAQ,eAAe,WAAW,EAAEJ,SAAS;oBAAC;gBAAE;aAC7H;QACH;IACF;IAEA,OAAO;QACLkB,MAAM;QACNZ;QACAG;IACF;AACF"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
1
|
+
import type { ServerContext } from '@mcp-z/server';
|
|
3
2
|
export default function createPrompt(): {
|
|
4
3
|
name: string;
|
|
5
4
|
config: {
|
|
@@ -7,7 +6,7 @@ export default function createPrompt(): {
|
|
|
7
6
|
};
|
|
8
7
|
handler: (_args: {
|
|
9
8
|
[x: string]: unknown;
|
|
10
|
-
}, _extra:
|
|
9
|
+
}, _extra: ServerContext) => Promise<{
|
|
11
10
|
messages: {
|
|
12
11
|
role: "user";
|
|
13
12
|
content: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/prompts/query-syntax.ts"],"sourcesContent":["import type { PromptModule } from '@mcp-z/server';\
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/prompts/query-syntax.ts"],"sourcesContent":["import type { PromptModule, ServerContext } from '@mcp-z/server';\n\nexport default function createPrompt() {\n const config = {\n description: 'Reference guide for Gmail query syntax',\n };\n\n const handler = async (_args: { [x: string]: unknown }, _extra: ServerContext) => {\n return {\n messages: [\n {\n role: 'user' as const,\n content: {\n type: 'text' as const,\n text: `# Gmail Query Syntax Reference\n\n## Logical Operators\n- \\`$and\\`: Array of conditions that ALL must match\n- \\`$or\\`: Array of conditions where ANY must match\n- \\`$not\\`: Condition that must NOT match\n\n## Email Address Fields\n- \\`from\\`, \\`to\\`, \\`cc\\`, \\`bcc\\`: String or field operators\n\n## Content Fields\n- \\`subject\\`: Search subject line\n- \\`body\\`: Search message body\n- \\`text\\`: Search all text content\n- \\`fuzzyPhrase\\`: Approximate phrase matching (words appear together)\n\n## Boolean Flags\n- \\`hasAttachment\\`: true/false\n- \\`isRead\\`: true/false\n\n## Date Range\n\\`\\`\\`json\n{ \"date\": { \"$gte\": \"2024-01-01\", \"$lt\": \"2024-12-31\" } }\n\\`\\`\\`\n\n## Gmail-Specific\n- \\`categories\\`: primary, social, promotions, updates, forums\n- \\`label\\`: User labels (case-sensitive, use gmail-labels-list to discover)\n- \\`rawGmailQuery\\`: Escape hatch for advanced Gmail syntax\n\n## Field Operators (for multi-value fields)\n- \\`$any\\`: OR - matches if ANY value matches\n- \\`$all\\`: AND - matches if ALL values match\n- \\`$none\\`: NOT - matches if NONE match\n\n## Example Queries\n\\`\\`\\`json\n// Unread from specific sender\n{ \"from\": \"boss@company.com\", \"isRead\": false }\n\n// Recent with attachment\n{ \"hasAttachment\": true, \"date\": { \"$gte\": \"2024-01-01\" } }\n\n// Multiple senders\n{ \"from\": { \"$any\": [\"alice@example.com\", \"bob@example.com\"] } }\n\n// Complex: promotions OR social, unread\n{ \"$and\": [\n { \"categories\": { \"$any\": [\"promotions\", \"social\"] } },\n { \"isRead\": false }\n]}\n\\`\\`\\``,\n },\n },\n ],\n };\n };\n\n return {\n name: 'query-syntax',\n config,\n handler,\n } satisfies PromptModule;\n}\n"],"names":["createPrompt","config","description","handler","_args","_extra","messages","role","content","type","text","name"],"mappings":"AAEA,eAAe,SAASA;IACtB,MAAMC,SAAS;QACbC,aAAa;IACf;IAEA,MAAMC,UAAU,OAAOC,OAAiCC;QACtD,OAAO;YACLC,UAAU;gBACR;oBACEC,MAAM;oBACNC,SAAS;wBACPC,MAAM;wBACNC,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MAmDb,CAAC;oBACG;gBACF;aACD;QACH;IACF;IAEA,OAAO;QACLC,MAAM;QACNV;QACAE;IACF;AACF"}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import type { ReadResourceResult, ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
1
|
+
import type { ReadResourceResult, ServerContext } from '@mcp-z/server';
|
|
2
|
+
import { ResourceTemplate } from '@mcp-z/server';
|
|
4
3
|
export default function createResource(): {
|
|
5
4
|
name: string;
|
|
6
5
|
template: ResourceTemplate;
|
|
7
|
-
config: import("@modelcontextprotocol/
|
|
6
|
+
config: import("@modelcontextprotocol/server").ResourceMetadata & {
|
|
7
|
+
cacheHint?: import("@mcp-z/server").CacheHint;
|
|
8
|
+
};
|
|
8
9
|
handler: (uri: URL, variables: {
|
|
9
10
|
id: string;
|
|
10
|
-
}, extra:
|
|
11
|
+
}, extra: ServerContext) => Promise<ReadResourceResult>;
|
|
11
12
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { gmail as gmailApi } from '@googleapis/gmail';
|
|
2
|
+
import { ResourceTemplate } from '@mcp-z/server';
|
|
3
3
|
import { extractEmails, extractFrom } from '../../email/parsing/message-extraction.js';
|
|
4
4
|
import { toIsoUtc } from '../../lib/date-conversion.js';
|
|
5
|
+
import { googleAuth } from '../../lib/google-auth.js';
|
|
5
6
|
export default function createResource() {
|
|
6
7
|
const template = new ResourceTemplate('gmail://messages/{id}', {
|
|
7
8
|
list: undefined
|
|
@@ -16,9 +17,9 @@ export default function createResource() {
|
|
|
16
17
|
var _fullData_payload;
|
|
17
18
|
const { logger, authContext } = extra;
|
|
18
19
|
logger.info(variables, 'gmail-email resource fetch');
|
|
19
|
-
const gmail =
|
|
20
|
+
const gmail = gmailApi({
|
|
20
21
|
version: 'v1',
|
|
21
|
-
auth: authContext.auth
|
|
22
|
+
auth: googleAuth(authContext.auth)
|
|
22
23
|
});
|
|
23
24
|
const response = await gmail.users.messages.get({
|
|
24
25
|
userId: 'me',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/resources/email.ts"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/resources/email.ts"],"sourcesContent":["import { type gmail_v1, gmail as gmailApi } from '@googleapis/gmail';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport type { ReadResourceResult, ResourceConfig, ResourceModule, ServerContext } from '@mcp-z/server';\nimport { ResourceTemplate } from '@mcp-z/server';\nimport { extractEmails, extractFrom } from '../../email/parsing/message-extraction.ts';\nimport { toIsoUtc } from '../../lib/date-conversion.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\nexport default function createResource() {\n const template = new ResourceTemplate('gmail://messages/{id}', {\n list: undefined,\n });\n const config: ResourceConfig = {\n description: 'Gmail message metadata (lightweight: id, subject, from, to, date)',\n mimeType: 'application/json',\n };\n\n const handler = async (uri: URL, variables: { id: string }, extra: ServerContext): Promise<ReadResourceResult> => {\n try {\n const { logger, authContext } = extra as unknown as EnrichedExtra;\n\n logger.info(variables, 'gmail-email resource fetch');\n\n const gmail = gmailApi({ version: 'v1', auth: googleAuth(authContext.auth) });\n const response = await gmail.users.messages.get({\n userId: 'me',\n id: variables.id,\n format: 'metadata',\n metadataHeaders: ['From', 'To', 'Subject', 'Date'],\n });\n\n const fullData = response.data;\n if (!fullData) {\n throw new Error('Message not found');\n }\n\n // Extract headers\n const headers = fullData?.payload?.headers;\n const headersArray = Array.isArray(headers) ? headers : [];\n const headersMap: Record<string, string> = Object.fromEntries(\n headersArray.map((h: unknown) => {\n const header = h as gmail_v1.Schema$MessagePartHeader;\n return [String(header.name ?? ''), String(header.value ?? '')];\n })\n );\n\n const fromInfo = extractFrom(headersMap.From);\n const toStr = extractEmails(headersMap.To).join(', ');\n\n // Return lightweight metadata only (no body/snippet)\n const metadata = {\n id: fullData.id ?? variables.id,\n subject: headersMap.Subject ?? '',\n from: fromInfo?.address || headersMap.From,\n to: toStr,\n date: toIsoUtc(headersMap.Date) || headersMap.Date,\n };\n\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify(metadata),\n },\n ],\n };\n } catch (e) {\n const { logger } = extra as unknown as EnrichedExtra;\n logger.error(e as Record<string, unknown>, 'gmail-email resource fetch failed');\n const error = e as { message?: unknown };\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'application/json',\n text: JSON.stringify({ error: String(error?.message ?? e) }),\n },\n ],\n };\n }\n };\n\n return {\n name: 'email',\n template,\n config,\n handler,\n } satisfies ResourceModule;\n}\n"],"names":["gmail","gmailApi","ResourceTemplate","extractEmails","extractFrom","toIsoUtc","googleAuth","createResource","template","list","undefined","config","description","mimeType","handler","uri","variables","extra","fullData","headersMap","logger","authContext","info","version","auth","response","users","messages","get","userId","id","format","metadataHeaders","data","Error","headers","payload","headersArray","Array","isArray","Object","fromEntries","map","h","header","String","name","value","fromInfo","From","toStr","To","join","metadata","subject","Subject","from","address","to","date","Date","contents","href","text","JSON","stringify","e","error","message"],"mappings":"AAAA,SAAwBA,SAASC,QAAQ,QAAQ,oBAAoB;AAGrE,SAASC,gBAAgB,QAAQ,gBAAgB;AACjD,SAASC,aAAa,EAAEC,WAAW,QAAQ,4CAA4C;AACvF,SAASC,QAAQ,QAAQ,+BAA+B;AACxD,SAASC,UAAU,QAAQ,2BAA2B;AAEtD,eAAe,SAASC;IACtB,MAAMC,WAAW,IAAIN,iBAAiB,yBAAyB;QAC7DO,MAAMC;IACR;IACA,MAAMC,SAAyB;QAC7BC,aAAa;QACbC,UAAU;IACZ;IAEA,MAAMC,UAAU,OAAOC,KAAUC,WAA2BC;QAC1D,IAAI;gBAiCIC,cACKC;gBAfKD;YAlBhB,MAAM,EAAEE,MAAM,EAAEC,WAAW,EAAE,GAAGJ;YAEhCG,OAAOE,IAAI,CAACN,WAAW;YAEvB,MAAMhB,QAAQC,SAAS;gBAAEsB,SAAS;gBAAMC,MAAMlB,WAAWe,YAAYG,IAAI;YAAE;YAC3E,MAAMC,WAAW,MAAMzB,MAAM0B,KAAK,CAACC,QAAQ,CAACC,GAAG,CAAC;gBAC9CC,QAAQ;gBACRC,IAAId,UAAUc,EAAE;gBAChBC,QAAQ;gBACRC,iBAAiB;oBAAC;oBAAQ;oBAAM;oBAAW;iBAAO;YACpD;YAEA,MAAMd,WAAWO,SAASQ,IAAI;YAC9B,IAAI,CAACf,UAAU;gBACb,MAAM,IAAIgB,MAAM;YAClB;YAEA,kBAAkB;YAClB,MAAMC,UAAUjB,qBAAAA,gCAAAA,oBAAAA,SAAUkB,OAAO,cAAjBlB,wCAAAA,kBAAmBiB,OAAO;YAC1C,MAAME,eAAeC,MAAMC,OAAO,CAACJ,WAAWA,UAAU,EAAE;YAC1D,MAAMhB,aAAqCqB,OAAOC,WAAW,CAC3DJ,aAAaK,GAAG,CAAC,CAACC;oBAEDC,cAA2BA;gBAD1C,MAAMA,SAASD;gBACf,OAAO;oBAACE,QAAOD,eAAAA,OAAOE,IAAI,cAAXF,0BAAAA,eAAe;oBAAKC,QAAOD,gBAAAA,OAAOG,KAAK,cAAZH,2BAAAA,gBAAgB;iBAAI;YAChE;YAGF,MAAMI,WAAW5C,YAAYe,WAAW8B,IAAI;YAC5C,MAAMC,QAAQ/C,cAAcgB,WAAWgC,EAAE,EAAEC,IAAI,CAAC;YAEhD,qDAAqD;YACrD,MAAMC,WAAW;gBACfvB,EAAE,GAAEZ,eAAAA,SAASY,EAAE,cAAXZ,0BAAAA,eAAeF,UAAUc,EAAE;gBAC/BwB,OAAO,GAAEnC,sBAAAA,WAAWoC,OAAO,cAAlBpC,iCAAAA,sBAAsB;gBAC/BqC,MAAMR,CAAAA,qBAAAA,+BAAAA,SAAUS,OAAO,KAAItC,WAAW8B,IAAI;gBAC1CS,IAAIR;gBACJS,MAAMtD,SAASc,WAAWyC,IAAI,KAAKzC,WAAWyC,IAAI;YACpD;YAEA,OAAO;gBACLC,UAAU;oBACR;wBACE9C,KAAKA,IAAI+C,IAAI;wBACbjD,UAAU;wBACVkD,MAAMC,KAAKC,SAAS,CAACZ;oBACvB;iBACD;YACH;QACF,EAAE,OAAOa,GAAG;;YACV,MAAM,EAAE9C,MAAM,EAAE,GAAGH;YACnBG,OAAO+C,KAAK,CAACD,GAA8B;YAC3C,MAAMC,QAAQD;YACd,OAAO;gBACLL,UAAU;oBACR;wBACE9C,KAAKA,IAAI+C,IAAI;wBACbjD,UAAU;wBACVkD,MAAMC,KAAKC,SAAS,CAAC;4BAAEE,OAAOtB,eAAOsB,kBAAAA,4BAAAA,MAAOC,OAAO,uCAAIF;wBAAG;oBAC5D;iBACD;YACH;QACF;IACF;IAEA,OAAO;QACLpB,MAAM;QACNtC;QACAG;QACAG;IACF;AACF"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { gmail as gmailApi } from '@googleapis/gmail';
|
|
1
2
|
import { schemas } from '@mcp-z/oauth-google';
|
|
2
3
|
const { AuthRequiredBranchSchema } = schemas;
|
|
3
|
-
import {
|
|
4
|
-
import { google } from 'googleapis';
|
|
4
|
+
import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
|
|
5
5
|
import { z } from 'zod';
|
|
6
|
+
import { googleAuth } from '../../lib/google-auth.js';
|
|
6
7
|
// Schema for individual category items
|
|
7
8
|
const CategorySchema = z.object({
|
|
8
9
|
id: z.string().describe('Gmail category ID (e.g., CATEGORY_PERSONAL)'),
|
|
@@ -33,9 +34,9 @@ async function handler(_, extra) {
|
|
|
33
34
|
const logger = extra.logger;
|
|
34
35
|
logger.info('gmail.categories.list called');
|
|
35
36
|
try {
|
|
36
|
-
const gmail =
|
|
37
|
+
const gmail = gmailApi({
|
|
37
38
|
version: 'v1',
|
|
38
|
-
auth: extra.authContext.auth
|
|
39
|
+
auth: googleAuth(extra.authContext.auth)
|
|
39
40
|
});
|
|
40
41
|
const started = Date.now();
|
|
41
42
|
// Fetch all labels from Gmail API
|
|
@@ -112,7 +113,7 @@ async function handler(_, extra) {
|
|
|
112
113
|
logger.error('gmail.categories.list error', {
|
|
113
114
|
error: message
|
|
114
115
|
});
|
|
115
|
-
throw new
|
|
116
|
+
throw new ProtocolError(ProtocolErrorCode.InternalError, `Error listing categories: ${message}`, {
|
|
116
117
|
stack: error instanceof Error ? error.stack : undefined
|
|
117
118
|
});
|
|
118
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/categories-list.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport {
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/categories-list.ts"],"sourcesContent":["import { gmail as gmailApi } from '@googleapis/gmail';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { z } from 'zod';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\n// Schema for individual category items\nconst CategorySchema = z.object({\n id: z.string().describe('Gmail category ID (e.g., CATEGORY_PERSONAL)'),\n name: z.string().describe('Human-readable category name'),\n description: z.string().describe('Description of what emails belong in this category'),\n});\n\n/**\n * Input schema for the categories-list tool (currently empty as this tool takes no parameters).\n */\nexport const inputSchema = z.object({});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n items: z.array(CategorySchema),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'List Gmail category labels (CATEGORY_*) with IDs and descriptions.',\n inputSchema: inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\n/**\n * Input parameters for the categories-list tool.\n */\nexport type Input = z.infer<typeof inputSchema>;\nexport type Output = z.infer<typeof outputSchema>;\n\nasync function handler(_: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail.categories.list called');\n\n try {\n const gmail = gmailApi({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n const started = Date.now();\n\n // Fetch all labels from Gmail API\n const response = await gmail.users.labels.list({ userId: 'me' });\n const labels = response.data.labels || [];\n\n // Filter for CATEGORY_* system labels and map to our schema\n const categories = labels\n .filter((label) => label.id?.startsWith('CATEGORY_'))\n .map((label) => {\n const id = label.id as string;\n let name = label.name || id;\n let description = '';\n\n // Map known category types to user-friendly names and descriptions\n switch (id) {\n case 'CATEGORY_PERSONAL':\n name = 'Primary';\n description = 'Important emails from people you know';\n break;\n case 'CATEGORY_SOCIAL':\n name = 'Social';\n description = 'Social networks and social websites';\n break;\n case 'CATEGORY_PROMOTIONS':\n name = 'Promotions';\n description = 'Deals, offers, and marketing emails';\n break;\n case 'CATEGORY_UPDATES':\n name = 'Updates';\n description = 'Confirmations, receipts, bills, and statements';\n break;\n case 'CATEGORY_FORUMS':\n name = 'Forums';\n description = 'Online groups, discussion boards, mailing lists';\n break;\n default:\n // For any unknown CATEGORY_* labels, use the label name as-is\n name = label.name || id.replace('CATEGORY_', '');\n description = `Gmail category: ${name}`;\n }\n\n return {\n id,\n name,\n description,\n };\n })\n .sort((a, b) => a.name.localeCompare(b.name)); // Sort alphabetically by name\n\n const durationMs = Date.now() - started;\n\n logger.info('gmail.categories.list results', { categoryCount: categories.length, totalLabels: labels.length });\n logger.info('gmail.categories.list metrics', { durationMs });\n\n const result: Output = {\n type: 'success' as const,\n items: categories,\n };\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('gmail.categories.list error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error listing categories: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'categories-list',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["gmail","gmailApi","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","z","googleAuth","CategorySchema","object","id","string","describe","name","description","inputSchema","successBranchSchema","type","literal","items","array","outputSchema","discriminatedUnion","config","result","handler","_","extra","logger","info","version","auth","authContext","started","Date","now","response","users","labels","list","userId","data","categories","filter","label","startsWith","map","replace","sort","a","b","localeCompare","durationMs","categoryCount","length","totalLabels","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool"],"mappings":"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"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { gmail as gmailApi } from '@googleapis/gmail';
|
|
1
2
|
import { schemas } from '@mcp-z/oauth-google';
|
|
2
3
|
const { AuthRequiredBranchSchema } = schemas;
|
|
3
|
-
import {
|
|
4
|
-
import { google } from 'googleapis';
|
|
4
|
+
import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { ensureLabelId } from '../../labels/gmail-labels.js';
|
|
7
|
+
import { googleAuth } from '../../lib/google-auth.js';
|
|
7
8
|
const inputSchema = z.object({
|
|
8
9
|
id: z.coerce.string().trim().min(1).describe('Gmail message ID to add label to'),
|
|
9
10
|
label: z.coerce.string().trim().min(1).describe('Label name or ID (use gmail-labels-list to discover available labels)')
|
|
@@ -39,12 +40,12 @@ async function handler({ id, label }, extra) {
|
|
|
39
40
|
id,
|
|
40
41
|
label
|
|
41
42
|
});
|
|
42
|
-
throw new
|
|
43
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id or label');
|
|
43
44
|
}
|
|
44
45
|
try {
|
|
45
|
-
const gmail =
|
|
46
|
+
const gmail = gmailApi({
|
|
46
47
|
version: 'v1',
|
|
47
|
-
auth: extra.authContext.auth
|
|
48
|
+
auth: googleAuth(extra.authContext.auth)
|
|
48
49
|
});
|
|
49
50
|
const labelId = await ensureLabelId(gmail, 'me', label);
|
|
50
51
|
await gmail.users.messages.modify({
|
|
@@ -87,7 +88,7 @@ async function handler({ id, label }, extra) {
|
|
|
87
88
|
logger.error('gmail.label.add error', {
|
|
88
89
|
error: message
|
|
89
90
|
});
|
|
90
|
-
throw new
|
|
91
|
+
throw new ProtocolError(ProtocolErrorCode.InternalError, `Error adding label to message: ${message}`, {
|
|
91
92
|
stack: error instanceof Error ? error.stack : undefined
|
|
92
93
|
});
|
|
93
94
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/label-add.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport {
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/label-add.ts"],"sourcesContent":["import { gmail as gmailApi } from '@googleapis/gmail';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { z } from 'zod';\nimport { ensureLabelId } from '../../labels/gmail-labels.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Gmail message ID to add label to'),\n label: z.coerce.string().trim().min(1).describe('Label name or ID (use gmail-labels-list to discover available labels)'),\n});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n item: z.object({\n id: z.string().describe('Message ID the label was added to'),\n label: z.string().describe('Label that was added'),\n }),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Add a label to a Gmail message',\n inputSchema: inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\nexport type Input = z.infer<typeof inputSchema>;\nexport type Output = z.infer<typeof outputSchema>;\n\nasync function handler({ id, label }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail.label.add called', { id, label });\n\n if (!id || !label) {\n logger.info('gmail.label.add missing parameters', { id, label });\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id or label');\n }\n\n try {\n const gmail = gmailApi({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n\n const labelId = await ensureLabelId(gmail, 'me', label);\n await gmail.users.messages.modify({\n userId: 'me',\n id: id,\n requestBody: {\n addLabelIds: [labelId],\n },\n });\n\n logger.info('gmail.label.add success', { id, label });\n logger.info('gmail.label.add result (typed)', { id, label });\n\n const result: Output = {\n type: 'success' as const,\n item: { id, label },\n };\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result),\n },\n ],\n structuredContent: { result },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('gmail.label.add error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error adding label to message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'label-add',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["gmail","gmailApi","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","z","ensureLabelId","googleAuth","inputSchema","object","id","coerce","string","trim","min","describe","label","successBranchSchema","type","literal","item","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","InvalidParams","version","auth","authContext","labelId","users","messages","modify","userId","requestBody","addLabelIds","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"AAAA,SAASA,SAASC,QAAQ,QAAQ,oBAAoB;AAEtD,SAASC,OAAO,QAAQ,sBAAsB;AAE9C,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAASE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACjE,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,aAAa,QAAQ,+BAA+B;AAC7D,SAASC,UAAU,QAAQ,2BAA2B;AAEtD,MAAMC,cAAcH,EAAEI,MAAM,CAAC;IAC3BC,IAAIL,EAAEM,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;IAC7CC,OAAOX,EAAEM,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;AAClD;AAEA,wBAAwB;AACxB,MAAME,sBAAsBZ,EAAEI,MAAM,CAAC;IACnCS,MAAMb,EAAEc,OAAO,CAAC;IAChBC,MAAMf,EAAEI,MAAM,CAAC;QACbC,IAAIL,EAAEO,MAAM,GAAGG,QAAQ,CAAC;QACxBC,OAAOX,EAAEO,MAAM,GAAGG,QAAQ,CAAC;IAC7B;AACF;AAEA,2CAA2C;AAC3C,MAAMM,eAAehB,EAAEiB,kBAAkB,CAAC,QAAQ;IAACL;IAAqBf;CAAyB;AAEjG,MAAMqB,SAAS;IACbC,aAAa;IACbhB,aAAaA;IACba,cAAchB,EAAEI,MAAM,CAAC;QACrBgB,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEhB,EAAE,EAAEM,KAAK,EAAS,EAAEW,KAAoB;IAC/D,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC,0BAA0B;QAAEnB;QAAIM;IAAM;IAElD,IAAI,CAACN,MAAM,CAACM,OAAO;QACjBY,OAAOC,IAAI,CAAC,sCAAsC;YAAEnB;YAAIM;QAAM;QAC9D,MAAM,IAAIb,cAAcC,kBAAkB0B,aAAa,EAAE;IAC3D;IAEA,IAAI;QACF,MAAM/B,QAAQC,SAAS;YAAE+B,SAAS;YAAMC,MAAMzB,WAAWoB,MAAMM,WAAW,CAACD,IAAI;QAAE;QAEjF,MAAME,UAAU,MAAM5B,cAAcP,OAAO,MAAMiB;QACjD,MAAMjB,MAAMoC,KAAK,CAACC,QAAQ,CAACC,MAAM,CAAC;YAChCC,QAAQ;YACR5B,IAAIA;YACJ6B,aAAa;gBACXC,aAAa;oBAACN;iBAAQ;YACxB;QACF;QAEAN,OAAOC,IAAI,CAAC,2BAA2B;YAAEnB;YAAIM;QAAM;QACnDY,OAAOC,IAAI,CAAC,kCAAkC;YAAEnB;YAAIM;QAAM;QAE1D,MAAMS,SAAiB;YACrBP,MAAM;YACNE,MAAM;gBAAEV;gBAAIM;YAAM;QACpB;QAEA,OAAO;YACLyB,SAAS;gBACP;oBACEvB,MAAM;oBACNwB,MAAMC,KAAKC,SAAS,CAACnB;gBACvB;aACD;YACDoB,mBAAmB;gBAAEpB;YAAO;QAC9B;IACF,EAAE,OAAOqB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChElB,OAAOkB,KAAK,CAAC,yBAAyB;YAAEA,OAAOC;QAAQ;QAEvD,MAAM,IAAI5C,cAAcC,kBAAkB8C,aAAa,EAAE,CAAC,+BAA+B,EAAEH,SAAS,EAAE;YACpGI,OAAOL,iBAAiBE,QAAQF,MAAMK,KAAK,GAAGC;QAChD;IACF;AACF;AAEA,eAAe,SAASC;IACtB,OAAO;QACLC,MAAM;QACN/B;QACAG;IACF;AACF"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { gmail as gmailApi } from '@googleapis/gmail';
|
|
1
2
|
import { schemas } from '@mcp-z/oauth-google';
|
|
2
3
|
const { AuthRequiredBranchSchema } = schemas;
|
|
3
|
-
import {
|
|
4
|
-
import { google } from 'googleapis';
|
|
4
|
+
import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.js';
|
|
7
|
+
import { googleAuth } from '../../lib/google-auth.js';
|
|
7
8
|
const inputSchema = z.object({
|
|
8
9
|
ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Gmail label IDs to delete')
|
|
9
10
|
});
|
|
@@ -35,11 +36,11 @@ async function handler({ ids }, extra) {
|
|
|
35
36
|
count: ids.length
|
|
36
37
|
});
|
|
37
38
|
if (!ids || ids.length === 0) {
|
|
38
|
-
throw new
|
|
39
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing ids');
|
|
39
40
|
}
|
|
40
41
|
// Validate batch size to prevent memory exhaustion
|
|
41
42
|
if (ids.length > MAX_BATCH_SIZE) {
|
|
42
|
-
throw new
|
|
43
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Batch size ${ids.length} exceeds maximum allowed size of ${MAX_BATCH_SIZE}`);
|
|
43
44
|
}
|
|
44
45
|
// Validate and sanitize IDs
|
|
45
46
|
const validatedIds = [];
|
|
@@ -58,15 +59,15 @@ async function handler({ ids }, extra) {
|
|
|
58
59
|
validatedIds.push(trimmedId);
|
|
59
60
|
}
|
|
60
61
|
if (invalidIds.length > 0) {
|
|
61
|
-
throw new
|
|
62
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);
|
|
62
63
|
}
|
|
63
64
|
if (validatedIds.length === 0) {
|
|
64
|
-
throw new
|
|
65
|
+
throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');
|
|
65
66
|
}
|
|
66
67
|
try {
|
|
67
|
-
const gmail =
|
|
68
|
+
const gmail = gmailApi({
|
|
68
69
|
version: 'v1',
|
|
69
|
-
auth: extra.authContext.auth
|
|
70
|
+
auth: googleAuth(extra.authContext.auth)
|
|
70
71
|
});
|
|
71
72
|
// Get all labels first to check for system labels
|
|
72
73
|
const labelsResponse = await gmail.users.labels.list({
|
|
@@ -172,7 +173,7 @@ async function handler({ ids }, extra) {
|
|
|
172
173
|
logger.error('gmail-label-delete error', {
|
|
173
174
|
error: message
|
|
174
175
|
});
|
|
175
|
-
throw new
|
|
176
|
+
throw new ProtocolError(ProtocolErrorCode.InternalError, `Error deleting labels: ${message}`, {
|
|
176
177
|
stack: error instanceof Error ? error.stack : undefined
|
|
177
178
|
});
|
|
178
179
|
}
|