@mcp-z/mcp-gmail 2.0.0 → 2.1.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.
Files changed (56) hide show
  1. package/dist/cjs/lib/google-auth.d.cts +9 -0
  2. package/dist/cjs/lib/google-auth.d.ts +9 -0
  3. package/dist/cjs/lib/google-auth.js +16 -0
  4. package/dist/cjs/lib/google-auth.js.map +1 -0
  5. package/dist/cjs/mcp/resources/email.js +2 -1
  6. package/dist/cjs/mcp/resources/email.js.map +1 -1
  7. package/dist/cjs/mcp/tools/categories-list.js +2 -1
  8. package/dist/cjs/mcp/tools/categories-list.js.map +1 -1
  9. package/dist/cjs/mcp/tools/label-add.js +2 -1
  10. package/dist/cjs/mcp/tools/label-add.js.map +1 -1
  11. package/dist/cjs/mcp/tools/label-delete.js +2 -1
  12. package/dist/cjs/mcp/tools/label-delete.js.map +1 -1
  13. package/dist/cjs/mcp/tools/labels-list.js +2 -1
  14. package/dist/cjs/mcp/tools/labels-list.js.map +1 -1
  15. package/dist/cjs/mcp/tools/message-get.js +2 -1
  16. package/dist/cjs/mcp/tools/message-get.js.map +1 -1
  17. package/dist/cjs/mcp/tools/message-mark-read.js +2 -1
  18. package/dist/cjs/mcp/tools/message-mark-read.js.map +1 -1
  19. package/dist/cjs/mcp/tools/message-move-to-trash.js +2 -1
  20. package/dist/cjs/mcp/tools/message-move-to-trash.js.map +1 -1
  21. package/dist/cjs/mcp/tools/message-respond.js +2 -1
  22. package/dist/cjs/mcp/tools/message-respond.js.map +1 -1
  23. package/dist/cjs/mcp/tools/message-search.js +2 -1
  24. package/dist/cjs/mcp/tools/message-search.js.map +1 -1
  25. package/dist/cjs/mcp/tools/message-send.js +2 -1
  26. package/dist/cjs/mcp/tools/message-send.js.map +1 -1
  27. package/dist/cjs/mcp/tools/messages-export-csv.js +2 -1
  28. package/dist/cjs/mcp/tools/messages-export-csv.js.map +1 -1
  29. package/dist/esm/lib/google-auth.d.ts +9 -0
  30. package/dist/esm/lib/google-auth.js +11 -0
  31. package/dist/esm/lib/google-auth.js.map +1 -0
  32. package/dist/esm/mcp/resources/email.js +2 -1
  33. package/dist/esm/mcp/resources/email.js.map +1 -1
  34. package/dist/esm/mcp/tools/categories-list.js +2 -1
  35. package/dist/esm/mcp/tools/categories-list.js.map +1 -1
  36. package/dist/esm/mcp/tools/label-add.js +2 -1
  37. package/dist/esm/mcp/tools/label-add.js.map +1 -1
  38. package/dist/esm/mcp/tools/label-delete.js +2 -1
  39. package/dist/esm/mcp/tools/label-delete.js.map +1 -1
  40. package/dist/esm/mcp/tools/labels-list.js +2 -1
  41. package/dist/esm/mcp/tools/labels-list.js.map +1 -1
  42. package/dist/esm/mcp/tools/message-get.js +2 -1
  43. package/dist/esm/mcp/tools/message-get.js.map +1 -1
  44. package/dist/esm/mcp/tools/message-mark-read.js +2 -1
  45. package/dist/esm/mcp/tools/message-mark-read.js.map +1 -1
  46. package/dist/esm/mcp/tools/message-move-to-trash.js +2 -1
  47. package/dist/esm/mcp/tools/message-move-to-trash.js.map +1 -1
  48. package/dist/esm/mcp/tools/message-respond.js +2 -1
  49. package/dist/esm/mcp/tools/message-respond.js.map +1 -1
  50. package/dist/esm/mcp/tools/message-search.js +2 -1
  51. package/dist/esm/mcp/tools/message-search.js.map +1 -1
  52. package/dist/esm/mcp/tools/message-send.js +2 -1
  53. package/dist/esm/mcp/tools/message-send.js.map +1 -1
  54. package/dist/esm/mcp/tools/messages-export-csv.js +2 -1
  55. package/dist/esm/mcp/tools/messages-export-csv.js.map +1 -1
  56. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/label-delete.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Gmail label IDs to delete'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n totalRequested: z.number().describe('Total number of labels requested to delete'),\n successCount: z.number().describe('Number of labels successfully deleted'),\n failureCount: z.number().describe('Number of labels that failed to delete'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Label ID'),\n success: z.boolean().describe('Whether the operation succeeded'),\n error: z.string().optional().describe('Error message if operation failed'),\n })\n )\n .describe('Individual results for each label'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Delete Gmail labels permanently (irreversible). System labels (INBOX, SENT, etc.) cannot be deleted.',\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({ ids }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-label-delete called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing ids');\n }\n\n // Validate batch size to prevent memory exhaustion\n if (ids.length > MAX_BATCH_SIZE) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Batch size ${ids.length} exceeds maximum allowed size of ${MAX_BATCH_SIZE}`);\n }\n\n // Validate and sanitize IDs\n const validatedIds: string[] = [];\n const invalidIds: string[] = [];\n\n for (const id of ids) {\n const trimmedId = id.trim();\n if (!trimmedId) {\n invalidIds.push(id);\n continue;\n }\n // Basic Gmail label ID validation - should not contain certain characters\n if (trimmedId.includes('/') || trimmedId.includes('\\\\') || trimmedId.includes('<') || trimmedId.includes('>')) {\n invalidIds.push(id);\n continue;\n }\n validatedIds.push(trimmedId);\n }\n\n if (invalidIds.length > 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n // Get all labels first to check for system labels\n const labelsResponse = await gmail.users.labels.list({ userId: 'me' });\n const allLabels = labelsResponse.data.labels || [];\n const labelMap = new Map(allLabels.map((label) => [label.id || '', label]));\n\n // Process deletions in chunks to prevent memory exhaustion\n const allResults: Array<{ id: string; success: boolean; error?: string }> = [];\n\n for (let i = 0; i < validatedIds.length; i += CHUNK_SIZE) {\n const chunk = validatedIds.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(validatedIds.length / CHUNK_SIZE) });\n\n const chunkResults = await Promise.allSettled(\n chunk.map(async (id) => {\n const label = labelMap.get(id);\n\n // Check if label exists\n if (!label) {\n throw new Error(`Label not found: ${id}`);\n }\n\n // Check if it's a system label\n if (label.type === 'system') {\n throw new Error(`Cannot delete system label: ${label.name} (${id})`);\n }\n\n // Delete the label\n await gmail.users.labels.delete({\n userId: 'me',\n id: id,\n });\n return { id, success: true };\n })\n );\n\n // Process chunk results\n const processedChunkResults = chunkResults.map((result, chunkIndex) => {\n const id = chunk[chunkIndex];\n if (!id) {\n throw new Error(`Chunk index ${chunkIndex} is out of bounds for chunk of size ${chunk.length}`);\n }\n if (result.status === 'fulfilled') {\n return { id, success: true };\n }\n\n // Extract error message more robustly\n let errorMessage = 'Unknown error';\n if (result.reason) {\n if (typeof result.reason === 'string') {\n errorMessage = result.reason;\n } else if (result.reason instanceof Error) {\n errorMessage = result.reason.message;\n } else if (result.reason && typeof result.reason === 'object' && 'message' in result.reason) {\n errorMessage = String(result.reason.message);\n } else if (result.reason && typeof result.reason === 'object' && 'error' in result.reason) {\n errorMessage = String(result.reason.error);\n } else {\n errorMessage = String(result.reason);\n }\n }\n\n return { id, success: false, error: errorMessage };\n });\n\n allResults.push(...processedChunkResults);\n }\n\n const successCount = allResults.filter((r) => r.success).length;\n const failureCount = allResults.filter((r) => !r.success).length;\n\n logger.info('gmail-label-delete completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\n });\n\n const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\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-delete error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error deleting labels: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'label-delete',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","CHUNK_SIZE","MAX_BATCH_SIZE","inputSchema","object","ids","array","coerce","string","trim","min","describe","successBranchSchema","type","literal","totalRequested","number","successCount","failureCount","results","id","success","boolean","error","optional","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","validatedIds","invalidIds","trimmedId","push","includes","join","gmail","version","auth","authContext","labelsResponse","users","labels","list","userId","allLabels","data","labelMap","Map","map","label","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","get","Error","name","delete","processedChunkResults","status","errorMessage","reason","message","String","filter","r","chunksProcessed","content","text","JSON","stringify","structuredContent","InternalError","stack","undefined","createTool"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/label-delete.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Gmail label IDs to delete'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n totalRequested: z.number().describe('Total number of labels requested to delete'),\n successCount: z.number().describe('Number of labels successfully deleted'),\n failureCount: z.number().describe('Number of labels that failed to delete'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Label ID'),\n success: z.boolean().describe('Whether the operation succeeded'),\n error: z.string().optional().describe('Error message if operation failed'),\n })\n )\n .describe('Individual results for each label'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Delete Gmail labels permanently (irreversible). System labels (INBOX, SENT, etc.) cannot be deleted.',\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({ ids }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-label-delete called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing ids');\n }\n\n // Validate batch size to prevent memory exhaustion\n if (ids.length > MAX_BATCH_SIZE) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Batch size ${ids.length} exceeds maximum allowed size of ${MAX_BATCH_SIZE}`);\n }\n\n // Validate and sanitize IDs\n const validatedIds: string[] = [];\n const invalidIds: string[] = [];\n\n for (const id of ids) {\n const trimmedId = id.trim();\n if (!trimmedId) {\n invalidIds.push(id);\n continue;\n }\n // Basic Gmail label ID validation - should not contain certain characters\n if (trimmedId.includes('/') || trimmedId.includes('\\\\') || trimmedId.includes('<') || trimmedId.includes('>')) {\n invalidIds.push(id);\n continue;\n }\n validatedIds.push(trimmedId);\n }\n\n if (invalidIds.length > 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n // Get all labels first to check for system labels\n const labelsResponse = await gmail.users.labels.list({ userId: 'me' });\n const allLabels = labelsResponse.data.labels || [];\n const labelMap = new Map(allLabels.map((label) => [label.id || '', label]));\n\n // Process deletions in chunks to prevent memory exhaustion\n const allResults: Array<{ id: string; success: boolean; error?: string }> = [];\n\n for (let i = 0; i < validatedIds.length; i += CHUNK_SIZE) {\n const chunk = validatedIds.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(validatedIds.length / CHUNK_SIZE) });\n\n const chunkResults = await Promise.allSettled(\n chunk.map(async (id) => {\n const label = labelMap.get(id);\n\n // Check if label exists\n if (!label) {\n throw new Error(`Label not found: ${id}`);\n }\n\n // Check if it's a system label\n if (label.type === 'system') {\n throw new Error(`Cannot delete system label: ${label.name} (${id})`);\n }\n\n // Delete the label\n await gmail.users.labels.delete({\n userId: 'me',\n id: id,\n });\n return { id, success: true };\n })\n );\n\n // Process chunk results\n const processedChunkResults = chunkResults.map((result, chunkIndex) => {\n const id = chunk[chunkIndex];\n if (!id) {\n throw new Error(`Chunk index ${chunkIndex} is out of bounds for chunk of size ${chunk.length}`);\n }\n if (result.status === 'fulfilled') {\n return { id, success: true };\n }\n\n // Extract error message more robustly\n let errorMessage = 'Unknown error';\n if (result.reason) {\n if (typeof result.reason === 'string') {\n errorMessage = result.reason;\n } else if (result.reason instanceof Error) {\n errorMessage = result.reason.message;\n } else if (result.reason && typeof result.reason === 'object' && 'message' in result.reason) {\n errorMessage = String(result.reason.message);\n } else if (result.reason && typeof result.reason === 'object' && 'error' in result.reason) {\n errorMessage = String(result.reason.error);\n } else {\n errorMessage = String(result.reason);\n }\n }\n\n return { id, success: false, error: errorMessage };\n });\n\n allResults.push(...processedChunkResults);\n }\n\n const successCount = allResults.filter((r) => r.success).length;\n const failureCount = allResults.filter((r) => !r.success).length;\n\n logger.info('gmail-label-delete completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\n });\n\n const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\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-delete error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error deleting labels: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'label-delete',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","CHUNK_SIZE","MAX_BATCH_SIZE","googleAuth","inputSchema","object","ids","array","coerce","string","trim","min","describe","successBranchSchema","type","literal","totalRequested","number","successCount","failureCount","results","id","success","boolean","error","optional","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","validatedIds","invalidIds","trimmedId","push","includes","join","gmail","version","auth","authContext","labelsResponse","users","labels","list","userId","allLabels","data","labelMap","Map","map","label","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","get","Error","name","delete","processedChunkResults","status","errorMessage","reason","message","String","filter","r","chunksProcessed","content","text","JSON","stringify","structuredContent","InternalError","stack","undefined","createTool"],"mappings":"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"}
@@ -3,6 +3,7 @@ const { AuthRequiredBranchSchema } = schemas;
3
3
  import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
4
4
  import { google } from 'googleapis';
5
5
  import { z } from 'zod';
6
+ import { googleAuth } from '../../lib/google-auth.js';
6
7
  // Schema for individual label items
7
8
  const LabelSchema = z.object({
8
9
  id: z.string().describe('Gmail label ID'),
@@ -41,7 +42,7 @@ async function handler(_, extra) {
41
42
  try {
42
43
  const gmail = google.gmail({
43
44
  version: 'v1',
44
- auth: extra.authContext.auth
45
+ auth: googleAuth(extra.authContext.auth)
45
46
  });
46
47
  const started = Date.now();
47
48
  // Fetch all labels from Gmail API
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/labels-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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\n\n// Schema for individual label items\nconst LabelSchema = z.object({\n id: z.string().describe('Gmail label ID'),\n name: z.string().describe('Label name for use in queries (case-sensitive)'),\n type: z.enum(['user', 'system']).describe('Whether this is a user-created or system label'),\n visibility: z.enum(['labelShow', 'labelHide', 'labelShowIfUnread']).describe('Label visibility in Gmail UI'),\n});\n\n/**\n * Input schema for the labels-list tool (currently empty as this tool takes no parameters).\n */\nexport const inputSchema = z.object({});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n items: z.array(LabelSchema),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'List Gmail labels for label: query syntax. Case-sensitive.',\n inputSchema: inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\n/**\n * Input parameters for the labels-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.labels.list called');\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: 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 out CATEGORY_* labels (handled by categories tool) and map to our schema\n const availableLabels = labels\n .filter((label) => {\n // Exclude CATEGORY_* labels as they're handled by the categories tool\n return !label.id?.startsWith('CATEGORY_');\n })\n .map((label) => {\n const id = label.id as string;\n const name = label.name || id;\n\n // Determine label type\n const type: 'user' | 'system' = label.type === 'user' ? 'user' : 'system';\n\n // Map label visibility\n let visibility: 'labelShow' | 'labelHide' | 'labelShowIfUnread' = 'labelShow';\n if (label.labelListVisibility === 'labelHide') {\n visibility = 'labelHide';\n } else if (label.labelListVisibility === 'labelShowIfUnread') {\n visibility = 'labelShowIfUnread';\n }\n\n return {\n id,\n name,\n type,\n visibility,\n };\n })\n .sort((a, b) => {\n // Sort user labels first, then system labels, both alphabetically\n if (a.type !== b.type) {\n return a.type === 'user' ? -1 : 1;\n }\n // Use simple ASCII comparison for consistent, case-sensitive sorting\n return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;\n });\n\n const durationMs = Date.now() - started;\n\n logger.info('gmail.labels.list results', {\n labelCount: availableLabels.length,\n userLabels: availableLabels.filter((l) => l.type === 'user').length,\n systemLabels: availableLabels.filter((l) => l.type === 'system').length,\n totalLabels: labels.length,\n });\n logger.info('gmail.labels.list metrics', { durationMs });\n\n const result: Output = {\n type: 'success' as const,\n items: availableLabels,\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.labels.list error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error listing labels: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'labels-list',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","LabelSchema","object","id","string","describe","name","type","enum","visibility","inputSchema","successBranchSchema","literal","items","array","outputSchema","discriminatedUnion","config","description","result","handler","_","extra","logger","info","gmail","version","auth","authContext","started","Date","now","response","users","labels","list","userId","data","availableLabels","filter","label","startsWith","map","labelListVisibility","sort","a","b","durationMs","labelCount","length","userLabels","l","systemLabels","totalLabels","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/labels-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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\n// Schema for individual label items\nconst LabelSchema = z.object({\n id: z.string().describe('Gmail label ID'),\n name: z.string().describe('Label name for use in queries (case-sensitive)'),\n type: z.enum(['user', 'system']).describe('Whether this is a user-created or system label'),\n visibility: z.enum(['labelShow', 'labelHide', 'labelShowIfUnread']).describe('Label visibility in Gmail UI'),\n});\n\n/**\n * Input schema for the labels-list tool (currently empty as this tool takes no parameters).\n */\nexport const inputSchema = z.object({});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n items: z.array(LabelSchema),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'List Gmail labels for label: query syntax. Case-sensitive.',\n inputSchema: inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\n/**\n * Input parameters for the labels-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.labels.list called');\n\n try {\n const gmail = google.gmail({ 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 out CATEGORY_* labels (handled by categories tool) and map to our schema\n const availableLabels = labels\n .filter((label) => {\n // Exclude CATEGORY_* labels as they're handled by the categories tool\n return !label.id?.startsWith('CATEGORY_');\n })\n .map((label) => {\n const id = label.id as string;\n const name = label.name || id;\n\n // Determine label type\n const type: 'user' | 'system' = label.type === 'user' ? 'user' : 'system';\n\n // Map label visibility\n let visibility: 'labelShow' | 'labelHide' | 'labelShowIfUnread' = 'labelShow';\n if (label.labelListVisibility === 'labelHide') {\n visibility = 'labelHide';\n } else if (label.labelListVisibility === 'labelShowIfUnread') {\n visibility = 'labelShowIfUnread';\n }\n\n return {\n id,\n name,\n type,\n visibility,\n };\n })\n .sort((a, b) => {\n // Sort user labels first, then system labels, both alphabetically\n if (a.type !== b.type) {\n return a.type === 'user' ? -1 : 1;\n }\n // Use simple ASCII comparison for consistent, case-sensitive sorting\n return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;\n });\n\n const durationMs = Date.now() - started;\n\n logger.info('gmail.labels.list results', {\n labelCount: availableLabels.length,\n userLabels: availableLabels.filter((l) => l.type === 'user').length,\n systemLabels: availableLabels.filter((l) => l.type === 'system').length,\n totalLabels: labels.length,\n });\n logger.info('gmail.labels.list metrics', { durationMs });\n\n const result: Output = {\n type: 'success' as const,\n items: availableLabels,\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.labels.list error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error listing labels: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'labels-list',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","googleAuth","LabelSchema","object","id","string","describe","name","type","enum","visibility","inputSchema","successBranchSchema","literal","items","array","outputSchema","discriminatedUnion","config","description","result","handler","_","extra","logger","info","gmail","version","auth","authContext","started","Date","now","response","users","labels","list","userId","data","availableLabels","filter","label","startsWith","map","labelListVisibility","sort","a","b","durationMs","labelCount","length","userLabels","l","systemLabels","totalLabels","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { google } from 'googleapis';
6
6
  import { z } from 'zod';
7
7
  import { extractBodyFromPayload, extractEmails, extractFrom } from '../../email/parsing/message-extraction.js';
8
8
  import { toIsoUtc } from '../../lib/date-conversion.js';
9
+ import { googleAuth } from '../../lib/google-auth.js';
9
10
  const inputSchema = z.object({
10
11
  id: z.coerce.string().trim().min(1).describe('Gmail message ID to retrieve'),
11
12
  fields: createFieldsSchema({
@@ -49,7 +50,7 @@ async function handler({ id, fields, contentType, excludeThreadHistory }, extra)
49
50
  }
50
51
  const gmail = google.gmail({
51
52
  version: 'v1',
52
- auth: extra.authContext.auth
53
+ auth: googleAuth(extra.authContext.auth)
53
54
  });
54
55
  const response = await gmail.users.messages.get({
55
56
  userId: 'me',
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-get.ts"],"sourcesContent":["import { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { createFieldsSchema, filterFields, ProtocolError, ProtocolErrorCode, parseFields, type ToolModule } from '@mcp-z/server';\nimport { type gmail_v1, google } from 'googleapis';\nimport { z } from 'zod';\nimport { extractBodyFromPayload, extractEmails, extractFrom } from '../../email/parsing/message-extraction.ts';\nimport { toIsoUtc } from '../../lib/date-conversion.ts';\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Gmail message ID to retrieve'),\n fields: createFieldsSchema({\n availableFields: EMAIL_FIELDS,\n fieldDescriptions: EMAIL_FIELD_DESCRIPTIONS,\n commonPatterns: EMAIL_COMMON_PATTERNS,\n resourceName: 'email message',\n }),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n item: EmailDetailSchema,\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Get a Gmail message by ID with flexible field selection',\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, fields, contentType, excludeThreadHistory }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n\n logger.info('gmail.message.get called', { id: Boolean(id), fields: fields || 'all' });\n\n try {\n if (!id) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n const response = await gmail.users.messages.get({\n userId: 'me',\n id: id,\n format: 'full',\n metadataHeaders: ['From', 'To', 'Cc', 'Bcc', 'Subject', 'Date'],\n });\n const fullData = response.data;\n if (!fullData) {\n throw new ProtocolError(ProtocolErrorCode.InvalidRequest, 'Message not found');\n }\n\n // Build full message data with type guards\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 const fromInfo = extractFrom(headersMap.From);\n const toStr = extractEmails(headersMap.To).join(', ');\n const ccStr = extractEmails(headersMap.Cc).join(', ');\n const bccStr = extractEmails(headersMap.Bcc).join(', ');\n const messagePayload = fullData?.payload;\n const bodyContent = messagePayload ? extractBodyFromPayload(messagePayload, { contentType, excludeThreadHistory }) : '';\n const payload: Partial<EmailDetail> = {\n id: fullData.id ?? undefined,\n threadId: fullData.threadId ?? undefined,\n date: toIsoUtc(headersMap.Date) || headersMap.Date,\n from: fromInfo?.address || headersMap.From,\n fromName: fromInfo?.name,\n to: toStr,\n cc: ccStr,\n bcc: bccStr,\n subject: headersMap.Subject ?? '',\n snippet: fullData.snippet ?? undefined,\n body: bodyContent,\n bodyContentType: contentType,\n };\n\n // Filter based on requested fields\n const filteredPayload = filterFields(payload, requestedFields);\n\n logger.info('gmail.message.get result', { id: fullData.id, subject: payload.subject, from: payload.from, fields: fields || 'all' });\n\n const result: Output = {\n type: 'success' as const,\n item: filteredPayload,\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.message.get error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error getting message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-get',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","schemas","AuthRequiredBranchSchema","createFieldsSchema","filterFields","ProtocolError","ProtocolErrorCode","parseFields","google","z","extractBodyFromPayload","extractEmails","extractFrom","toIsoUtc","inputSchema","object","id","coerce","string","trim","min","describe","fields","availableFields","fieldDescriptions","commonPatterns","resourceName","contentType","excludeThreadHistory","successBranchSchema","type","literal","item","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","requestedFields","info","Boolean","fullData","headersMap","InvalidParams","gmail","version","auth","authContext","response","users","messages","get","userId","format","metadataHeaders","data","InvalidRequest","headers","payload","headersArray","Array","isArray","Object","fromEntries","map","h","header","String","name","value","fromInfo","From","toStr","To","join","ccStr","Cc","bccStr","Bcc","messagePayload","bodyContent","undefined","threadId","date","Date","from","address","fromName","to","cc","bcc","subject","Subject","snippet","body","bodyContentType","filteredPayload","content","text","JSON","stringify","structuredContent","error","message","Error","InternalError","stack","createTool"],"mappings":"AAAA,SAASA,qBAAqB,EAAEC,wBAAwB,EAAEC,YAAY,EAAEC,sBAAsB,EAAoBC,iBAAiB,EAAEC,0BAA0B,QAAQ,eAAe;AAEtL,SAASC,OAAO,QAAQ,sBAAsB;AAE9C,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAErC,SAASE,kBAAkB,EAAEC,YAAY,EAAEC,aAAa,EAAEC,iBAAiB,EAAEC,WAAW,QAAyB,gBAAgB;AACjI,SAAwBC,MAAM,QAAQ,aAAa;AACnD,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,sBAAsB,EAAEC,aAAa,EAAEC,WAAW,QAAQ,4CAA4C;AAC/G,SAASC,QAAQ,QAAQ,+BAA+B;AAExD,MAAMC,cAAcL,EAAEM,MAAM,CAAC;IAC3BC,IAAIP,EAAEQ,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;IAC7CC,QAAQnB,mBAAmB;QACzBoB,iBAAiB1B;QACjB2B,mBAAmB5B;QACnB6B,gBAAgB9B;QAChB+B,cAAc;IAChB;IACAC,aAAa7B;IACb8B,sBAAsB5B;AACxB;AAEA,wBAAwB;AACxB,MAAM6B,sBAAsBpB,EAAEM,MAAM,CAAC;IACnCe,MAAMrB,EAAEsB,OAAO,CAAC;IAChBC,MAAMjC;AACR;AAEA,2CAA2C;AAC3C,MAAMkC,eAAexB,EAAEyB,kBAAkB,CAAC,QAAQ;IAACL;IAAqB3B;CAAyB;AAEjG,MAAMiC,SAAS;IACbC,aAAa;IACbtB,aAAaA;IACbmB,cAAcxB,EAAEM,MAAM,CAAC;QACrBsB,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEtB,EAAE,EAAEM,MAAM,EAAEK,WAAW,EAAEC,oBAAoB,EAAS,EAAEW,KAAoB;IACnG,MAAMC,SAASD,MAAMC,MAAM;IAE3B,MAAMC,kBAAkBlC,YAAYe,QAAQzB;IAE5C2C,OAAOE,IAAI,CAAC,4BAA4B;QAAE1B,IAAI2B,QAAQ3B;QAAKM,QAAQA,UAAU;IAAM;IAEnF,IAAI;YAiCIsB,cACMA,oBAODC,qBACAD;YAxBKA;QAjBhB,IAAI,CAAC5B,IAAI;YACP,MAAM,IAAIX,cAAcC,kBAAkBwC,aAAa,EAAE;QAC3D;QAEA,MAAMC,QAAQvC,OAAOuC,KAAK,CAAC;YAAEC,SAAS;YAAMC,MAAMV,MAAMW,WAAW,CAACD,IAAI;QAAC;QACzE,MAAME,WAAW,MAAMJ,MAAMK,KAAK,CAACC,QAAQ,CAACC,GAAG,CAAC;YAC9CC,QAAQ;YACRvC,IAAIA;YACJwC,QAAQ;YACRC,iBAAiB;gBAAC;gBAAQ;gBAAM;gBAAM;gBAAO;gBAAW;aAAO;QACjE;QACA,MAAMb,WAAWO,SAASO,IAAI;QAC9B,IAAI,CAACd,UAAU;YACb,MAAM,IAAIvC,cAAcC,kBAAkBqD,cAAc,EAAE;QAC5D;QAEA,2CAA2C;QAC3C,MAAMC,UAAUhB,qBAAAA,gCAAAA,oBAAAA,SAAUiB,OAAO,cAAjBjB,wCAAAA,kBAAmBgB,OAAO;QAC1C,MAAME,eAAeC,MAAMC,OAAO,CAACJ,WAAWA,UAAU,EAAE;QAC1D,MAAMf,aAAqCoB,OAAOC,WAAW,CAC3DJ,aAAaK,GAAG,CAAC,CAACC;gBAEDC,cAA2BA;YAD1C,MAAMA,SAASD;YACf,OAAO;gBAACE,QAAOD,eAAAA,OAAOE,IAAI,cAAXF,0BAAAA,eAAe;gBAAKC,QAAOD,gBAAAA,OAAOG,KAAK,cAAZH,2BAAAA,gBAAgB;aAAI;QAChE;QAEF,MAAMI,WAAW7D,YAAYiC,WAAW6B,IAAI;QAC5C,MAAMC,QAAQhE,cAAckC,WAAW+B,EAAE,EAAEC,IAAI,CAAC;QAChD,MAAMC,QAAQnE,cAAckC,WAAWkC,EAAE,EAAEF,IAAI,CAAC;QAChD,MAAMG,SAASrE,cAAckC,WAAWoC,GAAG,EAAEJ,IAAI,CAAC;QAClD,MAAMK,iBAAiBtC,qBAAAA,+BAAAA,SAAUiB,OAAO;QACxC,MAAMsB,cAAcD,iBAAiBxE,uBAAuBwE,gBAAgB;YAAEvD;YAAaC;QAAqB,KAAK;QACrH,MAAMiC,UAAgC;YACpC7C,EAAE,GAAE4B,eAAAA,SAAS5B,EAAE,cAAX4B,0BAAAA,eAAewC;YACnBC,QAAQ,GAAEzC,qBAAAA,SAASyC,QAAQ,cAAjBzC,gCAAAA,qBAAqBwC;YAC/BE,MAAMzE,SAASgC,WAAW0C,IAAI,KAAK1C,WAAW0C,IAAI;YAClDC,MAAMf,CAAAA,qBAAAA,+BAAAA,SAAUgB,OAAO,KAAI5C,WAAW6B,IAAI;YAC1CgB,QAAQ,EAAEjB,qBAAAA,+BAAAA,SAAUF,IAAI;YACxBoB,IAAIhB;YACJiB,IAAId;YACJe,KAAKb;YACLc,OAAO,GAAEjD,sBAAAA,WAAWkD,OAAO,cAAlBlD,iCAAAA,sBAAsB;YAC/BmD,OAAO,GAAEpD,oBAAAA,SAASoD,OAAO,cAAhBpD,+BAAAA,oBAAoBwC;YAC7Ba,MAAMd;YACNe,iBAAiBvE;QACnB;QAEA,mCAAmC;QACnC,MAAMwE,kBAAkB/F,aAAayD,SAASpB;QAE9CD,OAAOE,IAAI,CAAC,4BAA4B;YAAE1B,IAAI4B,SAAS5B,EAAE;YAAE8E,SAASjC,QAAQiC,OAAO;YAAEN,MAAM3B,QAAQ2B,IAAI;YAAElE,QAAQA,UAAU;QAAM;QAEjI,MAAMe,SAAiB;YACrBP,MAAM;YACNE,MAAMmE;QACR;QAEA,OAAO;YACLC,SAAS;gBACP;oBACEtE,MAAM;oBACNuE,MAAMC,KAAKC,SAAS,CAAClE;gBACvB;aACD;YACDmE,mBAAmB;gBAAEnE;YAAO;QAC9B;IACF,EAAE,OAAOoE,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGpC,OAAOmC;QAChEjE,OAAOiE,KAAK,CAAC,2BAA2B;YAAEA,OAAOC;QAAQ;QAEzD,MAAM,IAAIrG,cAAcC,kBAAkBsG,aAAa,EAAE,CAAC,uBAAuB,EAAEF,SAAS,EAAE;YAC5FG,OAAOJ,iBAAiBE,QAAQF,MAAMI,KAAK,GAAGzB;QAChD;IACF;AACF;AAEA,eAAe,SAAS0B;IACtB,OAAO;QACLvC,MAAM;QACNpC;QACAG;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-get.ts"],"sourcesContent":["import { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { createFieldsSchema, filterFields, ProtocolError, ProtocolErrorCode, parseFields, type ToolModule } from '@mcp-z/server';\nimport { type gmail_v1, google } from 'googleapis';\nimport { z } from 'zod';\nimport { extractBodyFromPayload, extractEmails, extractFrom } from '../../email/parsing/message-extraction.ts';\nimport { toIsoUtc } from '../../lib/date-conversion.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 retrieve'),\n fields: createFieldsSchema({\n availableFields: EMAIL_FIELDS,\n fieldDescriptions: EMAIL_FIELD_DESCRIPTIONS,\n commonPatterns: EMAIL_COMMON_PATTERNS,\n resourceName: 'email message',\n }),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n item: EmailDetailSchema,\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Get a Gmail message by ID with flexible field selection',\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, fields, contentType, excludeThreadHistory }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n\n logger.info('gmail.message.get called', { id: Boolean(id), fields: fields || 'all' });\n\n try {\n if (!id) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n const response = await gmail.users.messages.get({\n userId: 'me',\n id: id,\n format: 'full',\n metadataHeaders: ['From', 'To', 'Cc', 'Bcc', 'Subject', 'Date'],\n });\n const fullData = response.data;\n if (!fullData) {\n throw new ProtocolError(ProtocolErrorCode.InvalidRequest, 'Message not found');\n }\n\n // Build full message data with type guards\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 const fromInfo = extractFrom(headersMap.From);\n const toStr = extractEmails(headersMap.To).join(', ');\n const ccStr = extractEmails(headersMap.Cc).join(', ');\n const bccStr = extractEmails(headersMap.Bcc).join(', ');\n const messagePayload = fullData?.payload;\n const bodyContent = messagePayload ? extractBodyFromPayload(messagePayload, { contentType, excludeThreadHistory }) : '';\n const payload: Partial<EmailDetail> = {\n id: fullData.id ?? undefined,\n threadId: fullData.threadId ?? undefined,\n date: toIsoUtc(headersMap.Date) || headersMap.Date,\n from: fromInfo?.address || headersMap.From,\n fromName: fromInfo?.name,\n to: toStr,\n cc: ccStr,\n bcc: bccStr,\n subject: headersMap.Subject ?? '',\n snippet: fullData.snippet ?? undefined,\n body: bodyContent,\n bodyContentType: contentType,\n };\n\n // Filter based on requested fields\n const filteredPayload = filterFields(payload, requestedFields);\n\n logger.info('gmail.message.get result', { id: fullData.id, subject: payload.subject, from: payload.from, fields: fields || 'all' });\n\n const result: Output = {\n type: 'success' as const,\n item: filteredPayload,\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.message.get error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error getting message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-get',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","schemas","AuthRequiredBranchSchema","createFieldsSchema","filterFields","ProtocolError","ProtocolErrorCode","parseFields","google","z","extractBodyFromPayload","extractEmails","extractFrom","toIsoUtc","googleAuth","inputSchema","object","id","coerce","string","trim","min","describe","fields","availableFields","fieldDescriptions","commonPatterns","resourceName","contentType","excludeThreadHistory","successBranchSchema","type","literal","item","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","requestedFields","info","Boolean","fullData","headersMap","InvalidParams","gmail","version","auth","authContext","response","users","messages","get","userId","format","metadataHeaders","data","InvalidRequest","headers","payload","headersArray","Array","isArray","Object","fromEntries","map","h","header","String","name","value","fromInfo","From","toStr","To","join","ccStr","Cc","bccStr","Bcc","messagePayload","bodyContent","undefined","threadId","date","Date","from","address","fromName","to","cc","bcc","subject","Subject","snippet","body","bodyContentType","filteredPayload","content","text","JSON","stringify","structuredContent","error","message","Error","InternalError","stack","createTool"],"mappings":"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"}
@@ -3,6 +3,7 @@ const { AuthRequiredBranchSchema } = schemas;
3
3
  import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
4
4
  import { google } from 'googleapis';
5
5
  import { z } from 'zod';
6
+ import { googleAuth } from '../../lib/google-auth.js';
6
7
  const inputSchema = z.object({
7
8
  id: z.coerce.string().trim().min(1).describe('Gmail message ID to mark as read')
8
9
  });
@@ -32,7 +33,7 @@ async function handler({ id }, extra) {
32
33
  try {
33
34
  const gmail = google.gmail({
34
35
  version: 'v1',
35
- auth: extra.authContext.auth
36
+ auth: googleAuth(extra.authContext.auth)
36
37
  });
37
38
  await gmail.users.messages.modify({
38
39
  userId: 'me',
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-mark-read.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Gmail message ID to mark as read'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: z.string().describe('Message ID that was marked as read'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Mark a Gmail message as read',\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 }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-message-mark-read called', { id: Boolean(id) });\n\n if (!id) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n await gmail.users.messages.modify({\n userId: 'me',\n id: id,\n requestBody: {\n removeLabelIds: ['UNREAD'],\n },\n });\n\n logger.info('gmail-message-mark-read success', { id });\n\n const result: Output = {\n type: 'success' as const,\n id,\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-message-mark-read error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error marking message as read: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-mark-read',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","inputSchema","object","id","coerce","string","trim","min","describe","successBranchSchema","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","Boolean","InvalidParams","gmail","version","auth","authContext","users","messages","modify","userId","requestBody","removeLabelIds","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"AACA,SAASA,OAAO,QAAQ,sBAAsB;AAE9C,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAASE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACjE,SAASC,MAAM,QAAQ,aAAa;AACpC,SAASC,CAAC,QAAQ,MAAM;AAExB,MAAMC,cAAcD,EAAEE,MAAM,CAAC;IAC3BC,IAAIH,EAAEI,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;AAC/C;AAEA,MAAMC,sBAAsBT,EAAEE,MAAM,CAAC;IACnCQ,MAAMV,EAAEW,OAAO,CAAC;IAChBR,IAAIH,EAAEK,MAAM,GAAGG,QAAQ,CAAC;AAC1B;AAEA,MAAMI,eAAeZ,EAAEa,kBAAkB,CAAC,QAAQ;IAACJ;IAAqBb;CAAyB;AAEjG,MAAMkB,SAAS;IACbC,aAAa;IACbd,aAAaA;IACbW,cAAcZ,EAAEE,MAAM,CAAC;QACrBc,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEd,EAAE,EAAS,EAAEe,KAAoB;IACxD,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC,kCAAkC;QAAEjB,IAAIkB,QAAQlB;IAAI;IAEhE,IAAI,CAACA,IAAI;QACP,MAAM,IAAIN,cAAcC,kBAAkBwB,aAAa,EAAE;IAC3D;IAEA,IAAI;QACF,MAAMC,QAAQxB,OAAOwB,KAAK,CAAC;YAAEC,SAAS;YAAMC,MAAMP,MAAMQ,WAAW,CAACD,IAAI;QAAC;QACzE,MAAMF,MAAMI,KAAK,CAACC,QAAQ,CAACC,MAAM,CAAC;YAChCC,QAAQ;YACR3B,IAAIA;YACJ4B,aAAa;gBACXC,gBAAgB;oBAAC;iBAAS;YAC5B;QACF;QAEAb,OAAOC,IAAI,CAAC,mCAAmC;YAAEjB;QAAG;QAEpD,MAAMa,SAAiB;YACrBN,MAAM;YACNP;QACF;QAEA,OAAO;YACL8B,SAAS;gBACP;oBACEvB,MAAM;oBACNwB,MAAMC,KAAKC,SAAS,CAACpB;gBACvB;aACD;YACDqB,mBAAmB;gBAAErB;YAAO;QAC9B;IACF,EAAE,OAAOsB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChEnB,OAAOmB,KAAK,CAAC,iCAAiC;YAAEA,OAAOC;QAAQ;QAE/D,MAAM,IAAI1C,cAAcC,kBAAkB4C,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;QACNhC;QACAG;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-mark-read.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\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 mark as read'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: z.string().describe('Message ID that was marked as read'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Mark a Gmail message as read',\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 }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-message-mark-read called', { id: Boolean(id) });\n\n if (!id) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n await gmail.users.messages.modify({\n userId: 'me',\n id: id,\n requestBody: {\n removeLabelIds: ['UNREAD'],\n },\n });\n\n logger.info('gmail-message-mark-read success', { id });\n\n const result: Output = {\n type: 'success' as const,\n id,\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-message-mark-read error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error marking message as read: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-mark-read',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","googleAuth","inputSchema","object","id","coerce","string","trim","min","describe","successBranchSchema","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","Boolean","InvalidParams","gmail","version","auth","authContext","users","messages","modify","userId","requestBody","removeLabelIds","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"AACA,SAASA,OAAO,QAAQ,sBAAsB;AAE9C,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAASE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACjE,SAASC,MAAM,QAAQ,aAAa;AACpC,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,UAAU,QAAQ,2BAA2B;AAEtD,MAAMC,cAAcF,EAAEG,MAAM,CAAC;IAC3BC,IAAIJ,EAAEK,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;AAC/C;AAEA,MAAMC,sBAAsBV,EAAEG,MAAM,CAAC;IACnCQ,MAAMX,EAAEY,OAAO,CAAC;IAChBR,IAAIJ,EAAEM,MAAM,GAAGG,QAAQ,CAAC;AAC1B;AAEA,MAAMI,eAAeb,EAAEc,kBAAkB,CAAC,QAAQ;IAACJ;IAAqBd;CAAyB;AAEjG,MAAMmB,SAAS;IACbC,aAAa;IACbd,aAAaA;IACbW,cAAcb,EAAEG,MAAM,CAAC;QACrBc,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEd,EAAE,EAAS,EAAEe,KAAoB;IACxD,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC,kCAAkC;QAAEjB,IAAIkB,QAAQlB;IAAI;IAEhE,IAAI,CAACA,IAAI;QACP,MAAM,IAAIP,cAAcC,kBAAkByB,aAAa,EAAE;IAC3D;IAEA,IAAI;QACF,MAAMC,QAAQzB,OAAOyB,KAAK,CAAC;YAAEC,SAAS;YAAMC,MAAMzB,WAAWkB,MAAMQ,WAAW,CAACD,IAAI;QAAE;QACrF,MAAMF,MAAMI,KAAK,CAACC,QAAQ,CAACC,MAAM,CAAC;YAChCC,QAAQ;YACR3B,IAAIA;YACJ4B,aAAa;gBACXC,gBAAgB;oBAAC;iBAAS;YAC5B;QACF;QAEAb,OAAOC,IAAI,CAAC,mCAAmC;YAAEjB;QAAG;QAEpD,MAAMa,SAAiB;YACrBN,MAAM;YACNP;QACF;QAEA,OAAO;YACL8B,SAAS;gBACP;oBACEvB,MAAM;oBACNwB,MAAMC,KAAKC,SAAS,CAACpB;gBACvB;aACD;YACDqB,mBAAmB;gBAAErB;YAAO;QAC9B;IACF,EAAE,OAAOsB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChEnB,OAAOmB,KAAK,CAAC,iCAAiC;YAAEA,OAAOC;QAAQ;QAE/D,MAAM,IAAI3C,cAAcC,kBAAkB6C,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;QACNhC;QACAG;IACF;AACF"}
@@ -4,6 +4,7 @@ import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';
4
4
  import { google } from 'googleapis';
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 message IDs to move to trash')
9
10
  });
@@ -66,7 +67,7 @@ async function handler({ ids }, extra) {
66
67
  try {
67
68
  const gmail = google.gmail({
68
69
  version: 'v1',
69
- auth: extra.authContext.auth
70
+ auth: googleAuth(extra.authContext.auth)
70
71
  });
71
72
  // Process operations in chunks to prevent memory exhaustion
72
73
  const allResults = [];
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-move-to-trash.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Gmail message IDs to move to trash'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n totalRequested: z.number().describe('Total number of messages requested to trash'),\n successCount: z.number().describe('Number of messages successfully moved to trash'),\n failureCount: z.number().describe('Number of messages that failed to move'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Message ID'),\n success: z.boolean().describe('Whether the operation succeeded'),\n error: z.string().optional().describe('Error message if operation failed'),\n })\n )\n .describe('Individual results for each message'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Move Gmail messages to trash (recoverable).',\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({ ids }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-message-move-to-trash called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing ids');\n }\n\n // Validate batch size to prevent memory exhaustion\n if (ids.length > MAX_BATCH_SIZE) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Batch size ${ids.length} exceeds maximum allowed size of ${MAX_BATCH_SIZE}`);\n }\n\n // Validate and sanitize IDs\n const validatedIds: string[] = [];\n const invalidIds: string[] = [];\n\n for (const id of ids) {\n const trimmedId = id.trim();\n if (!trimmedId) {\n invalidIds.push(id);\n continue;\n }\n // Basic Gmail message ID validation - should not contain certain characters\n if (trimmedId.includes('/') || trimmedId.includes('\\\\') || trimmedId.includes('<') || trimmedId.includes('>')) {\n invalidIds.push(id);\n continue;\n }\n validatedIds.push(trimmedId);\n }\n\n if (invalidIds.length > 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n // Process operations in chunks to prevent memory exhaustion\n const allResults: Array<{ id: string; success: boolean; error?: string }> = [];\n\n for (let i = 0; i < validatedIds.length; i += CHUNK_SIZE) {\n const chunk = validatedIds.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(validatedIds.length / CHUNK_SIZE) });\n\n const chunkResults = await Promise.allSettled(\n chunk.map(async (id) => {\n await gmail.users.messages.trash({\n userId: 'me',\n id: id,\n });\n return { id, success: true };\n })\n );\n\n // Process chunk results\n const processedChunkResults = chunkResults.map((result, chunkIndex) => {\n const id = chunk[chunkIndex];\n if (!id) {\n throw new Error(`Chunk index ${chunkIndex} is out of bounds for chunk of size ${chunk.length}`);\n }\n if (result.status === 'fulfilled') {\n return { id, success: true };\n }\n\n // Extract error message more robustly\n let errorMessage = 'Unknown error';\n if (result.reason) {\n if (typeof result.reason === 'string') {\n errorMessage = result.reason;\n } else if (result.reason instanceof Error) {\n errorMessage = result.reason.message;\n } else if (result.reason && typeof result.reason === 'object' && 'message' in result.reason) {\n errorMessage = String(result.reason.message);\n } else if (result.reason && typeof result.reason === 'object' && 'error' in result.reason) {\n errorMessage = String(result.reason.error);\n } else {\n errorMessage = String(result.reason);\n }\n }\n\n return { id, success: false, error: errorMessage };\n });\n\n allResults.push(...processedChunkResults);\n }\n\n const successCount = allResults.filter((r) => r.success).length;\n const failureCount = allResults.filter((r) => !r.success).length;\n\n logger.info('gmail-message-move-to-trash completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\n });\n\n const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\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-message-move-to-trash error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error moving messages to trash: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-move-to-trash',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","CHUNK_SIZE","MAX_BATCH_SIZE","inputSchema","object","ids","array","coerce","string","trim","min","describe","successBranchSchema","type","literal","totalRequested","number","successCount","failureCount","results","id","success","boolean","error","optional","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","validatedIds","invalidIds","trimmedId","push","includes","join","gmail","version","auth","authContext","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","map","users","messages","trash","userId","processedChunkResults","Error","status","errorMessage","reason","message","String","filter","r","chunksProcessed","content","text","JSON","stringify","structuredContent","InternalError","stack","undefined","createTool","name"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-move-to-trash.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 { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { google } from 'googleapis';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Gmail message IDs to move to trash'),\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n totalRequested: z.number().describe('Total number of messages requested to trash'),\n successCount: z.number().describe('Number of messages successfully moved to trash'),\n failureCount: z.number().describe('Number of messages that failed to move'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Message ID'),\n success: z.boolean().describe('Whether the operation succeeded'),\n error: z.string().optional().describe('Error message if operation failed'),\n })\n )\n .describe('Individual results for each message'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Move Gmail messages to trash (recoverable).',\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({ ids }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n logger.info('gmail-message-move-to-trash called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing ids');\n }\n\n // Validate batch size to prevent memory exhaustion\n if (ids.length > MAX_BATCH_SIZE) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Batch size ${ids.length} exceeds maximum allowed size of ${MAX_BATCH_SIZE}`);\n }\n\n // Validate and sanitize IDs\n const validatedIds: string[] = [];\n const invalidIds: string[] = [];\n\n for (const id of ids) {\n const trimmedId = id.trim();\n if (!trimmedId) {\n invalidIds.push(id);\n continue;\n }\n // Basic Gmail message ID validation - should not contain certain characters\n if (trimmedId.includes('/') || trimmedId.includes('\\\\') || trimmedId.includes('<') || trimmedId.includes('>')) {\n invalidIds.push(id);\n continue;\n }\n validatedIds.push(trimmedId);\n }\n\n if (invalidIds.length > 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n // Process operations in chunks to prevent memory exhaustion\n const allResults: Array<{ id: string; success: boolean; error?: string }> = [];\n\n for (let i = 0; i < validatedIds.length; i += CHUNK_SIZE) {\n const chunk = validatedIds.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(validatedIds.length / CHUNK_SIZE) });\n\n const chunkResults = await Promise.allSettled(\n chunk.map(async (id) => {\n await gmail.users.messages.trash({\n userId: 'me',\n id: id,\n });\n return { id, success: true };\n })\n );\n\n // Process chunk results\n const processedChunkResults = chunkResults.map((result, chunkIndex) => {\n const id = chunk[chunkIndex];\n if (!id) {\n throw new Error(`Chunk index ${chunkIndex} is out of bounds for chunk of size ${chunk.length}`);\n }\n if (result.status === 'fulfilled') {\n return { id, success: true };\n }\n\n // Extract error message more robustly\n let errorMessage = 'Unknown error';\n if (result.reason) {\n if (typeof result.reason === 'string') {\n errorMessage = result.reason;\n } else if (result.reason instanceof Error) {\n errorMessage = result.reason.message;\n } else if (result.reason && typeof result.reason === 'object' && 'message' in result.reason) {\n errorMessage = String(result.reason.message);\n } else if (result.reason && typeof result.reason === 'object' && 'error' in result.reason) {\n errorMessage = String(result.reason.error);\n } else {\n errorMessage = String(result.reason);\n }\n }\n\n return { id, success: false, error: errorMessage };\n });\n\n allResults.push(...processedChunkResults);\n }\n\n const successCount = allResults.filter((r) => r.success).length;\n const failureCount = allResults.filter((r) => !r.success).length;\n\n logger.info('gmail-message-move-to-trash completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\n });\n\n const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\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-message-move-to-trash error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error moving messages to trash: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-move-to-trash',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","CHUNK_SIZE","MAX_BATCH_SIZE","googleAuth","inputSchema","object","ids","array","coerce","string","trim","min","describe","successBranchSchema","type","literal","totalRequested","number","successCount","failureCount","results","id","success","boolean","error","optional","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","validatedIds","invalidIds","trimmedId","push","includes","join","gmail","version","auth","authContext","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","map","users","messages","trash","userId","processedChunkResults","Error","status","errorMessage","reason","message","String","filter","r","chunksProcessed","content","text","JSON","stringify","structuredContent","InternalError","stack","undefined","createTool","name"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { google } from 'googleapis';
6
6
  import { z } from 'zod';
7
7
  import { extractEmails } from '../../email/parsing/headers-utils.js';
8
8
  import { b64url } from '../../lib/base64-encoding.js';
9
+ import { googleAuth } from '../../lib/google-auth.js';
9
10
  const inputSchema = z.object({
10
11
  id: z.coerce.string().trim().min(1).describe('Gmail message ID to reply to'),
11
12
  body: z.coerce.string().trim().min(1).describe('Reply body content (plain text or HTML)'),
@@ -40,7 +41,7 @@ async function handler({ id, body, contentType }, extra) {
40
41
  var _fullData_payload;
41
42
  const gmail = google.gmail({
42
43
  version: 'v1',
43
- auth: extra.authContext.auth
44
+ auth: googleAuth(extra.authContext.auth)
44
45
  });
45
46
  let full;
46
47
  try {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-respond.ts"],"sourcesContent":["import { ComposeContentTypeSchema } from '@mcp-z/email';\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 { google } from 'googleapis';\nimport { z } from 'zod';\nimport { extractEmails } from '../../email/parsing/headers-utils.ts';\nimport { b64url } from '../../lib/base64-encoding.ts';\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Gmail message ID to reply to'),\n body: z.coerce.string().trim().min(1).describe('Reply body content (plain text or HTML)'),\n contentType: ComposeContentTypeSchema,\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: z.string().describe('Original message ID that was replied to'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Send a reply 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, body, contentType }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n if (!id || !body) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id or body');\n }\n\n logger.info('gmail.message.respond called', { id, contentType });\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n\n let full: unknown;\n try {\n const response = await gmail.users.messages.get({\n userId: 'me',\n id: id,\n format: 'metadata',\n metadataHeaders: ['From', 'To', 'Reply-To', 'Subject', 'Message-ID', 'References', 'In-Reply-To', 'Date'],\n });\n full = response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('gmail.message.respond fetch error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error fetching message metadata: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n\n // Type-safe header extraction\n const fullData = full as { payload?: { headers?: unknown[] }; threadId?: unknown };\n const headersArray = Array.isArray(fullData?.payload?.headers) ? fullData.payload.headers : [];\n const headers = Object.fromEntries(\n headersArray.map((h: unknown) => {\n const header = h as { name?: unknown; value?: unknown };\n return [String(header.name ?? ''), String(header.value ?? '')];\n })\n );\n const fromHdr = headers.From || headers.from;\n const replyToHdr = headers['Reply-To'] || headers['reply-to'];\n const toAddr = (replyToHdr ? extractEmails(replyToHdr)[0] : extractEmails(fromHdr)[0]) ?? '';\n const subject = (headers.Subject || headers.subject) ?? '';\n const messageIdHeader = headers['Message-ID'] || headers['Message-Id'] || headers['message-id'];\n const references = (headers.References || headers.references) ?? '';\n const replySubject = /^re:/i.test(subject) ? subject : `Re: ${subject}`;\n const inReplyTo = messageIdHeader?.startsWith('<') ? messageIdHeader : messageIdHeader ? `<${messageIdHeader}>` : undefined;\n const refs = [references, inReplyTo].filter(Boolean).join(' ').trim();\n const mimeType = contentType === 'html' ? 'text/html' : 'text/plain';\n const lines = [`To: ${toAddr}`, `Subject: ${replySubject}`, `In-Reply-To: ${inReplyTo ?? ''}`, `References: ${refs}`, 'MIME-Version: 1.0', `Content-Type: ${mimeType}; charset=UTF-8`, '', body].join('\\r\\n');\n const raw = b64url(lines);\n\n // Prepare request body with conditional threadId for exactOptionalPropertyTypes\n const threadId = fullData?.threadId ? String(fullData.threadId) : undefined;\n await gmail.users.messages.send({\n userId: 'me',\n requestBody: {\n raw: raw,\n ...(threadId && { threadId }),\n },\n });\n\n logger.info('gmail.message.respond sent reply', { id });\n\n const result: Output = {\n type: 'success' as const,\n id,\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.message.respond error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error responding to message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-respond',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ComposeContentTypeSchema","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","extractEmails","b64url","inputSchema","object","id","coerce","string","trim","min","describe","body","contentType","successBranchSchema","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","InvalidParams","info","replyToHdr","headers","fullData","gmail","version","auth","authContext","full","response","users","messages","get","userId","format","metadataHeaders","data","error","message","Error","String","InternalError","stack","undefined","headersArray","Array","isArray","payload","Object","fromEntries","map","h","header","name","value","fromHdr","From","from","toAddr","subject","Subject","messageIdHeader","references","References","replySubject","test","inReplyTo","startsWith","refs","filter","Boolean","join","mimeType","lines","raw","threadId","send","requestBody","content","text","JSON","stringify","structuredContent","createTool"],"mappings":"AAAA,SAASA,wBAAwB,QAAQ,eAAe;AAExD,SAASC,OAAO,QAAQ,sBAAsB;AAE9C,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAASE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACjE,SAASC,MAAM,QAAQ,aAAa;AACpC,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,aAAa,QAAQ,uCAAuC;AACrE,SAASC,MAAM,QAAQ,+BAA+B;AAEtD,MAAMC,cAAcH,EAAEI,MAAM,CAAC;IAC3BC,IAAIL,EAAEM,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;IAC7CC,MAAMX,EAAEM,MAAM,CAACC,MAAM,GAAGC,IAAI,GAAGC,GAAG,CAAC,GAAGC,QAAQ,CAAC;IAC/CE,aAAalB;AACf;AAEA,MAAMmB,sBAAsBb,EAAEI,MAAM,CAAC;IACnCU,MAAMd,EAAEe,OAAO,CAAC;IAChBV,IAAIL,EAAEO,MAAM,GAAGG,QAAQ,CAAC;AAC1B;AAEA,MAAMM,eAAehB,EAAEiB,kBAAkB,CAAC,QAAQ;IAACJ;IAAqBjB;CAAyB;AAEjG,MAAMsB,SAAS;IACbC,aAAa;IACbhB,aAAaA;IACba,cAAchB,EAAEI,MAAM,CAAC;QACrBgB,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEhB,EAAE,EAAEM,IAAI,EAAEC,WAAW,EAAS,EAAEU,KAAoB;IAC3E,MAAMC,SAASD,MAAMC,MAAM;IAE3B,IAAI,CAAClB,MAAM,CAACM,MAAM;QAChB,MAAM,IAAId,cAAcC,kBAAkB0B,aAAa,EAAE;IAC3D;IAEAD,OAAOE,IAAI,CAAC,gCAAgC;QAAEpB;QAAIO;IAAY;IAE9D,IAAI;YAgCcc,MACCC,OAEGA;YAZeC;QAtBnC,MAAMC,QAAQ9B,OAAO8B,KAAK,CAAC;YAAEC,SAAS;YAAMC,MAAMT,MAAMU,WAAW,CAACD,IAAI;QAAC;QAEzE,IAAIE;QACJ,IAAI;YACF,MAAMC,WAAW,MAAML,MAAMM,KAAK,CAACC,QAAQ,CAACC,GAAG,CAAC;gBAC9CC,QAAQ;gBACRjC,IAAIA;gBACJkC,QAAQ;gBACRC,iBAAiB;oBAAC;oBAAQ;oBAAM;oBAAY;oBAAW;oBAAc;oBAAc;oBAAe;iBAAO;YAC3G;YACAP,OAAOC,SAASO,IAAI;QACtB,EAAE,OAAOC,OAAO;YACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;YAChEnB,OAAOmB,KAAK,CAAC,qCAAqC;gBAAEA,OAAOC;YAAQ;YAEnE,MAAM,IAAI9C,cAAcC,kBAAkBgD,aAAa,EAAE,CAAC,iCAAiC,EAAEH,SAAS,EAAE;gBACtGI,OAAOL,iBAAiBE,QAAQF,MAAMK,KAAK,GAAGC;YAChD;QACF;QAEA,8BAA8B;QAC9B,MAAMpB,WAAWK;QACjB,MAAMgB,eAAeC,MAAMC,OAAO,CAACvB,qBAAAA,gCAAAA,oBAAAA,SAAUwB,OAAO,cAAjBxB,wCAAAA,kBAAmBD,OAAO,IAAIC,SAASwB,OAAO,CAACzB,OAAO,GAAG,EAAE;QAC9F,MAAMA,UAAU0B,OAAOC,WAAW,CAChCL,aAAaM,GAAG,CAAC,CAACC;gBAEDC,cAA2BA;YAD1C,MAAMA,SAASD;YACf,OAAO;gBAACX,QAAOY,eAAAA,OAAOC,IAAI,cAAXD,0BAAAA,eAAe;gBAAKZ,QAAOY,gBAAAA,OAAOE,KAAK,cAAZF,2BAAAA,gBAAgB;aAAI;QAChE;QAEF,MAAMG,UAAUjC,QAAQkC,IAAI,IAAIlC,QAAQmC,IAAI;QAC5C,MAAMpC,aAAaC,OAAO,CAAC,WAAW,IAAIA,OAAO,CAAC,WAAW;QAC7D,MAAMoC,UAAUrC,OAAAA,aAAazB,cAAcyB,WAAW,CAAC,EAAE,GAAGzB,cAAc2D,QAAQ,CAAC,EAAE,cAArElC,kBAAAA,OAA0E;QAC1F,MAAMsC,WAAWrC,QAAAA,QAAQsC,OAAO,IAAItC,QAAQqC,OAAO,cAAlCrC,mBAAAA,QAAuC;QACxD,MAAMuC,kBAAkBvC,OAAO,CAAC,aAAa,IAAIA,OAAO,CAAC,aAAa,IAAIA,OAAO,CAAC,aAAa;QAC/F,MAAMwC,cAAcxC,QAAAA,QAAQyC,UAAU,IAAIzC,QAAQwC,UAAU,cAAxCxC,mBAAAA,QAA6C;QACjE,MAAM0C,eAAe,QAAQC,IAAI,CAACN,WAAWA,UAAU,CAAC,IAAI,EAAEA,SAAS;QACvE,MAAMO,YAAYL,CAAAA,4BAAAA,sCAAAA,gBAAiBM,UAAU,CAAC,QAAON,kBAAkBA,kBAAkB,CAAC,CAAC,EAAEA,gBAAgB,CAAC,CAAC,GAAGlB;QAClH,MAAMyB,OAAO;YAACN;YAAYI;SAAU,CAACG,MAAM,CAACC,SAASC,IAAI,CAAC,KAAKpE,IAAI;QACnE,MAAMqE,WAAWjE,gBAAgB,SAAS,cAAc;QACxD,MAAMkE,QAAQ;YAAC,CAAC,IAAI,EAAEf,QAAQ;YAAE,CAAC,SAAS,EAAEM,cAAc;YAAE,CAAC,aAAa,EAAEE,sBAAAA,uBAAAA,YAAa,IAAI;YAAE,CAAC,YAAY,EAAEE,MAAM;YAAE;YAAqB,CAAC,cAAc,EAAEI,SAAS,eAAe,CAAC;YAAE;YAAIlE;SAAK,CAACiE,IAAI,CAAC;QACtM,MAAMG,MAAM7E,OAAO4E;QAEnB,gFAAgF;QAChF,MAAME,WAAWpD,CAAAA,qBAAAA,+BAAAA,SAAUoD,QAAQ,IAAGnC,OAAOjB,SAASoD,QAAQ,IAAIhC;QAClE,MAAMnB,MAAMM,KAAK,CAACC,QAAQ,CAAC6C,IAAI,CAAC;YAC9B3C,QAAQ;YACR4C,aAAa;gBACXH,KAAKA;gBACL,GAAIC,YAAY;oBAAEA;gBAAS,CAAC;YAC9B;QACF;QAEAzD,OAAOE,IAAI,CAAC,oCAAoC;YAAEpB;QAAG;QAErD,MAAMe,SAAiB;YACrBN,MAAM;YACNT;QACF;QAEA,OAAO;YACL8E,SAAS;gBACP;oBACErE,MAAM;oBACNsE,MAAMC,KAAKC,SAAS,CAAClE;gBACvB;aACD;YACDmE,mBAAmB;gBAAEnE;YAAO;QAC9B;IACF,EAAE,OAAOsB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChEnB,OAAOmB,KAAK,CAAC,+BAA+B;YAAEA,OAAOC;QAAQ;QAE7D,MAAM,IAAI9C,cAAcC,kBAAkBgD,aAAa,EAAE,CAAC,6BAA6B,EAAEH,SAAS,EAAE;YAClGI,OAAOL,iBAAiBE,QAAQF,MAAMK,KAAK,GAAGC;QAChD;IACF;AACF;AAEA,eAAe,SAASwC;IACtB,OAAO;QACL9B,MAAM;QACNxC;QACAG;IACF;AACF"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-respond.ts"],"sourcesContent":["import { ComposeContentTypeSchema } from '@mcp-z/email';\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 { google } from 'googleapis';\nimport { z } from 'zod';\nimport { extractEmails } from '../../email/parsing/headers-utils.ts';\nimport { b64url } from '../../lib/base64-encoding.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 reply to'),\n body: z.coerce.string().trim().min(1).describe('Reply body content (plain text or HTML)'),\n contentType: ComposeContentTypeSchema,\n});\n\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n id: z.string().describe('Original message ID that was replied to'),\n});\n\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Send a reply 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, body, contentType }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n if (!id || !body) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id or body');\n }\n\n logger.info('gmail.message.respond called', { id, contentType });\n\n try {\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n\n let full: unknown;\n try {\n const response = await gmail.users.messages.get({\n userId: 'me',\n id: id,\n format: 'metadata',\n metadataHeaders: ['From', 'To', 'Reply-To', 'Subject', 'Message-ID', 'References', 'In-Reply-To', 'Date'],\n });\n full = response.data;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.error('gmail.message.respond fetch error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error fetching message metadata: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n\n // Type-safe header extraction\n const fullData = full as { payload?: { headers?: unknown[] }; threadId?: unknown };\n const headersArray = Array.isArray(fullData?.payload?.headers) ? fullData.payload.headers : [];\n const headers = Object.fromEntries(\n headersArray.map((h: unknown) => {\n const header = h as { name?: unknown; value?: unknown };\n return [String(header.name ?? ''), String(header.value ?? '')];\n })\n );\n const fromHdr = headers.From || headers.from;\n const replyToHdr = headers['Reply-To'] || headers['reply-to'];\n const toAddr = (replyToHdr ? extractEmails(replyToHdr)[0] : extractEmails(fromHdr)[0]) ?? '';\n const subject = (headers.Subject || headers.subject) ?? '';\n const messageIdHeader = headers['Message-ID'] || headers['Message-Id'] || headers['message-id'];\n const references = (headers.References || headers.references) ?? '';\n const replySubject = /^re:/i.test(subject) ? subject : `Re: ${subject}`;\n const inReplyTo = messageIdHeader?.startsWith('<') ? messageIdHeader : messageIdHeader ? `<${messageIdHeader}>` : undefined;\n const refs = [references, inReplyTo].filter(Boolean).join(' ').trim();\n const mimeType = contentType === 'html' ? 'text/html' : 'text/plain';\n const lines = [`To: ${toAddr}`, `Subject: ${replySubject}`, `In-Reply-To: ${inReplyTo ?? ''}`, `References: ${refs}`, 'MIME-Version: 1.0', `Content-Type: ${mimeType}; charset=UTF-8`, '', body].join('\\r\\n');\n const raw = b64url(lines);\n\n // Prepare request body with conditional threadId for exactOptionalPropertyTypes\n const threadId = fullData?.threadId ? String(fullData.threadId) : undefined;\n await gmail.users.messages.send({\n userId: 'me',\n requestBody: {\n raw: raw,\n ...(threadId && { threadId }),\n },\n });\n\n logger.info('gmail.message.respond sent reply', { id });\n\n const result: Output = {\n type: 'success' as const,\n id,\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.message.respond error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error responding to message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-respond',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ComposeContentTypeSchema","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","extractEmails","b64url","googleAuth","inputSchema","object","id","coerce","string","trim","min","describe","body","contentType","successBranchSchema","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","InvalidParams","info","replyToHdr","headers","fullData","gmail","version","auth","authContext","full","response","users","messages","get","userId","format","metadataHeaders","data","error","message","Error","String","InternalError","stack","undefined","headersArray","Array","isArray","payload","Object","fromEntries","map","h","header","name","value","fromHdr","From","from","toAddr","subject","Subject","messageIdHeader","references","References","replySubject","test","inReplyTo","startsWith","refs","filter","Boolean","join","mimeType","lines","raw","threadId","send","requestBody","content","text","JSON","stringify","structuredContent","createTool"],"mappings":"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"}
@@ -8,6 +8,7 @@ import { z } from 'zod';
8
8
  import { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../constants.js';
9
9
  import { extractBodyFromPayload } from '../../email/parsing/html-processing.js';
10
10
  import { executeQuery as executeGmailQuery } from '../../email/querying/execute-query.js';
11
+ import { googleAuth } from '../../lib/google-auth.js';
11
12
  import { GmailQueryParameterSchema, parseGmailQueryParameter } from '../../schemas/gmail-query-schema.js';
12
13
  const inputSchema = z.object({
13
14
  query: GmailQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and rawGmailQuery for Gmail syntax.'),
@@ -70,7 +71,7 @@ async function handler({ query, pageSize = DEFAULT_PAGE_SIZE, pageToken, fields,
70
71
  });
71
72
  const gmail = google.gmail({
72
73
  version: 'v1',
73
- auth: extra.authContext.auth
74
+ auth: googleAuth(extra.authContext.auth)
74
75
  });
75
76
  const started = Date.now();
76
77
  const exec = await executeGmailQuery(parsedQuery, {
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-search.ts"],"sourcesContent":["import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\n/** Gmail message search using middleware-based auth pattern */\n\nimport { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { createFieldsSchema, createPaginationSchema, createShapeSchema, filterFields, parseFields, type ToolModule, toColumnarFormat } from '@mcp-z/server';\nimport { type gmail_v1, google } from 'googleapis';\nimport { z } from 'zod';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../constants.ts';\nimport { extractBodyFromPayload } from '../../email/parsing/html-processing.ts';\nimport { executeQuery as executeGmailQuery } from '../../email/querying/execute-query.ts';\nimport { GmailQueryParameterSchema, parseGmailQueryParameter } from '../../schemas/gmail-query-schema.ts';\n\nconst inputSchema = z.object({\n query: GmailQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and rawGmailQuery for Gmail syntax.'),\n fields: createFieldsSchema({\n availableFields: EMAIL_FIELDS,\n fieldDescriptions: EMAIL_FIELD_DESCRIPTIONS,\n commonPatterns: EMAIL_COMMON_PATTERNS,\n resourceName: 'email message',\n }),\n ...createPaginationSchema({ defaultPageSize: DEFAULT_PAGE_SIZE, maxPageSize: MAX_PAGE_SIZE, provider: 'gmail' }).shape,\n shape: createShapeSchema(),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schemas for different shapes\nconst successObjectsBranchSchema = z.object({\n type: z.literal('success'),\n shape: z.literal('objects'),\n items: z.array(EmailDetailSchema).describe('Matching email messages'),\n nextPageToken: z.string().optional().describe('Token for fetching next page of results'),\n});\n\nconst successArraysBranchSchema = z.object({\n type: z.literal('success'),\n shape: z.literal('arrays'),\n columns: z.array(z.string()).describe('Column names in canonical order'),\n rows: z.array(z.array(z.unknown())).describe('Row data matching column order'),\n nextPageToken: z.string().optional().describe('Token for fetching next page of results'),\n});\n\n// Output schema with auth_required support\n// Using z.union instead of discriminatedUnion since we have two success branches with different shapes\nconst outputSchema = z.union([successObjectsBranchSchema, successArraysBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Search Gmail messages using structured query objects with flexible field selection.',\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({ query, pageSize = DEFAULT_PAGE_SIZE, pageToken, fields, shape = 'arrays', contentType = 'text', excludeThreadHistory = false }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n try {\n const parsedQuery = parseGmailQueryParameter(query);\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n const includeBody = requestedFields === 'all' || requestedFields.has('body');\n\n logger.info('gmail.message.search called', {\n query: parsedQuery,\n pageSize,\n pageToken: pageToken ? '[provided]' : undefined,\n fields,\n includeBody,\n accountId: extra.authContext.accountId, // Available from middleware\n });\n\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n\n const started = Date.now();\n\n const exec = await executeGmailQuery(\n parsedQuery,\n {\n client: gmail,\n logger,\n pageSize,\n ...(pageToken !== undefined && { pageToken }),\n includeBody,\n },\n (full: unknown) => {\n // Type-safe property access with guards\n const fullData = full as gmail_v1.Schema$Message;\n\n const headersArray = Array.isArray(fullData?.payload?.headers) ? fullData.payload.headers : [];\n const headers = 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 mapped: Partial<EmailDetail> = {\n id: String(fullData?.id ?? ''),\n threadId: fullData?.threadId ? String(fullData.threadId) : undefined,\n from: headers?.From,\n to: headers?.To,\n subject: headers?.Subject,\n date: headers?.Date,\n snippet: fullData?.snippet ? String(fullData.snippet) : undefined,\n };\n\n if (includeBody) {\n const payload = fullData?.payload;\n // Cast to Schema$MessagePart for extractBodyFromPayload\n const body = payload ? extractBodyFromPayload(payload as gmail_v1.Schema$MessagePart, { contentType, excludeThreadHistory }) : '';\n if (body) {\n mapped.body = body;\n mapped.bodyContentType = contentType;\n }\n }\n return mapped;\n }\n );\n\n const items = exec.items;\n const metadata = exec.metadata;\n const durationMs = Date.now() - started;\n\n // Type-safe field filtering\n const filteredItems = items.map((item) => filterFields(item, requestedFields));\n\n logger.info('gmail.message.search results', { query, pageSize, resultCount: filteredItems.length, fields: fields || 'all' });\n logger.info('gmail.message.search metrics', { durationMs, metadata });\n\n // Type-safe metadata access\n const metadataObj = metadata as { nextPageToken?: string } | undefined;\n\n // Build result based on shape\n const result: Output =\n shape === 'arrays'\n ? {\n type: 'success' as const,\n shape: 'arrays' as const,\n ...toColumnarFormat(filteredItems, requestedFields, EMAIL_FIELDS),\n ...(metadataObj?.nextPageToken && { nextPageToken: metadataObj.nextPageToken }),\n }\n : {\n type: 'success' as const,\n shape: 'objects' as const,\n items: filteredItems,\n ...(metadataObj?.nextPageToken && { nextPageToken: metadataObj.nextPageToken }),\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.message.search error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error searching messages: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-search',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ProtocolError","ProtocolErrorCode","EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","schemas","AuthRequiredBranchSchema","createFieldsSchema","createPaginationSchema","createShapeSchema","filterFields","parseFields","toColumnarFormat","google","z","DEFAULT_PAGE_SIZE","MAX_PAGE_SIZE","extractBodyFromPayload","executeQuery","executeGmailQuery","GmailQueryParameterSchema","parseGmailQueryParameter","inputSchema","object","query","optional","describe","fields","availableFields","fieldDescriptions","commonPatterns","resourceName","defaultPageSize","maxPageSize","provider","shape","contentType","excludeThreadHistory","successObjectsBranchSchema","type","literal","items","array","nextPageToken","string","successArraysBranchSchema","columns","rows","unknown","outputSchema","union","config","description","result","handler","pageSize","pageToken","extra","logger","parsedQuery","requestedFields","includeBody","has","info","undefined","accountId","authContext","gmail","version","auth","started","Date","now","exec","client","full","fullData","headersArray","Array","isArray","payload","headers","Object","fromEntries","map","h","header","String","name","value","mapped","id","threadId","from","From","to","To","subject","Subject","date","snippet","body","bodyContentType","metadata","durationMs","filteredItems","item","resultCount","length","metadataObj","content","text","JSON","stringify","structuredContent","error","message","Error","InternalError","stack","createTool"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-search.ts"],"sourcesContent":["import { ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\n/** Gmail message search using middleware-based auth pattern */\n\nimport { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-google';\nimport { schemas } from '@mcp-z/oauth-google';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { createFieldsSchema, createPaginationSchema, createShapeSchema, filterFields, parseFields, type ToolModule, toColumnarFormat } from '@mcp-z/server';\nimport { type gmail_v1, google } from 'googleapis';\nimport { z } from 'zod';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../../constants.ts';\nimport { extractBodyFromPayload } from '../../email/parsing/html-processing.ts';\nimport { executeQuery as executeGmailQuery } from '../../email/querying/execute-query.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\nimport { GmailQueryParameterSchema, parseGmailQueryParameter } from '../../schemas/gmail-query-schema.ts';\n\nconst inputSchema = z.object({\n query: GmailQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and rawGmailQuery for Gmail syntax.'),\n fields: createFieldsSchema({\n availableFields: EMAIL_FIELDS,\n fieldDescriptions: EMAIL_FIELD_DESCRIPTIONS,\n commonPatterns: EMAIL_COMMON_PATTERNS,\n resourceName: 'email message',\n }),\n ...createPaginationSchema({ defaultPageSize: DEFAULT_PAGE_SIZE, maxPageSize: MAX_PAGE_SIZE, provider: 'gmail' }).shape,\n shape: createShapeSchema(),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schemas for different shapes\nconst successObjectsBranchSchema = z.object({\n type: z.literal('success'),\n shape: z.literal('objects'),\n items: z.array(EmailDetailSchema).describe('Matching email messages'),\n nextPageToken: z.string().optional().describe('Token for fetching next page of results'),\n});\n\nconst successArraysBranchSchema = z.object({\n type: z.literal('success'),\n shape: z.literal('arrays'),\n columns: z.array(z.string()).describe('Column names in canonical order'),\n rows: z.array(z.array(z.unknown())).describe('Row data matching column order'),\n nextPageToken: z.string().optional().describe('Token for fetching next page of results'),\n});\n\n// Output schema with auth_required support\n// Using z.union instead of discriminatedUnion since we have two success branches with different shapes\nconst outputSchema = z.union([successObjectsBranchSchema, successArraysBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Search Gmail messages using structured query objects with flexible field selection.',\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({ query, pageSize = DEFAULT_PAGE_SIZE, pageToken, fields, shape = 'arrays', contentType = 'text', excludeThreadHistory = false }: Input, extra: EnrichedExtra) {\n const logger = extra.logger;\n\n try {\n const parsedQuery = parseGmailQueryParameter(query);\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n const includeBody = requestedFields === 'all' || requestedFields.has('body');\n\n logger.info('gmail.message.search called', {\n query: parsedQuery,\n pageSize,\n pageToken: pageToken ? '[provided]' : undefined,\n fields,\n includeBody,\n accountId: extra.authContext.accountId, // Available from middleware\n });\n\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n\n const started = Date.now();\n\n const exec = await executeGmailQuery(\n parsedQuery,\n {\n client: gmail,\n logger,\n pageSize,\n ...(pageToken !== undefined && { pageToken }),\n includeBody,\n },\n (full: unknown) => {\n // Type-safe property access with guards\n const fullData = full as gmail_v1.Schema$Message;\n\n const headersArray = Array.isArray(fullData?.payload?.headers) ? fullData.payload.headers : [];\n const headers = 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 mapped: Partial<EmailDetail> = {\n id: String(fullData?.id ?? ''),\n threadId: fullData?.threadId ? String(fullData.threadId) : undefined,\n from: headers?.From,\n to: headers?.To,\n subject: headers?.Subject,\n date: headers?.Date,\n snippet: fullData?.snippet ? String(fullData.snippet) : undefined,\n };\n\n if (includeBody) {\n const payload = fullData?.payload;\n // Cast to Schema$MessagePart for extractBodyFromPayload\n const body = payload ? extractBodyFromPayload(payload as gmail_v1.Schema$MessagePart, { contentType, excludeThreadHistory }) : '';\n if (body) {\n mapped.body = body;\n mapped.bodyContentType = contentType;\n }\n }\n return mapped;\n }\n );\n\n const items = exec.items;\n const metadata = exec.metadata;\n const durationMs = Date.now() - started;\n\n // Type-safe field filtering\n const filteredItems = items.map((item) => filterFields(item, requestedFields));\n\n logger.info('gmail.message.search results', { query, pageSize, resultCount: filteredItems.length, fields: fields || 'all' });\n logger.info('gmail.message.search metrics', { durationMs, metadata });\n\n // Type-safe metadata access\n const metadataObj = metadata as { nextPageToken?: string } | undefined;\n\n // Build result based on shape\n const result: Output =\n shape === 'arrays'\n ? {\n type: 'success' as const,\n shape: 'arrays' as const,\n ...toColumnarFormat(filteredItems, requestedFields, EMAIL_FIELDS),\n ...(metadataObj?.nextPageToken && { nextPageToken: metadataObj.nextPageToken }),\n }\n : {\n type: 'success' as const,\n shape: 'objects' as const,\n items: filteredItems,\n ...(metadataObj?.nextPageToken && { nextPageToken: metadataObj.nextPageToken }),\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.message.search error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error searching messages: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-search',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ProtocolError","ProtocolErrorCode","EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","schemas","AuthRequiredBranchSchema","createFieldsSchema","createPaginationSchema","createShapeSchema","filterFields","parseFields","toColumnarFormat","google","z","DEFAULT_PAGE_SIZE","MAX_PAGE_SIZE","extractBodyFromPayload","executeQuery","executeGmailQuery","googleAuth","GmailQueryParameterSchema","parseGmailQueryParameter","inputSchema","object","query","optional","describe","fields","availableFields","fieldDescriptions","commonPatterns","resourceName","defaultPageSize","maxPageSize","provider","shape","contentType","excludeThreadHistory","successObjectsBranchSchema","type","literal","items","array","nextPageToken","string","successArraysBranchSchema","columns","rows","unknown","outputSchema","union","config","description","result","handler","pageSize","pageToken","extra","logger","parsedQuery","requestedFields","includeBody","has","info","undefined","accountId","authContext","gmail","version","auth","started","Date","now","exec","client","full","fullData","headersArray","Array","isArray","payload","headers","Object","fromEntries","map","h","header","String","name","value","mapped","id","threadId","from","From","to","To","subject","Subject","date","snippet","body","bodyContentType","metadata","durationMs","filteredItems","item","resultCount","length","metadataObj","content","text","JSON","stringify","structuredContent","error","message","Error","InternalError","stack","createTool"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { google } from 'googleapis';
6
6
  import { z } from 'zod';
7
7
  import { buildRfc822FromArgs } from '../../email/composition/rfc822-builder.js';
8
8
  import { b64url } from '../../lib/base64-encoding.js';
9
+ import { googleAuth } from '../../lib/google-auth.js';
9
10
  const inputSchema = z.object({
10
11
  to: createEmailRecipientsSchema('to', true),
11
12
  cc: createEmailRecipientsSchema('cc', false),
@@ -57,7 +58,7 @@ async function handler(params, extra) {
57
58
  const encodedMessage = b64url(raw);
58
59
  const gmail = google.gmail({
59
60
  version: 'v1',
60
- auth: extra.authContext.auth
61
+ auth: googleAuth(extra.authContext.auth)
61
62
  });
62
63
  const sendRes = await gmail.users.messages.send({
63
64
  userId: 'me',
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-send.ts"],"sourcesContent":["import { ComposeContentTypeSchema, createEmailRecipientsSchema, createMessageResultSchema } from '@mcp-z/email';\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 { google } from 'googleapis';\nimport { z } from 'zod';\nimport { buildRfc822FromArgs } from '../../email/composition/rfc822-builder.ts';\nimport { b64url } from '../../lib/base64-encoding.ts';\n\nconst inputSchema = z.object({\n to: createEmailRecipientsSchema('to', true),\n cc: createEmailRecipientsSchema('cc', false),\n bcc: createEmailRecipientsSchema('bcc', false),\n subject: z.string().describe('Message subject').default(''),\n body: z.string().trim().min(1).describe('Email body content (plain text or HTML)'),\n contentType: ComposeContentTypeSchema,\n});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n item: createMessageResultSchema('gmail'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Send an email message through Gmail',\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(params: Input, extra: EnrichedExtra) {\n const { to, cc, bcc, subject, body, contentType } = params;\n const logger = extra.logger;\n logger.info('gmail.message.send called', { to, subject, contentType });\n\n if (!to) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing required field: to');\n }\n\n try {\n // Build RFC822 message - only include optional headers when defined to satisfy\n // exactOptionalPropertyTypes (avoid passing `undefined` into optional props)\n const msgArgs: { to: string; cc?: string; bcc?: string; subject?: string; body: string; contentType: 'text' | 'html' } = { to, body, contentType };\n if (cc !== undefined) msgArgs.cc = cc;\n if (bcc !== undefined) msgArgs.bcc = bcc;\n if (subject !== undefined) msgArgs.subject = subject;\n\n const raw = buildRfc822FromArgs(msgArgs);\n const encodedMessage = b64url(raw);\n\n const gmail = google.gmail({ version: 'v1', auth: extra.authContext.auth });\n\n const sendRes = await gmail.users.messages.send({\n userId: 'me',\n requestBody: { raw: encodedMessage },\n });\n const sendData = sendRes.data;\n const messageId = sendData.id || 'unknown';\n logger.info('Gmail: sent message successfully', { id: messageId });\n logger.info('gmail.message.send result (typed)', { to, subject, messageId });\n\n const totalRecipients = (Array.isArray(to) ? to.length : 1) + (cc ? (Array.isArray(cc) ? cc.length : 1) : 0) + (bcc ? (Array.isArray(bcc) ? bcc.length : 1) : 0);\n const result: Output = {\n type: 'success' as const,\n item: {\n id: messageId,\n sentAt: new Date().toISOString(),\n recipientCount: totalRecipients,\n webLink: `https://mail.google.com/mail/u/0/#sent/${messageId}`,\n },\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.message.send error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error sending message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-send',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ComposeContentTypeSchema","createEmailRecipientsSchema","createMessageResultSchema","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","buildRfc822FromArgs","b64url","inputSchema","object","to","cc","bcc","subject","string","describe","default","body","trim","min","contentType","successBranchSchema","type","literal","item","outputSchema","discriminatedUnion","config","description","result","handler","params","extra","logger","info","InvalidParams","msgArgs","undefined","raw","encodedMessage","gmail","version","auth","authContext","sendRes","users","messages","send","userId","requestBody","sendData","data","messageId","id","totalRecipients","Array","isArray","length","sentAt","Date","toISOString","recipientCount","webLink","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","createTool","name"],"mappings":"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"}
1
+ {"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-gmail/src/mcp/tools/message-send.ts"],"sourcesContent":["import { ComposeContentTypeSchema, createEmailRecipientsSchema, createMessageResultSchema } from '@mcp-z/email';\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 { google } from 'googleapis';\nimport { z } from 'zod';\nimport { buildRfc822FromArgs } from '../../email/composition/rfc822-builder.ts';\nimport { b64url } from '../../lib/base64-encoding.ts';\nimport { googleAuth } from '../../lib/google-auth.ts';\n\nconst inputSchema = z.object({\n to: createEmailRecipientsSchema('to', true),\n cc: createEmailRecipientsSchema('cc', false),\n bcc: createEmailRecipientsSchema('bcc', false),\n subject: z.string().describe('Message subject').default(''),\n body: z.string().trim().min(1).describe('Email body content (plain text or HTML)'),\n contentType: ComposeContentTypeSchema,\n});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n item: createMessageResultSchema('gmail'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Send an email message through Gmail',\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(params: Input, extra: EnrichedExtra) {\n const { to, cc, bcc, subject, body, contentType } = params;\n const logger = extra.logger;\n logger.info('gmail.message.send called', { to, subject, contentType });\n\n if (!to) {\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing required field: to');\n }\n\n try {\n // Build RFC822 message - only include optional headers when defined to satisfy\n // exactOptionalPropertyTypes (avoid passing `undefined` into optional props)\n const msgArgs: { to: string; cc?: string; bcc?: string; subject?: string; body: string; contentType: 'text' | 'html' } = { to, body, contentType };\n if (cc !== undefined) msgArgs.cc = cc;\n if (bcc !== undefined) msgArgs.bcc = bcc;\n if (subject !== undefined) msgArgs.subject = subject;\n\n const raw = buildRfc822FromArgs(msgArgs);\n const encodedMessage = b64url(raw);\n\n const gmail = google.gmail({ version: 'v1', auth: googleAuth(extra.authContext.auth) });\n\n const sendRes = await gmail.users.messages.send({\n userId: 'me',\n requestBody: { raw: encodedMessage },\n });\n const sendData = sendRes.data;\n const messageId = sendData.id || 'unknown';\n logger.info('Gmail: sent message successfully', { id: messageId });\n logger.info('gmail.message.send result (typed)', { to, subject, messageId });\n\n const totalRecipients = (Array.isArray(to) ? to.length : 1) + (cc ? (Array.isArray(cc) ? cc.length : 1) : 0) + (bcc ? (Array.isArray(bcc) ? bcc.length : 1) : 0);\n const result: Output = {\n type: 'success' as const,\n item: {\n id: messageId,\n sentAt: new Date().toISOString(),\n recipientCount: totalRecipients,\n webLink: `https://mail.google.com/mail/u/0/#sent/${messageId}`,\n },\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.message.send error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error sending message: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'message-send',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["ComposeContentTypeSchema","createEmailRecipientsSchema","createMessageResultSchema","schemas","AuthRequiredBranchSchema","ProtocolError","ProtocolErrorCode","google","z","buildRfc822FromArgs","b64url","googleAuth","inputSchema","object","to","cc","bcc","subject","string","describe","default","body","trim","min","contentType","successBranchSchema","type","literal","item","outputSchema","discriminatedUnion","config","description","result","handler","params","extra","logger","info","InvalidParams","msgArgs","undefined","raw","encodedMessage","gmail","version","auth","authContext","sendRes","users","messages","send","userId","requestBody","sendData","data","messageId","id","totalRecipients","Array","isArray","length","sentAt","Date","toISOString","recipientCount","webLink","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","createTool","name"],"mappings":"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"}
@@ -10,6 +10,7 @@ import { z } from 'zod';
10
10
  import { DEFAULT_PAGE_SIZE } from '../../constants.js';
11
11
  import { extractBodyFromPayload } from '../../email/parsing/html-processing.js';
12
12
  import { executeQuery as executeGmailQuery } from '../../email/querying/execute-query.js';
13
+ import { googleAuth } from '../../lib/google-auth.js';
13
14
  import { GmailQueryParameterSchema, parseGmailQueryParameter } from '../../schemas/gmail-query-schema.js';
14
15
  const DEFAULT_MAX_ITEMS = 10000;
15
16
  const MAX_EXPORT_ITEMS = 50000;
@@ -70,7 +71,7 @@ const config = {
70
71
  });
71
72
  const gmail = google.gmail({
72
73
  version: 'v1',
73
- auth: extra.authContext.auth
74
+ auth: googleAuth(extra.authContext.auth)
74
75
  });
75
76
  // Create CSV headers (all email fields)
76
77
  const csvHeaders = [