@mcp-z/mcp-outlook 2.2.2 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/constants.js.map +1 -1
- package/dist/cjs/email/composition/outlook-message-builder.js.map +1 -1
- package/dist/cjs/email/messages/messages.js.map +1 -1
- package/dist/cjs/email/parsing/header-parsing.js.map +1 -1
- package/dist/cjs/email/parsing/message-extraction.js.map +1 -1
- package/dist/cjs/email/parsing/message-mapping.js.map +1 -1
- package/dist/cjs/email/querying/client-filter.js.map +1 -1
- package/dist/cjs/email/querying/execute-query.js.map +1 -1
- package/dist/cjs/email/querying/pagination-token.js.map +1 -1
- package/dist/cjs/email/querying/query-builder.js.map +1 -1
- package/dist/cjs/email/querying/search-execution.js.map +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/lib/create-store.js.map +1 -1
- package/dist/cjs/lib/messages-to-row.js.map +1 -1
- package/dist/cjs/lib/outlook/index.js.map +1 -1
- package/dist/cjs/lib/outlook/types.js.map +1 -1
- package/dist/cjs/mcp/index.js.map +1 -1
- package/dist/cjs/mcp/prompts/draft-email.js.map +1 -1
- package/dist/cjs/mcp/prompts/index.js.map +1 -1
- package/dist/cjs/mcp/prompts/query-syntax.js.map +1 -1
- package/dist/cjs/mcp/resources/email.js.map +1 -1
- package/dist/cjs/mcp/resources/index.js.map +1 -1
- package/dist/cjs/mcp/tools/categories-list.js.map +1 -1
- package/dist/cjs/mcp/tools/index.js.map +1 -1
- package/dist/cjs/mcp/tools/label-add.js.map +1 -1
- package/dist/cjs/mcp/tools/label-delete.js.map +1 -1
- package/dist/cjs/mcp/tools/labels-list.js.map +1 -1
- package/dist/cjs/mcp/tools/message-get.js.map +1 -1
- package/dist/cjs/mcp/tools/message-mark-read.js.map +1 -1
- package/dist/cjs/mcp/tools/message-move-to-trash.js.map +1 -1
- package/dist/cjs/mcp/tools/message-respond.js.map +1 -1
- package/dist/cjs/mcp/tools/message-search.js.map +1 -1
- package/dist/cjs/mcp/tools/message-send.js.map +1 -1
- package/dist/cjs/mcp/tools/messages-export-csv.js.map +1 -1
- package/dist/cjs/schemas/index.js.map +1 -1
- package/dist/cjs/schemas/outlook-query-schema.js.map +1 -1
- package/dist/cjs/schemas/outlook-validation.js.map +1 -1
- package/dist/cjs/setup/config.js.map +1 -1
- package/dist/cjs/setup/http.js.map +1 -1
- package/dist/cjs/setup/index.js.map +1 -1
- package/dist/cjs/setup/oauth-microsoft.js.map +1 -1
- package/dist/cjs/setup/runtime.js.map +1 -1
- package/dist/cjs/setup/stdio.js.map +1 -1
- package/dist/cjs/setup/version-help.js.map +1 -1
- package/dist/esm/constants.js.map +1 -1
- package/dist/esm/email/composition/outlook-message-builder.js.map +1 -1
- package/dist/esm/email/messages/messages.js.map +1 -1
- package/dist/esm/email/parsing/header-parsing.js.map +1 -1
- package/dist/esm/email/parsing/message-extraction.js.map +1 -1
- package/dist/esm/email/parsing/message-mapping.js.map +1 -1
- package/dist/esm/email/querying/client-filter.js.map +1 -1
- package/dist/esm/email/querying/execute-query.js.map +1 -1
- package/dist/esm/email/querying/pagination-token.js.map +1 -1
- package/dist/esm/email/querying/query-builder.js.map +1 -1
- package/dist/esm/email/querying/search-execution.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/lib/create-store.js.map +1 -1
- package/dist/esm/lib/messages-to-row.js.map +1 -1
- package/dist/esm/lib/outlook/index.js.map +1 -1
- package/dist/esm/lib/outlook/types.js.map +1 -1
- package/dist/esm/mcp/index.js.map +1 -1
- package/dist/esm/mcp/prompts/draft-email.js.map +1 -1
- package/dist/esm/mcp/prompts/index.js.map +1 -1
- package/dist/esm/mcp/prompts/query-syntax.js.map +1 -1
- package/dist/esm/mcp/resources/email.js.map +1 -1
- package/dist/esm/mcp/resources/index.js.map +1 -1
- package/dist/esm/mcp/tools/categories-list.js.map +1 -1
- package/dist/esm/mcp/tools/index.js.map +1 -1
- package/dist/esm/mcp/tools/label-add.js.map +1 -1
- package/dist/esm/mcp/tools/label-delete.js.map +1 -1
- package/dist/esm/mcp/tools/labels-list.js.map +1 -1
- package/dist/esm/mcp/tools/message-get.js.map +1 -1
- package/dist/esm/mcp/tools/message-mark-read.js.map +1 -1
- package/dist/esm/mcp/tools/message-move-to-trash.js.map +1 -1
- package/dist/esm/mcp/tools/message-respond.js.map +1 -1
- package/dist/esm/mcp/tools/message-search.js.map +1 -1
- package/dist/esm/mcp/tools/message-send.js.map +1 -1
- package/dist/esm/mcp/tools/messages-export-csv.js.map +1 -1
- package/dist/esm/schemas/index.js.map +1 -1
- package/dist/esm/schemas/outlook-query-schema.js.map +1 -1
- package/dist/esm/schemas/outlook-validation.js.map +1 -1
- package/dist/esm/setup/config.js.map +1 -1
- package/dist/esm/setup/http.js.map +1 -1
- package/dist/esm/setup/index.js.map +1 -1
- package/dist/esm/setup/oauth-microsoft.js.map +1 -1
- package/dist/esm/setup/runtime.js.map +1 -1
- package/dist/esm/setup/stdio.js.map +1 -1
- package/dist/esm/setup/version-help.js.map +1 -1
- package/dist/esm/types.js.map +1 -1
- package/package.json +6 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-outlook/src/mcp/tools/label-delete.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst BatchResultSchema = z.object({\n totalRequested: z.number().describe('Total number of categories requested to delete'),\n successCount: z.number().describe('Number of categories successfully deleted'),\n failureCount: z.number().describe('Number of categories that failed to delete'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Category 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 category'),\n});\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).max(MAX_BATCH_SIZE).describe('Outlook category IDs to delete'),\n});\n\n// Success branch schema\nconst successBranchSchema = BatchResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Delete Outlook categories permanently (irreversible). Categories organize messages by color and name.',\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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook-label-delete called', { count: ids.length });\n\n // Validate IDs for Outlook-specific constraints\n // Note: Schema already validates non-empty, trimmed strings with min/max length\n // This check enforces business rule: Outlook category IDs cannot contain path separators or angle brackets\n const invalidIds: string[] = [];\n for (const id of ids) {\n if (id.includes('/') || id.includes('\\\\') || id.includes('<') || id.includes('>')) {\n invalidIds.push(id);\n }\n }\n\n if (invalidIds.length > 0) {\n logger.info('outlook-label-delete found invalid ids', { invalidIds, count: invalidIds.length });\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs (contain invalid characters): ${invalidIds.join(', ')}`);\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\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 < ids.length; i += CHUNK_SIZE) {\n const chunk = ids.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(ids.length / CHUNK_SIZE) });\n\n // Delete categories sequentially to avoid API lock conflicts\n const chunkResults: Array<{ status: string; value?: unknown; reason?: unknown }> = [];\n for (const id of chunk) {\n try {\n await graph.api(`/me/outlook/masterCategories/${encodeURIComponent(id)}`).delete();\n chunkResults.push({ status: 'fulfilled', value: { id, success: true } });\n } catch (error) {\n chunkResults.push({ status: 'rejected', reason: error });\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 const result: Output = {\n type: 'success' as const,\n totalRequested: ids.length,\n successCount,\n failureCount,\n results: allResults,\n };\n\n logger.info('outlook-label-delete completed', {\n totalRequested: ids.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(ids.length / CHUNK_SIZE),\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('outlook-label-delete error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error deleting categories: ${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","Client","z","CHUNK_SIZE","MAX_BATCH_SIZE","BatchResultSchema","object","totalRequested","number","describe","successCount","failureCount","results","array","id","string","success","boolean","error","optional","inputSchema","ids","coerce","trim","min","max","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","invalidIds","includes","push","InvalidParams","join","graph","initWithMiddleware","authProvider","authContext","auth","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","api","encodeURIComponent","delete","status","value","reason","processedChunkResults","map","Error","errorMessage","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/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/label-delete.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst BatchResultSchema = z.object({\n totalRequested: z.number().describe('Total number of categories requested to delete'),\n successCount: z.number().describe('Number of categories successfully deleted'),\n failureCount: z.number().describe('Number of categories that failed to delete'),\n results: z\n .array(\n z.object({\n id: z.string().describe('Category 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 category'),\n});\n\nconst inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).max(MAX_BATCH_SIZE).describe('Outlook category IDs to delete'),\n});\n\n// Success branch schema\nconst successBranchSchema = BatchResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Delete Outlook categories permanently (irreversible). Categories organize messages by color and name.',\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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook-label-delete called', { count: ids.length });\n\n // Validate IDs for Outlook-specific constraints\n // Note: Schema already validates non-empty, trimmed strings with min/max length\n // This check enforces business rule: Outlook category IDs cannot contain path separators or angle brackets\n const invalidIds: string[] = [];\n for (const id of ids) {\n if (id.includes('/') || id.includes('\\\\') || id.includes('<') || id.includes('>')) {\n invalidIds.push(id);\n }\n }\n\n if (invalidIds.length > 0) {\n logger.info('outlook-label-delete found invalid ids', { invalidIds, count: invalidIds.length });\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs (contain invalid characters): ${invalidIds.join(', ')}`);\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\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 < ids.length; i += CHUNK_SIZE) {\n const chunk = ids.slice(i, i + CHUNK_SIZE);\n logger.info('Processing chunk', { chunkIndex: i / CHUNK_SIZE + 1, chunkSize: chunk.length, totalChunks: Math.ceil(ids.length / CHUNK_SIZE) });\n\n // Delete categories sequentially to avoid API lock conflicts\n const chunkResults: Array<{ status: string; value?: unknown; reason?: unknown }> = [];\n for (const id of chunk) {\n try {\n await graph.api(`/me/outlook/masterCategories/${encodeURIComponent(id)}`).delete();\n chunkResults.push({ status: 'fulfilled', value: { id, success: true } });\n } catch (error) {\n chunkResults.push({ status: 'rejected', reason: error });\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 const result: Output = {\n type: 'success' as const,\n totalRequested: ids.length,\n successCount,\n failureCount,\n results: allResults,\n };\n\n logger.info('outlook-label-delete completed', {\n totalRequested: ids.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(ids.length / CHUNK_SIZE),\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('outlook-label-delete error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error deleting categories: ${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","Client","z","CHUNK_SIZE","MAX_BATCH_SIZE","BatchResultSchema","object","totalRequested","number","describe","successCount","failureCount","results","array","id","string","success","boolean","error","optional","inputSchema","ids","coerce","trim","min","max","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","invalidIds","includes","push","InvalidParams","join","graph","initWithMiddleware","authProvider","authContext","auth","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","api","encodeURIComponent","delete","status","value","reason","processedChunkResults","map","Error","errorMessage","message","String","filter","r","chunksProcessed","content","text","JSON","stringify","structuredContent","InternalError","stack","undefined","createTool","name"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/labels-list.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { z } from 'zod';\nimport { OutlookCategorySchema } from '../../schemas/index.ts';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\n/**\n * Input schema for the labels-list tool\n *\n * Defines the validation schema for input parameters.\n */\nexport const inputSchema = z.object({});\n\n// Success branch schema\nconst successBranchSchema = z.object({\n type: z.literal('success'),\n items: z.array(OutlookCategorySchema),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'List Outlook categories for label: query syntax. Case-sensitive.',\n inputSchema: inputSchema,\n outputSchema: z.object({\n result: outputSchema,\n }),\n} as const;\n\n/**\n * Input type for the labels-list tool\n *\n * Represents the input parameters for listing Outlook labels.\n */\nexport type Input = z.infer<typeof inputSchema>;\nexport type Output = z.infer<typeof outputSchema>;\n\nasync function handler(_: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook.labels.list called');\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n const started = Date.now();\n\n // Call Microsoft Graph API to get master categories (same as categories tool)\n const response = await graph.api('/me/outlook/masterCategories').get();\n const categories = Array.isArray(response.value) ? response.value : [];\n\n const durationMs = Date.now() - started;\n logger.info('outlook.labels.list returning', { labelsCount: categories.length });\n logger.info('outlook.labels.list metrics', { durationMs });\n\n const result: Output = {\n type: 'success' as const,\n items: categories.map((category: MicrosoftGraph.OutlookCategory) => ({\n id: category.id || undefined,\n displayName: category.displayName || undefined,\n color: category.color || undefined,\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('outlook.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","ProtocolError","ProtocolErrorCode","Client","z","OutlookCategorySchema","AuthRequiredBranchSchema","inputSchema","object","successBranchSchema","type","literal","items","array","outputSchema","discriminatedUnion","config","description","result","handler","_","extra","logger","info","graph","initWithMiddleware","authProvider","authContext","auth","started","Date","now","response","api","get","categories","Array","isArray","value","durationMs","labelsCount","length","map","category","id","undefined","displayName","color","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","createTool","name"],"mappings":"AACA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,SAA8BC,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACtF,SAASC,MAAM,QAAQ,oCAAoC;AAE3D,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,qBAAqB,QAAQ,yBAAyB;AAE/D,MAAM,EAAEC,wBAAwB,EAAE,GAAGN;AAErC;;;;CAIC,GACD,OAAO,MAAMO,cAAcH,EAAEI,MAAM,CAAC,CAAC,GAAG;AAExC,wBAAwB;AACxB,MAAMC,sBAAsBL,EAAEI,MAAM,CAAC;IACnCE,MAAMN,EAAEO,OAAO,CAAC;IAChBC,OAAOR,EAAES,KAAK,CAACR;AACjB;AAEA,2CAA2C;AAC3C,MAAMS,eAAeV,EAAEW,kBAAkB,CAAC,QAAQ;IAACN;IAAqBH;CAAyB;AAEjG,MAAMU,SAAS;IACbC,aAAa;IACbV,aAAaA;IACbO,cAAcV,EAAEI,MAAM,CAAC;QACrBU,QAAQJ;IACV;AACF;AAUA,eAAeK,QAAQC,CAAQ,EAAEC,KAAoB;IACnD,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC;IAEZ,IAAI;QACF,MAAMC,QAAQrB,OAAOsB,kBAAkB,CAAC;YAAEC,cAAcL,MAAMM,WAAW,CAACC,IAAI;QAAC;QAC/E,MAAMC,UAAUC,KAAKC,GAAG;QAExB,8EAA8E;QAC9E,MAAMC,WAAW,MAAMR,MAAMS,GAAG,CAAC,gCAAgCC,GAAG;QACpE,MAAMC,aAAaC,MAAMC,OAAO,CAACL,SAASM,KAAK,IAAIN,SAASM,KAAK,GAAG,EAAE;QAEtE,MAAMC,aAAaT,KAAKC,GAAG,KAAKF;QAChCP,OAAOC,IAAI,CAAC,iCAAiC;YAAEiB,aAAaL,WAAWM,MAAM;QAAC;QAC9EnB,OAAOC,IAAI,CAAC,+BAA+B;YAAEgB;QAAW;QAExD,MAAMrB,SAAiB;YACrBR,MAAM;YACNE,OAAOuB,WAAWO,GAAG,CAAC,CAACC,WAA8C,CAAA;oBACnEC,IAAID,SAASC,EAAE,IAAIC;oBACnBC,aAAaH,SAASG,WAAW,IAAID;oBACrCE,OAAOJ,SAASI,KAAK,IAAIF;gBAC3B,CAAA;QACF;QAEA,OAAO;YACLG,SAAS;gBACP;oBACEtC,MAAM;oBACNuC,MAAMC,KAAKC,SAAS,CAACjC;gBACvB;aACD;YACDkC,mBAAmB;gBAAElC;YAAO;QAC9B;IACF,EAAE,OAAOmC,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChE/B,OAAO+B,KAAK,CAAC,6BAA6B;YAAEA,OAAOC;QAAQ;QAE3D,MAAM,IAAIrD,cAAcC,kBAAkBuD,aAAa,EAAE,CAAC,sBAAsB,EAAEH,SAAS,EAAE;YAC3FI,OAAOL,iBAAiBE,QAAQF,MAAMK,KAAK,GAAGb;QAChD;IACF;AACF;AAEA,eAAe,SAASc;IACtB,OAAO;QACLC,MAAM;QACN5C;QACAG;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-get.ts"],"sourcesContent":["import { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, EmailDetailSchema, ExcludeThreadHistorySchema, extractCurrentMessageFromHtml, extractCurrentMessageFromHtmlToText, normalizeDateToISO as toIsoUtc } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { type CallToolResult, createFieldsSchema, filterFields, ProtocolError, ProtocolErrorCode, parseFields, type ToolModule } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { z } from 'zod';\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Outlook 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 - uses item: wrapper for consistency with standard vocabulary\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 an Outlook 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): Promise<CallToolResult> {\n const logger = extra.logger;\n\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n\n logger.info('outlook.message.get called', { id, fields: fields || 'all' });\n\n if (!id) {\n logger.info('outlook.message.get missing id');\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n const message = (await graph.api(`/me/messages/${encodeURIComponent(id)}`).get()) as MicrosoftGraph.Message;\n\n // Process body based on contentType and excludeThreadHistory options\n let bodyContent = message.body?.content ?? '';\n const isHtml = message.body?.contentType?.toLowerCase() === 'html';\n\n if (isHtml && excludeThreadHistory) {\n // Remove thread history from HTML\n bodyContent = extractCurrentMessageFromHtml(bodyContent);\n }\n\n if (isHtml && contentType === 'text') {\n // Convert HTML to plain text (thread extraction happens inside if excludeThreadHistory was true)\n bodyContent = excludeThreadHistory ? extractCurrentMessageFromHtmlToText(bodyContent) : extractCurrentMessageFromHtmlToText(message.body?.content ?? '');\n }\n\n // Build full message data\n const payload = {\n id: message.id,\n subject: message.subject,\n from: message.from?.emailAddress?.address,\n date: toIsoUtc(message.receivedDateTime) || message.receivedDateTime,\n snippet: message.bodyPreview,\n body: bodyContent,\n bodyContentType: contentType,\n };\n\n // Filter based on requested fields\n const filteredPayload = filterFields(payload, requestedFields);\n\n logger.info('outlook.message.get success', { id: payload.id, subject: payload.subject, from: payload.from, date: payload.date, fields: fields || 'all' });\n\n const result: Output = {\n type: 'success' as const,\n item: filteredPayload as z.infer<typeof EmailDetailSchema>,\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('outlook.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","extractCurrentMessageFromHtml","extractCurrentMessageFromHtmlToText","normalizeDateToISO","toIsoUtc","schemas","AuthRequiredBranchSchema","createFieldsSchema","filterFields","ProtocolError","ProtocolErrorCode","parseFields","Client","z","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","InvalidParams","message","graph","initWithMiddleware","authProvider","authContext","auth","api","encodeURIComponent","get","bodyContent","body","content","isHtml","toLowerCase","payload","subject","from","emailAddress","address","date","receivedDateTime","snippet","bodyPreview","bodyContentType","filteredPayload","text","JSON","stringify","structuredContent","error","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-mark-read.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\n\nconst SuccessSchema = z.object({\n success: z.boolean().describe('Whether the operation completed successfully'),\n id: z.string().optional().describe('Message ID that was marked as read'),\n});\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Outlook message ID to mark as read'),\n});\n\n// Success branch schema\nconst successBranchSchema = SuccessSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Mark an Outlook 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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook-message-mark-read called', { id });\n\n if (!id) {\n logger.info('outlook-message-mark-read missing id');\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id');\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n await graph.api(`/me/messages/${encodeURIComponent(id)}`).update({ isRead: true });\n\n logger.info('outlook-message-mark-read success', { id });\n\n const result: Output = {\n type: 'success' as const,\n success: true,\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('outlook-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","Client","z","SuccessSchema","object","success","boolean","describe","id","string","optional","inputSchema","coerce","trim","min","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","InvalidParams","graph","initWithMiddleware","authProvider","authContext","auth","api","encodeURIComponent","update","isRead","content","text","JSON","stringify","structuredContent","error","message","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"AACA,SAASA,OAAO,QAAQ,yBAAyB;AAEjD,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAA8BE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACtF,SAASC,MAAM,QAAQ,oCAAoC;AAC3D,SAASC,CAAC,QAAQ,MAAM;AAExB,MAAMC,gBAAgBD,EAAEE,MAAM,CAAC;IAC7BC,SAASH,EAAEI,OAAO,GAAGC,QAAQ,CAAC;IAC9BC,IAAIN,EAAEO,MAAM,GAAGC,QAAQ,GAAGH,QAAQ,CAAC;AACrC;AAEA,MAAMI,cAAcT,EAAEE,MAAM,CAAC;IAC3BI,IAAIN,EAAEU,MAAM,CAACH,MAAM,GAAGI,IAAI,GAAGC,GAAG,CAAC,GAAGP,QAAQ,CAAC;AAC/C;AAEA,wBAAwB;AACxB,MAAMQ,sBAAsBZ,cAAca,MAAM,CAAC;IAC/CC,MAAMf,EAAEgB,OAAO,CAAC;AAClB;AAEA,2CAA2C;AAC3C,MAAMC,eAAejB,EAAEkB,kBAAkB,CAAC,QAAQ;IAACL;IAAqBjB;CAAyB;AAEjG,MAAMuB,SAAS;IACbC,aAAa;IACbX,aAAaA;IACbQ,cAAcjB,EAAEE,MAAM,CAAC;QACrBmB,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAEhB,EAAE,EAAS,EAAEiB,KAAoB;IACxD,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC,oCAAoC;QAAEnB;IAAG;IAErD,IAAI,CAACA,IAAI;QACPkB,OAAOC,IAAI,CAAC;QACZ,MAAM,IAAI5B,cAAcC,kBAAkB4B,aAAa,EAAE;IAC3D;IAEA,IAAI;QACF,MAAMC,QAAQ5B,OAAO6B,kBAAkB,CAAC;YAAEC,cAAcN,MAAMO,WAAW,CAACC,IAAI;QAAC;QAC/E,MAAMJ,MAAMK,GAAG,CAAC,CAAC,aAAa,EAAEC,mBAAmB3B,KAAK,EAAE4B,MAAM,CAAC;YAAEC,QAAQ;QAAK;QAEhFX,OAAOC,IAAI,CAAC,qCAAqC;YAAEnB;QAAG;QAEtD,MAAMe,SAAiB;YACrBN,MAAM;YACNZ,SAAS;YACTG;QACF;QAEA,OAAO;YACL8B,SAAS;gBACP;oBACErB,MAAM;oBACNsB,MAAMC,KAAKC,SAAS,CAAClB;gBACvB;aACD;YACDmB,mBAAmB;gBAAEnB;YAAO;QAC9B;IACF,EAAE,OAAOoB,OAAO;QACd,MAAMC,UAAUD,iBAAiBE,QAAQF,MAAMC,OAAO,GAAGE,OAAOH;QAChEjB,OAAOiB,KAAK,CAAC,mCAAmC;YAAEA,OAAOC;QAAQ;QAEjE,MAAM,IAAI7C,cAAcC,kBAAkB+C,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;QACN9B;QACAG;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-outlook/src/mcp/tools/message-move-to-trash.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst BatchResultSchema = z.object({\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 inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Outlook message IDs to move to trash'),\n});\n\n// Success branch schema\nconst successBranchSchema = BatchResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Move Outlook 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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook-message-move-to-trash called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n logger.info('outlook-message-move-to-trash missing ids');\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 logger.info('outlook-message-move-to-trash batch size exceeded', { requested: ids.length, max: 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 Outlook 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 logger.info('outlook-message-move-to-trash found invalid ids', { invalidIds, count: invalidIds.length });\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n logger.info('outlook-message-move-to-trash no valid ids after validation');\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: 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 graph.api(`/me/messages/${encodeURIComponent(id)}`).delete();\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 const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\n };\n\n logger.info('outlook-message-move-to-trash completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\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('outlook-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","Client","z","CHUNK_SIZE","MAX_BATCH_SIZE","BatchResultSchema","object","totalRequested","number","describe","successCount","failureCount","results","array","id","string","success","boolean","error","optional","inputSchema","ids","coerce","trim","min","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","requested","max","validatedIds","invalidIds","trimmedId","push","includes","join","graph","initWithMiddleware","authProvider","authContext","auth","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","map","api","encodeURIComponent","delete","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/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-move-to-trash.ts"],"sourcesContent":["import type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\nimport { CHUNK_SIZE, MAX_BATCH_SIZE } from '../../constants.ts';\n\nconst BatchResultSchema = z.object({\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 inputSchema = z.object({\n ids: z.array(z.coerce.string().trim().min(1)).min(1).describe('Outlook message IDs to move to trash'),\n});\n\n// Success branch schema\nconst successBranchSchema = BatchResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Move Outlook 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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook-message-move-to-trash called', { count: ids.length });\n\n if (!ids || ids.length === 0) {\n logger.info('outlook-message-move-to-trash missing ids');\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 logger.info('outlook-message-move-to-trash batch size exceeded', { requested: ids.length, max: 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 Outlook 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 logger.info('outlook-message-move-to-trash found invalid ids', { invalidIds, count: invalidIds.length });\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Found ${invalidIds.length} invalid IDs: ${invalidIds.join(', ')}`);\n }\n\n if (validatedIds.length === 0) {\n logger.info('outlook-message-move-to-trash no valid ids after validation');\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'No valid IDs found after validation');\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: 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 graph.api(`/me/messages/${encodeURIComponent(id)}`).delete();\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 const result: Output = {\n type: 'success' as const,\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n results: allResults,\n };\n\n logger.info('outlook-message-move-to-trash completed', {\n totalRequested: validatedIds.length,\n successCount,\n failureCount,\n chunksProcessed: Math.ceil(validatedIds.length / CHUNK_SIZE),\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('outlook-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","Client","z","CHUNK_SIZE","MAX_BATCH_SIZE","BatchResultSchema","object","totalRequested","number","describe","successCount","failureCount","results","array","id","string","success","boolean","error","optional","inputSchema","ids","coerce","trim","min","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","count","length","InvalidParams","requested","max","validatedIds","invalidIds","trimmedId","push","includes","join","graph","initWithMiddleware","authProvider","authContext","auth","allResults","i","chunk","slice","chunkIndex","chunkSize","totalChunks","Math","ceil","chunkResults","Promise","allSettled","map","api","encodeURIComponent","delete","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 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-respond.ts"],"sourcesContent":["import { ComposeContentTypeSchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\n\nconst SuccessSchema = z.object({\n success: z.boolean().describe('Whether the reply was sent successfully'),\n id: z.string().optional().describe('Original message ID that was replied to'),\n});\n\nconst inputSchema = z.object({\n id: z.coerce.string().trim().min(1).describe('Outlook 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\n// Success branch schema\nconst successBranchSchema = SuccessSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Reply to an Outlook 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): Promise<CallToolResult> {\n const logger = extra.logger;\n logger.info('outlook.respond called', { id, hasBody: !!body });\n\n if (!id || !body) {\n logger.info('outlook.respond missing id or body');\n throw new ProtocolError(ProtocolErrorCode.InvalidParams, 'Missing id or body');\n }\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n await graph.api(`/me/messages/${encodeURIComponent(id)}/reply`).post({ message: { body: { contentType: contentType === 'html' ? 'HTML' : 'Text', content: body } } });\n\n logger.info('outlook.respond success', { id });\n\n const result: Output = {\n type: 'success' as const,\n success: true,\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('outlook.respond error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error replying 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","Client","z","SuccessSchema","object","success","boolean","describe","id","string","optional","inputSchema","coerce","trim","min","body","contentType","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","info","hasBody","InvalidParams","graph","initWithMiddleware","authProvider","authContext","auth","api","encodeURIComponent","post","message","content","text","JSON","stringify","structuredContent","error","Error","String","InternalError","stack","undefined","createTool","name"],"mappings":"AAAA,SAASA,wBAAwB,QAAQ,eAAe;AAExD,SAASC,OAAO,QAAQ,yBAAyB;AAEjD,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAGrC,SAA8BE,aAAa,EAAEC,iBAAiB,QAAQ,gBAAgB;AACtF,SAASC,MAAM,QAAQ,oCAAoC;AAC3D,SAASC,CAAC,QAAQ,MAAM;AAExB,MAAMC,gBAAgBD,EAAEE,MAAM,CAAC;IAC7BC,SAASH,EAAEI,OAAO,GAAGC,QAAQ,CAAC;IAC9BC,IAAIN,EAAEO,MAAM,GAAGC,QAAQ,GAAGH,QAAQ,CAAC;AACrC;AAEA,MAAMI,cAAcT,EAAEE,MAAM,CAAC;IAC3BI,IAAIN,EAAEU,MAAM,CAACH,MAAM,GAAGI,IAAI,GAAGC,GAAG,CAAC,GAAGP,QAAQ,CAAC;IAC7CQ,MAAMb,EAAEU,MAAM,CAACH,MAAM,GAAGI,IAAI,GAAGC,GAAG,CAAC,GAAGP,QAAQ,CAAC;IAC/CS,aAAapB;AACf;AAEA,wBAAwB;AACxB,MAAMqB,sBAAsBd,cAAce,MAAM,CAAC;IAC/CC,MAAMjB,EAAEkB,OAAO,CAAC;AAClB;AAEA,2CAA2C;AAC3C,MAAMC,eAAenB,EAAEoB,kBAAkB,CAAC,QAAQ;IAACL;IAAqBnB;CAAyB;AAEjG,MAAMyB,SAAS;IACbC,aAAa;IACbb,aAAaA;IACbU,cAAcnB,EAAEE,MAAM,CAAC;QACrBqB,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAElB,EAAE,EAAEO,IAAI,EAAEC,WAAW,EAAS,EAAEW,KAAoB;IAC3E,MAAMC,SAASD,MAAMC,MAAM;IAC3BA,OAAOC,IAAI,CAAC,0BAA0B;QAAErB;QAAIsB,SAAS,CAAC,CAACf;IAAK;IAE5D,IAAI,CAACP,MAAM,CAACO,MAAM;QAChBa,OAAOC,IAAI,CAAC;QACZ,MAAM,IAAI9B,cAAcC,kBAAkB+B,aAAa,EAAE;IAC3D;IAEA,IAAI;QACF,MAAMC,QAAQ/B,OAAOgC,kBAAkB,CAAC;YAAEC,cAAcP,MAAMQ,WAAW,CAACC,IAAI;QAAC;QAC/E,MAAMJ,MAAMK,GAAG,CAAC,CAAC,aAAa,EAAEC,mBAAmB9B,IAAI,MAAM,CAAC,EAAE+B,IAAI,CAAC;YAAEC,SAAS;gBAAEzB,MAAM;oBAAEC,aAAaA,gBAAgB,SAAS,SAAS;oBAAQyB,SAAS1B;gBAAK;YAAE;QAAE;QAEnKa,OAAOC,IAAI,CAAC,2BAA2B;YAAErB;QAAG;QAE5C,MAAMiB,SAAiB;YACrBN,MAAM;YACNd,SAAS;YACTG;QACF;QAEA,OAAO;YACLiC,SAAS;gBACP;oBACEtB,MAAM;oBACNuB,MAAMC,KAAKC,SAAS,CAACnB;gBACvB;aACD;YACDoB,mBAAmB;gBAAEpB;YAAO;QAC9B;IACF,EAAE,OAAOqB,OAAO;QACd,MAAMN,UAAUM,iBAAiBC,QAAQD,MAAMN,OAAO,GAAGQ,OAAOF;QAChElB,OAAOkB,KAAK,CAAC,yBAAyB;YAAEA,OAAON;QAAQ;QAEvD,MAAM,IAAIzC,cAAcC,kBAAkBiD,aAAa,EAAE,CAAC,2BAA2B,EAAET,SAAS,EAAE;YAChGU,OAAOJ,iBAAiBC,QAAQD,MAAMI,KAAK,GAAGC;QAChD;IACF;AACF;AAEA,eAAe,SAASC;IACtB,OAAO;QACLC,MAAM;QACN9B;QACAG;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-outlook/src/mcp/tools/message-search.ts"],"sourcesContent":["import { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema, extractCurrentMessageFromHtml, extractCurrentMessageFromHtmlToText } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { type CallToolResult, createFieldsSchema, createPaginationSchema, createShapeSchema, filterFields, ProtocolError, ProtocolErrorCode, parseFields, type ToolModule, toColumnarFormat } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { z } from 'zod';\nimport { needsBody } from '../../email/querying/client-filter.ts';\nimport { executeQuery as executeOutlookQuery } from '../../email/querying/execute-query.ts';\nimport { OutlookQueryParameterSchema, parseOutlookQueryParameter } from '../../schemas/outlook-query-schema.ts';\n\nconst inputSchema = z.object({\n query: OutlookQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and kqlQuery for KQL 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({\n defaultPageSize: 50,\n maxPageSize: 500,\n provider: 'outlook',\n }).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 Outlook 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 = 50, pageToken, fields, shape = 'arrays', contentType, excludeThreadHistory }: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n\n try {\n const parsedQuery = parseOutlookQueryParameter(query);\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n const needsBodyContent = needsBody(parsedQuery);\n const includeBody = requestedFields === 'all' || requestedFields.has('body') || needsBodyContent;\n\n logger.info('outlook.search called with', {\n query: parsedQuery,\n pageSize,\n pageToken: pageToken ? '[provided]' : undefined,\n fields: fields || 'all',\n includeBody,\n });\n\n const graph = Client.initWithMiddleware({\n authProvider: extra.authContext.auth,\n });\n const started = Date.now();\n const exec = await executeOutlookQuery(\n graph,\n parsedQuery,\n {\n logger,\n pageSize,\n ...(pageToken ? { pageToken } : {}),\n includeBody,\n limit: pageSize,\n },\n (m: unknown) => {\n const message = m as MicrosoftGraph.Message;\n const to = Array.isArray(message?.toRecipients)\n ? message.toRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const cc = Array.isArray(message?.ccRecipients)\n ? message.ccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const bcc = Array.isArray(message?.bccRecipients)\n ? message.bccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const fromAddr = message?.from?.emailAddress?.address ?? null;\n const fromName = message?.from?.emailAddress?.name ?? null;\n // Process body based on contentType and excludeThreadHistory options\n let bodyContent: string | undefined;\n if (includeBody && message?.body?.content) {\n const isHtml = message.body.contentType?.toLowerCase() === 'html';\n bodyContent = message.body.content;\n\n if (isHtml && excludeThreadHistory) {\n bodyContent = extractCurrentMessageFromHtml(bodyContent);\n }\n\n if (isHtml && contentType === 'text') {\n bodyContent = excludeThreadHistory ? extractCurrentMessageFromHtmlToText(bodyContent) : extractCurrentMessageFromHtmlToText(message.body.content);\n }\n }\n\n const mapped: Partial<EmailDetail> = {\n id: message?.id ?? undefined,\n subject: message?.subject ?? undefined,\n from: fromAddr ?? undefined,\n fromName: fromName ?? undefined,\n to,\n cc,\n bcc,\n date: message?.receivedDateTime ?? undefined,\n snippet: message?.bodyPreview ?? undefined,\n ...(bodyContent && { body: bodyContent, bodyContentType: contentType }),\n };\n return mapped;\n }\n );\n const durationMs = Date.now() - started;\n\n const filteredItems = exec.items.map((item) => filterFields(item, requestedFields));\n logger.info('outlook.message.search returning', {\n query,\n pageSize,\n itemsLength: filteredItems.length,\n fields: fields || 'all',\n });\n logger.info('outlook.message.search metrics', {\n durationMs,\n metadata: exec.metadata,\n });\n\n // Type-safe metadata access\n const metadataObj = exec.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('outlook.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":["EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","extractCurrentMessageFromHtml","extractCurrentMessageFromHtmlToText","schemas","AuthRequiredBranchSchema","createFieldsSchema","createPaginationSchema","createShapeSchema","filterFields","ProtocolError","ProtocolErrorCode","parseFields","toColumnarFormat","Client","z","needsBody","executeQuery","executeOutlookQuery","OutlookQueryParameterSchema","parseOutlookQueryParameter","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","needsBodyContent","includeBody","has","info","undefined","graph","initWithMiddleware","authProvider","authContext","auth","started","Date","now","exec","limit","m","message","to","Array","isArray","toRecipients","map","r","emailAddress","address","filter","Boolean","join","cc","ccRecipients","bcc","bccRecipients","fromAddr","from","fromName","name","bodyContent","body","content","isHtml","toLowerCase","mapped","id","subject","date","receivedDateTime","snippet","bodyPreview","bodyContentType","durationMs","filteredItems","item","itemsLength","length","metadata","metadataObj","text","JSON","stringify","structuredContent","error","Error","String","InternalError","stack","createTool"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-search.ts"],"sourcesContent":["import { EMAIL_COMMON_PATTERNS, EMAIL_FIELD_DESCRIPTIONS, EMAIL_FIELDS, EmailContentTypeSchema, type EmailDetail, EmailDetailSchema, ExcludeThreadHistorySchema, extractCurrentMessageFromHtml, extractCurrentMessageFromHtmlToText } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { type CallToolResult, createFieldsSchema, createPaginationSchema, createShapeSchema, filterFields, ProtocolError, ProtocolErrorCode, parseFields, type ToolModule, toColumnarFormat } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { z } from 'zod';\nimport { needsBody } from '../../email/querying/client-filter.ts';\nimport { executeQuery as executeOutlookQuery } from '../../email/querying/execute-query.ts';\nimport { OutlookQueryParameterSchema, parseOutlookQueryParameter } from '../../schemas/outlook-query-schema.ts';\n\nconst inputSchema = z.object({\n query: OutlookQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and kqlQuery for KQL 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({\n defaultPageSize: 50,\n maxPageSize: 500,\n provider: 'outlook',\n }).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 Outlook 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 = 50, pageToken, fields, shape = 'arrays', contentType, excludeThreadHistory }: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n\n try {\n const parsedQuery = parseOutlookQueryParameter(query);\n const requestedFields = parseFields(fields, EMAIL_FIELDS);\n const needsBodyContent = needsBody(parsedQuery);\n const includeBody = requestedFields === 'all' || requestedFields.has('body') || needsBodyContent;\n\n logger.info('outlook.search called with', {\n query: parsedQuery,\n pageSize,\n pageToken: pageToken ? '[provided]' : undefined,\n fields: fields || 'all',\n includeBody,\n });\n\n const graph = Client.initWithMiddleware({\n authProvider: extra.authContext.auth,\n });\n const started = Date.now();\n const exec = await executeOutlookQuery(\n graph,\n parsedQuery,\n {\n logger,\n pageSize,\n ...(pageToken ? { pageToken } : {}),\n includeBody,\n limit: pageSize,\n },\n (m: unknown) => {\n const message = m as MicrosoftGraph.Message;\n const to = Array.isArray(message?.toRecipients)\n ? message.toRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const cc = Array.isArray(message?.ccRecipients)\n ? message.ccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const bcc = Array.isArray(message?.bccRecipients)\n ? message.bccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address)\n .filter(Boolean)\n .join(', ')\n : undefined;\n const fromAddr = message?.from?.emailAddress?.address ?? null;\n const fromName = message?.from?.emailAddress?.name ?? null;\n // Process body based on contentType and excludeThreadHistory options\n let bodyContent: string | undefined;\n if (includeBody && message?.body?.content) {\n const isHtml = message.body.contentType?.toLowerCase() === 'html';\n bodyContent = message.body.content;\n\n if (isHtml && excludeThreadHistory) {\n bodyContent = extractCurrentMessageFromHtml(bodyContent);\n }\n\n if (isHtml && contentType === 'text') {\n bodyContent = excludeThreadHistory ? extractCurrentMessageFromHtmlToText(bodyContent) : extractCurrentMessageFromHtmlToText(message.body.content);\n }\n }\n\n const mapped: Partial<EmailDetail> = {\n id: message?.id ?? undefined,\n subject: message?.subject ?? undefined,\n from: fromAddr ?? undefined,\n fromName: fromName ?? undefined,\n to,\n cc,\n bcc,\n date: message?.receivedDateTime ?? undefined,\n snippet: message?.bodyPreview ?? undefined,\n ...(bodyContent && { body: bodyContent, bodyContentType: contentType }),\n };\n return mapped;\n }\n );\n const durationMs = Date.now() - started;\n\n const filteredItems = exec.items.map((item) => filterFields(item, requestedFields));\n logger.info('outlook.message.search returning', {\n query,\n pageSize,\n itemsLength: filteredItems.length,\n fields: fields || 'all',\n });\n logger.info('outlook.message.search metrics', {\n durationMs,\n metadata: exec.metadata,\n });\n\n // Type-safe metadata access\n const metadataObj = exec.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('outlook.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":["EMAIL_COMMON_PATTERNS","EMAIL_FIELD_DESCRIPTIONS","EMAIL_FIELDS","EmailContentTypeSchema","EmailDetailSchema","ExcludeThreadHistorySchema","extractCurrentMessageFromHtml","extractCurrentMessageFromHtmlToText","schemas","AuthRequiredBranchSchema","createFieldsSchema","createPaginationSchema","createShapeSchema","filterFields","ProtocolError","ProtocolErrorCode","parseFields","toColumnarFormat","Client","z","needsBody","executeQuery","executeOutlookQuery","OutlookQueryParameterSchema","parseOutlookQueryParameter","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","needsBodyContent","includeBody","has","info","undefined","graph","initWithMiddleware","authProvider","authContext","auth","started","Date","now","exec","limit","m","message","to","Array","isArray","toRecipients","map","r","emailAddress","address","filter","Boolean","join","cc","ccRecipients","bcc","bccRecipients","fromAddr","from","fromName","name","bodyContent","body","content","isHtml","toLowerCase","mapped","id","subject","date","receivedDateTime","snippet","bodyPreview","bodyContentType","durationMs","filteredItems","item","itemsLength","length","metadata","metadataObj","text","JSON","stringify","structuredContent","error","Error","String","InternalError","stack","createTool"],"mappings":"AAAA,SAASA,qBAAqB,EAAEC,wBAAwB,EAAEC,YAAY,EAAEC,sBAAsB,EAAoBC,iBAAiB,EAAEC,0BAA0B,EAAEC,6BAA6B,EAAEC,mCAAmC,QAAQ,eAAe;AAE1P,SAASC,OAAO,QAAQ,yBAAyB;AAEjD,MAAM,EAAEC,wBAAwB,EAAE,GAAGD;AAErC,SAA8BE,kBAAkB,EAAEC,sBAAsB,EAAEC,iBAAiB,EAAEC,YAAY,EAAEC,aAAa,EAAEC,iBAAiB,EAAEC,WAAW,EAAmBC,gBAAgB,QAAQ,gBAAgB;AACnN,SAASC,MAAM,QAAQ,oCAAoC;AAE3D,SAASC,CAAC,QAAQ,MAAM;AACxB,SAASC,SAAS,QAAQ,wCAAwC;AAClE,SAASC,gBAAgBC,mBAAmB,QAAQ,wCAAwC;AAC5F,SAASC,2BAA2B,EAAEC,0BAA0B,QAAQ,wCAAwC;AAEhH,MAAMC,cAAcN,EAAEO,MAAM,CAAC;IAC3BC,OAAOJ,4BAA4BK,QAAQ,GAAGC,QAAQ,CAAC;IACvDC,QAAQpB,mBAAmB;QACzBqB,iBAAiB7B;QACjB8B,mBAAmB/B;QACnBgC,gBAAgBjC;QAChBkC,cAAc;IAChB;IACA,GAAGvB,uBAAuB;QACxBwB,iBAAiB;QACjBC,aAAa;QACbC,UAAU;IACZ,GAAGC,KAAK;IACRA,OAAO1B;IACP2B,aAAapC;IACbqC,sBAAsBnC;AACxB;AAEA,8CAA8C;AAC9C,MAAMoC,6BAA6BtB,EAAEO,MAAM,CAAC;IAC1CgB,MAAMvB,EAAEwB,OAAO,CAAC;IAChBL,OAAOnB,EAAEwB,OAAO,CAAC;IACjBC,OAAOzB,EAAE0B,KAAK,CAACzC,mBAAmByB,QAAQ,CAAC;IAC3CiB,eAAe3B,EAAE4B,MAAM,GAAGnB,QAAQ,GAAGC,QAAQ,CAAC;AAChD;AAEA,MAAMmB,4BAA4B7B,EAAEO,MAAM,CAAC;IACzCgB,MAAMvB,EAAEwB,OAAO,CAAC;IAChBL,OAAOnB,EAAEwB,OAAO,CAAC;IACjBM,SAAS9B,EAAE0B,KAAK,CAAC1B,EAAE4B,MAAM,IAAIlB,QAAQ,CAAC;IACtCqB,MAAM/B,EAAE0B,KAAK,CAAC1B,EAAE0B,KAAK,CAAC1B,EAAEgC,OAAO,KAAKtB,QAAQ,CAAC;IAC7CiB,eAAe3B,EAAE4B,MAAM,GAAGnB,QAAQ,GAAGC,QAAQ,CAAC;AAChD;AAEA,2CAA2C;AAC3C,uGAAuG;AACvG,MAAMuB,eAAejC,EAAEkC,KAAK,CAAC;IAACZ;IAA4BO;IAA2BvC;CAAyB;AAE9G,MAAM6C,SAAS;IACbC,aAAa;IACb9B,aAAaA;IACb2B,cAAcjC,EAAEO,MAAM,CAAC;QACrB8B,QAAQJ;IACV;AACF;AAKA,eAAeK,QAAQ,EAAE9B,KAAK,EAAE+B,WAAW,EAAE,EAAEC,SAAS,EAAE7B,MAAM,EAAEQ,QAAQ,QAAQ,EAAEC,WAAW,EAAEC,oBAAoB,EAAS,EAAEoB,KAAoB;IAClJ,MAAMC,SAASD,MAAMC,MAAM;IAE3B,IAAI;QACF,MAAMC,cAActC,2BAA2BG;QAC/C,MAAMoC,kBAAkB/C,YAAYc,QAAQ5B;QAC5C,MAAM8D,mBAAmB5C,UAAU0C;QACnC,MAAMG,cAAcF,oBAAoB,SAASA,gBAAgBG,GAAG,CAAC,WAAWF;QAEhFH,OAAOM,IAAI,CAAC,8BAA8B;YACxCxC,OAAOmC;YACPJ;YACAC,WAAWA,YAAY,eAAeS;YACtCtC,QAAQA,UAAU;YAClBmC;QACF;QAEA,MAAMI,QAAQnD,OAAOoD,kBAAkB,CAAC;YACtCC,cAAcX,MAAMY,WAAW,CAACC,IAAI;QACtC;QACA,MAAMC,UAAUC,KAAKC,GAAG;QACxB,MAAMC,OAAO,MAAMvD,oBACjB+C,OACAP,aACA;YACED;YACAH;YACA,GAAIC,YAAY;gBAAEA;YAAU,IAAI,CAAC,CAAC;YAClCM;YACAa,OAAOpB;QACT,GACA,CAACqB;;gBAoBkBC,4BAAAA,eACAA,6BAAAA,gBAGEA;YAvBnB,MAAMA,UAAUD;YAChB,MAAME,KAAKC,MAAMC,OAAO,CAACH,oBAAAA,8BAAAA,QAASI,YAAY,IAC1CJ,QAAQI,YAAY,CACjBC,GAAG,CAAC,CAACC;oBAAgCA;uBAAAA,cAAAA,yBAAAA,kBAAAA,EAAGC,YAAY,cAAfD,sCAAAA,gBAAiBE,OAAO;eAC7DC,MAAM,CAACC,SACPC,IAAI,CAAC,QACRvB;YACJ,MAAMwB,KAAKV,MAAMC,OAAO,CAACH,oBAAAA,8BAAAA,QAASa,YAAY,IAC1Cb,QAAQa,YAAY,CACjBR,GAAG,CAAC,CAACC;oBAAgCA;uBAAAA,cAAAA,yBAAAA,kBAAAA,EAAGC,YAAY,cAAfD,sCAAAA,gBAAiBE,OAAO;eAC7DC,MAAM,CAACC,SACPC,IAAI,CAAC,QACRvB;YACJ,MAAM0B,MAAMZ,MAAMC,OAAO,CAACH,oBAAAA,8BAAAA,QAASe,aAAa,IAC5Cf,QAAQe,aAAa,CAClBV,GAAG,CAAC,CAACC;oBAAgCA;uBAAAA,cAAAA,yBAAAA,kBAAAA,EAAGC,YAAY,cAAfD,sCAAAA,gBAAiBE,OAAO;eAC7DC,MAAM,CAACC,SACPC,IAAI,CAAC,QACRvB;YACJ,MAAM4B,mBAAWhB,oBAAAA,+BAAAA,gBAAAA,QAASiB,IAAI,cAAbjB,qCAAAA,6BAAAA,cAAeO,YAAY,cAA3BP,iDAAAA,2BAA6BQ,OAAO,uCAAI;YACzD,MAAMU,oBAAWlB,oBAAAA,+BAAAA,iBAAAA,QAASiB,IAAI,cAAbjB,sCAAAA,8BAAAA,eAAeO,YAAY,cAA3BP,kDAAAA,4BAA6BmB,IAAI,yCAAI;YACtD,qEAAqE;YACrE,IAAIC;YACJ,IAAInC,gBAAee,oBAAAA,+BAAAA,gBAAAA,QAASqB,IAAI,cAAbrB,oCAAAA,cAAesB,OAAO,GAAE;oBAC1BtB;gBAAf,MAAMuB,SAASvB,EAAAA,4BAAAA,QAAQqB,IAAI,CAAC9D,WAAW,cAAxByC,gDAAAA,0BAA0BwB,WAAW,QAAO;gBAC3DJ,cAAcpB,QAAQqB,IAAI,CAACC,OAAO;gBAElC,IAAIC,UAAU/D,sBAAsB;oBAClC4D,cAAc9F,8BAA8B8F;gBAC9C;gBAEA,IAAIG,UAAUhE,gBAAgB,QAAQ;oBACpC6D,cAAc5D,uBAAuBjC,oCAAoC6F,eAAe7F,oCAAoCyE,QAAQqB,IAAI,CAACC,OAAO;gBAClJ;YACF;YAEA,MAAMG,SAA+B;gBACnCC,EAAE,WAAE1B,oBAAAA,8BAAAA,QAAS0B,EAAE,yCAAItC;gBACnBuC,OAAO,WAAE3B,oBAAAA,8BAAAA,QAAS2B,OAAO,yCAAIvC;gBAC7B6B,IAAI,EAAED,qBAAAA,sBAAAA,WAAY5B;gBAClB8B,QAAQ,EAAEA,qBAAAA,sBAAAA,WAAY9B;gBACtBa;gBACAW;gBACAE;gBACAc,IAAI,WAAE5B,oBAAAA,8BAAAA,QAAS6B,gBAAgB,yCAAIzC;gBACnC0C,OAAO,WAAE9B,oBAAAA,8BAAAA,QAAS+B,WAAW,yCAAI3C;gBACjC,GAAIgC,eAAe;oBAAEC,MAAMD;oBAAaY,iBAAiBzE;gBAAY,CAAC;YACxE;YACA,OAAOkE;QACT;QAEF,MAAMQ,aAAatC,KAAKC,GAAG,KAAKF;QAEhC,MAAMwC,gBAAgBrC,KAAKjC,KAAK,CAACyC,GAAG,CAAC,CAAC8B,OAAStG,aAAasG,MAAMpD;QAClEF,OAAOM,IAAI,CAAC,oCAAoC;YAC9CxC;YACA+B;YACA0D,aAAaF,cAAcG,MAAM;YACjCvF,QAAQA,UAAU;QACpB;QACA+B,OAAOM,IAAI,CAAC,kCAAkC;YAC5C8C;YACAK,UAAUzC,KAAKyC,QAAQ;QACzB;QAEA,4BAA4B;QAC5B,MAAMC,cAAc1C,KAAKyC,QAAQ;QAEjC,8BAA8B;QAC9B,MAAM9D,SACJlB,UAAU,WACN;YACEI,MAAM;YACNJ,OAAO;YACP,GAAGrB,iBAAiBiG,eAAenD,iBAAiB7D,aAAa;YACjE,GAAIqH,CAAAA,wBAAAA,kCAAAA,YAAazE,aAAa,KAAI;gBAAEA,eAAeyE,YAAYzE,aAAa;YAAC,CAAC;QAChF,IACA;YACEJ,MAAM;YACNJ,OAAO;YACPM,OAAOsE;YACP,GAAIK,CAAAA,wBAAAA,kCAAAA,YAAazE,aAAa,KAAI;gBAAEA,eAAeyE,YAAYzE,aAAa;YAAC,CAAC;QAChF;QAEN,OAAO;YACLwD,SAAS;gBACP;oBACE5D,MAAM;oBACN8E,MAAMC,KAAKC,SAAS,CAAClE;gBACvB;aACD;YACDmE,mBAAmB;gBAAEnE;YAAO;QAC9B;IACF,EAAE,OAAOoE,OAAO;QACd,MAAM5C,UAAU4C,iBAAiBC,QAAQD,MAAM5C,OAAO,GAAG8C,OAAOF;QAChE/D,OAAO+D,KAAK,CAAC,gCAAgC;YAAEA,OAAO5C;QAAQ;QAE9D,MAAM,IAAIlE,cAAcC,kBAAkBgH,aAAa,EAAE,CAAC,0BAA0B,EAAE/C,SAAS,EAAE;YAC/FgD,OAAOJ,iBAAiBC,QAAQD,MAAMI,KAAK,GAAG5D;QAChD;IACF;AACF;AAEA,eAAe,SAAS6D;IACtB,OAAO;QACL9B,MAAM;QACN7C;QACAG;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/message-send.ts"],"sourcesContent":["import { ComposeContentTypeSchema, createEmailRecipientsSchema, createMessageResultSchema } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport type { ToolModule } from '@mcp-z/server';\nimport { type CallToolResult, ProtocolError, ProtocolErrorCode } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport { z } from 'zod';\nimport { buildOutlookMessage } from '../../email/composition/outlook-message-builder.ts';\n\nconst MessageResultSchema = createMessageResultSchema('outlook');\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('Email subject line').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 = MessageResultSchema.extend({\n type: z.literal('success'),\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 Outlook',\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({ to, cc, bcc, subject, body, contentType }: Input, extra: EnrichedExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n\n try {\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n\n // Use composition module to build the message\n const toArray = to\n ?.split(',')\n .map((addr) => addr.trim())\n .filter((addr) => addr);\n const ccArray = cc\n ?.split(',')\n .map((addr) => addr.trim())\n .filter((addr) => addr);\n const bccArray = bcc\n ?.split(',')\n .map((addr) => addr.trim())\n .filter((addr) => addr);\n\n const message = buildOutlookMessage({\n to: toArray,\n cc: ccArray && ccArray.length > 0 ? ccArray : undefined,\n bcc: bccArray && bccArray.length > 0 ? bccArray : undefined,\n subject: subject ?? '',\n body,\n contentType: contentType === 'html' ? 'HTML' : 'Text',\n });\n\n // Use draft-send pattern to get message ID\n // 1. Create draft message\n const draft = await graph.api('/me/messages').post(message);\n const messageId = draft.id;\n\n if (!messageId) {\n logger.error('outlook.message.send draft creation failed - no ID returned');\n throw new ProtocolError(ProtocolErrorCode.InternalError, 'Failed to create draft message');\n }\n\n // 2. Send the draft\n await graph.api(`/me/messages/${messageId}/send`).post({});\n logger.info('Outlook: sent mail successfully', { messageId });\n\n const toCount = message.toRecipients?.length ?? 0;\n const ccCount = message.ccRecipients?.length ?? 0;\n const bccCount = message.bccRecipients?.length ?? 0;\n\n logger.info('outlook.message.send success', { toCount, ccCount, bccCount, subject: subject ?? '', messageId });\n\n const totalRecipients = toCount + ccCount + bccCount;\n const result: Output = {\n type: 'success' as const,\n id: messageId,\n sentAt: new Date().toISOString(),\n recipientCount: totalRecipients,\n webLink: 'https://outlook.live.com/mail/0/sentitems',\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('outlook.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","Client","z","buildOutlookMessage","MessageResultSchema","inputSchema","object","to","cc","bcc","subject","string","describe","default","body","trim","min","contentType","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","message","graph","initWithMiddleware","authProvider","authContext","auth","toArray","split","map","addr","filter","ccArray","bccArray","length","undefined","draft","api","post","messageId","id","error","InternalError","info","toCount","toRecipients","ccCount","ccRecipients","bccCount","bccRecipients","totalRecipients","sentAt","Date","toISOString","recipientCount","webLink","content","text","JSON","stringify","structuredContent","Error","String","stack","createTool","name"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/OpenSource/ai/mcp-z/mcp-outlook/src/mcp/tools/messages-export-csv.ts"],"sourcesContent":["/** Outlook message CSV export tool - streams results to file without loading all data into context */\n\nimport { EmailContentTypeSchema, ExcludeThreadHistorySchema, extractCurrentMessageFromHtml, extractCurrentMessageFromHtmlToText } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { type CallToolResult, getFileUri, ProtocolError, ProtocolErrorCode, reserveFile, type ToolModule } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { stringify } from 'csv-stringify/sync';\nimport { createWriteStream } from 'fs';\nimport { unlink } from 'fs/promises';\nimport { z } from 'zod';\nimport { executeQuery as executeOutlookQuery } from '../../email/querying/execute-query.ts';\nimport { OutlookQueryParameterSchema, parseOutlookQueryParameter } from '../../schemas/outlook-query-schema.ts';\nimport type { StorageExtra } from '../../types.ts';\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst DEFAULT_MAX_ITEMS = 10000;\nconst MAX_EXPORT_ITEMS = 50000;\n\nconst ExportResultSchema = z.object({\n uri: z.string().describe('File URI (file:// or http://)'),\n filename: z.string().describe('Stored filename'),\n rowCount: z.number().describe('Number of messages exported'),\n truncated: z.boolean().describe('Whether export was truncated at maxItems'),\n});\n\nconst inputSchema = z.object({\n query: OutlookQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and kqlQuery for KQL syntax.'),\n maxItems: z.number().int().positive().max(MAX_EXPORT_ITEMS).default(DEFAULT_MAX_ITEMS).describe(`Maximum messages to export (default: ${DEFAULT_MAX_ITEMS}, max: ${MAX_EXPORT_ITEMS})`),\n filename: z.string().trim().min(1).default('outlook-messages.csv').describe('Output filename (default: outlook-messages.csv)'),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schema\nconst successBranchSchema = ExportResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Export Outlook messages to CSV with streaming pagination. Returns file URI. Use query-syntax prompt for query reference.',\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\n/**\n * Handler for outlook-messages-export-csv tool\n *\n * CRITICAL: Streaming implementation per user requirements\n * - Generate UUID upfront\n * - Write CSV header immediately\n * - Append rows as batches arrive\n * - Delete partial file on error\n * - NO RETRIES (fail fast on error)\n */\nasync function handler({ query, maxItems, filename, contentType, excludeThreadHistory }: Input, extra: EnrichedExtra & StorageExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n const { storageContext } = extra;\n const { transport, resourceStoreUri, baseUrl } = storageContext;\n\n // Reserve file location for streaming write (creates directory, generates ID, formats filename)\n const reservation = await reserveFile(filename, {\n resourceStoreUri,\n });\n const { storedName, fullPath } = reservation;\n\n logger.info('outlook.messages.export-csv starting streaming export', { path: fullPath, maxItems });\n\n try {\n const parsedQuery = parseOutlookQueryParameter(query);\n\n logger.info('outlook.messages.export-csv called', {\n query: parsedQuery,\n maxItems,\n filename,\n accountId: extra.authContext.accountId,\n });\n\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n\n // Create CSV headers (all email fields)\n const csvHeaders = ['id', 'threadId', 'from', 'to', 'cc', 'bcc', 'subject', 'date', 'snippet', 'body', 'provider', 'labels'];\n\n // Create write stream and write headers immediately\n const writeStream = createWriteStream(fullPath, { encoding: 'utf-8' });\n const headerLine = stringify([csvHeaders], { header: false, quoted: true, quote: '\"', escape: '\"' });\n writeStream.write(headerLine);\n\n // Internal pagination loop - append to CSV with each batch\n // NO RETRIES: If any error occurs, fail the whole operation and clean up\n let totalRows = 0;\n let nextPageToken: string | undefined;\n const started = Date.now();\n\n while (totalRows < maxItems) {\n const remainingItems = maxItems - totalRows;\n const pageSize = Math.min(remainingItems, DEFAULT_PAGE_SIZE);\n\n const exec: {\n items: Array<{\n id: string;\n threadId?: string;\n from: string;\n to: string;\n cc: string;\n bcc: string;\n subject: string;\n date: string;\n snippet: string;\n body: string;\n provider: string;\n labels: string;\n }>;\n metadata?: { nextPageToken?: string };\n } = await executeOutlookQuery(\n graph,\n parsedQuery,\n {\n logger,\n pageSize,\n ...(nextPageToken !== undefined && { pageToken: nextPageToken }),\n includeBody: true, // Always include body for CSV export\n limit: pageSize,\n },\n (m: unknown) => {\n const message = m as MicrosoftGraph.Message;\n const to = Array.isArray(message?.toRecipients)\n ? message.toRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const cc = Array.isArray(message?.ccRecipients)\n ? message.ccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const bcc = Array.isArray(message?.bccRecipients)\n ? message.bccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const fromAddr = message?.from?.emailAddress?.address ?? (message?.from as { address?: string })?.address ?? '';\n const categories = Array.isArray(message?.categories) ? message.categories.join(';') : '';\n\n // Process body based on contentType and excludeThreadHistory options\n let body = message?.body?.content ?? '';\n const isHtml = message?.body?.contentType?.toLowerCase() === 'html';\n\n if (isHtml && excludeThreadHistory) {\n body = extractCurrentMessageFromHtml(body);\n }\n\n if (isHtml && contentType === 'text') {\n body = excludeThreadHistory ? extractCurrentMessageFromHtmlToText(body) : extractCurrentMessageFromHtmlToText(message?.body?.content ?? '');\n }\n\n return {\n id: String(message?.id ?? ''),\n threadId: message?.conversationId ? String(message.conversationId) : '',\n from: fromAddr,\n to,\n cc,\n bcc,\n subject: message?.subject ?? '',\n date: message?.receivedDateTime ?? '',\n snippet: message?.bodyPreview ?? '',\n body,\n provider: 'outlook' as const,\n labels: categories,\n };\n }\n );\n\n const csvRows = exec.items.map((item) => {\n return [item.id, item.threadId, item.from, item.to, item.cc, item.bcc, item.subject, item.date, item.snippet, item.body, item.provider, item.labels];\n });\n\n // Append rows to CSV file immediately\n if (csvRows.length > 0) {\n const rowsContent = stringify(csvRows, { header: false, quoted: true, quote: '\"', escape: '\"' });\n writeStream.write(rowsContent);\n }\n\n totalRows += exec.items.length;\n nextPageToken = exec.metadata?.nextPageToken;\n\n logger.info('outlook.messages.export-csv batch written', {\n batchSize: exec.items.length,\n totalRows,\n hasMore: Boolean(nextPageToken),\n });\n\n // Exit if no more results or reached maxItems\n if (!nextPageToken || exec.items.length === 0) {\n break;\n }\n }\n\n // Close write stream\n await new Promise<void>((resolve, reject) => {\n writeStream.end(() => resolve());\n writeStream.on('error', reject);\n });\n\n const durationMs = Date.now() - started;\n const truncated = totalRows >= maxItems && Boolean(nextPageToken);\n\n logger.info('outlook.messages.export-csv completed', {\n rowCount: totalRows,\n truncated,\n durationMs,\n filename: storedName,\n });\n\n // Generate URI based on transport type (stdio: file://, HTTP: http://)\n const uri = getFileUri(storedName, transport, {\n resourceStoreUri,\n ...(baseUrl && { baseUrl }),\n endpoint: '/files',\n });\n\n const result: Output = {\n type: 'success' as const,\n uri,\n filename: storedName,\n rowCount: totalRows,\n truncated,\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 // CRITICAL: Clean up partial CSV file on error\n try {\n await unlink(fullPath);\n logger.debug('Cleaned up partial CSV file after error', { path: fullPath });\n } catch (_cleanupError) {\n logger.debug('Could not clean up CSV file (may not exist)', { path: fullPath });\n }\n\n const message = error instanceof Error ? error.message : String(error);\n logger.error('outlook.messages.export-csv error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error exporting messages to CSV: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'messages-export-csv',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["EmailContentTypeSchema","ExcludeThreadHistorySchema","extractCurrentMessageFromHtml","extractCurrentMessageFromHtmlToText","schemas","AuthRequiredBranchSchema","getFileUri","ProtocolError","ProtocolErrorCode","reserveFile","Client","stringify","createWriteStream","unlink","z","executeQuery","executeOutlookQuery","OutlookQueryParameterSchema","parseOutlookQueryParameter","DEFAULT_PAGE_SIZE","DEFAULT_MAX_ITEMS","MAX_EXPORT_ITEMS","ExportResultSchema","object","uri","string","describe","filename","rowCount","number","truncated","boolean","inputSchema","query","optional","maxItems","int","positive","max","default","trim","min","contentType","excludeThreadHistory","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","storageContext","transport","resourceStoreUri","baseUrl","reservation","storedName","fullPath","info","path","parsedQuery","accountId","authContext","graph","initWithMiddleware","authProvider","auth","csvHeaders","writeStream","encoding","headerLine","header","quoted","quote","escape","write","totalRows","nextPageToken","started","Date","now","exec","remainingItems","pageSize","Math","undefined","pageToken","includeBody","limit","m","message","to","Array","isArray","toRecipients","map","r","emailAddress","address","filter","Boolean","join","cc","ccRecipients","bcc","bccRecipients","fromAddr","from","categories","body","content","isHtml","toLowerCase","id","String","threadId","conversationId","subject","date","receivedDateTime","snippet","bodyPreview","provider","labels","csvRows","items","item","length","rowsContent","metadata","batchSize","hasMore","Promise","resolve","reject","end","on","durationMs","endpoint","text","JSON","structuredContent","error","debug","_cleanupError","Error","InternalError","stack","createTool","name"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/mcp/tools/messages-export-csv.ts"],"sourcesContent":["/** Outlook message CSV export tool - streams results to file without loading all data into context */\n\nimport { EmailContentTypeSchema, ExcludeThreadHistorySchema, extractCurrentMessageFromHtml, extractCurrentMessageFromHtmlToText } from '@mcp-z/email';\nimport type { EnrichedExtra } from '@mcp-z/oauth-microsoft';\nimport { schemas } from '@mcp-z/oauth-microsoft';\n\nconst { AuthRequiredBranchSchema } = schemas;\n\nimport { type CallToolResult, getFileUri, ProtocolError, ProtocolErrorCode, reserveFile, type ToolModule } from '@mcp-z/server';\nimport { Client } from '@microsoft/microsoft-graph-client';\nimport type * as MicrosoftGraph from '@microsoft/microsoft-graph-types';\nimport { stringify } from 'csv-stringify/sync';\nimport { createWriteStream } from 'fs';\nimport { unlink } from 'fs/promises';\nimport { z } from 'zod';\nimport { executeQuery as executeOutlookQuery } from '../../email/querying/execute-query.ts';\nimport { OutlookQueryParameterSchema, parseOutlookQueryParameter } from '../../schemas/outlook-query-schema.ts';\nimport type { StorageExtra } from '../../types.ts';\n\nconst DEFAULT_PAGE_SIZE = 50;\nconst DEFAULT_MAX_ITEMS = 10000;\nconst MAX_EXPORT_ITEMS = 50000;\n\nconst ExportResultSchema = z.object({\n uri: z.string().describe('File URI (file:// or http://)'),\n filename: z.string().describe('Stored filename'),\n rowCount: z.number().describe('Number of messages exported'),\n truncated: z.boolean().describe('Whether export was truncated at maxItems'),\n});\n\nconst inputSchema = z.object({\n query: OutlookQueryParameterSchema.optional().describe('Structured query object or JSON string for filtering messages. Use query-syntax prompt for reference and kqlQuery for KQL syntax.'),\n maxItems: z.number().int().positive().max(MAX_EXPORT_ITEMS).default(DEFAULT_MAX_ITEMS).describe(`Maximum messages to export (default: ${DEFAULT_MAX_ITEMS}, max: ${MAX_EXPORT_ITEMS})`),\n filename: z.string().trim().min(1).default('outlook-messages.csv').describe('Output filename (default: outlook-messages.csv)'),\n contentType: EmailContentTypeSchema,\n excludeThreadHistory: ExcludeThreadHistorySchema,\n});\n\n// Success branch schema\nconst successBranchSchema = ExportResultSchema.extend({\n type: z.literal('success'),\n});\n\n// Output schema with auth_required support\nconst outputSchema = z.discriminatedUnion('type', [successBranchSchema, AuthRequiredBranchSchema]);\n\nconst config = {\n description: 'Export Outlook messages to CSV with streaming pagination. Returns file URI. Use query-syntax prompt for query reference.',\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\n/**\n * Handler for outlook-messages-export-csv tool\n *\n * CRITICAL: Streaming implementation per user requirements\n * - Generate UUID upfront\n * - Write CSV header immediately\n * - Append rows as batches arrive\n * - Delete partial file on error\n * - NO RETRIES (fail fast on error)\n */\nasync function handler({ query, maxItems, filename, contentType, excludeThreadHistory }: Input, extra: EnrichedExtra & StorageExtra): Promise<CallToolResult> {\n const logger = extra.logger;\n const { storageContext } = extra;\n const { transport, resourceStoreUri, baseUrl } = storageContext;\n\n // Reserve file location for streaming write (creates directory, generates ID, formats filename)\n const reservation = await reserveFile(filename, {\n resourceStoreUri,\n });\n const { storedName, fullPath } = reservation;\n\n logger.info('outlook.messages.export-csv starting streaming export', { path: fullPath, maxItems });\n\n try {\n const parsedQuery = parseOutlookQueryParameter(query);\n\n logger.info('outlook.messages.export-csv called', {\n query: parsedQuery,\n maxItems,\n filename,\n accountId: extra.authContext.accountId,\n });\n\n const graph = Client.initWithMiddleware({ authProvider: extra.authContext.auth });\n\n // Create CSV headers (all email fields)\n const csvHeaders = ['id', 'threadId', 'from', 'to', 'cc', 'bcc', 'subject', 'date', 'snippet', 'body', 'provider', 'labels'];\n\n // Create write stream and write headers immediately\n const writeStream = createWriteStream(fullPath, { encoding: 'utf-8' });\n const headerLine = stringify([csvHeaders], { header: false, quoted: true, quote: '\"', escape: '\"' });\n writeStream.write(headerLine);\n\n // Internal pagination loop - append to CSV with each batch\n // NO RETRIES: If any error occurs, fail the whole operation and clean up\n let totalRows = 0;\n let nextPageToken: string | undefined;\n const started = Date.now();\n\n while (totalRows < maxItems) {\n const remainingItems = maxItems - totalRows;\n const pageSize = Math.min(remainingItems, DEFAULT_PAGE_SIZE);\n\n const exec: {\n items: Array<{\n id: string;\n threadId?: string;\n from: string;\n to: string;\n cc: string;\n bcc: string;\n subject: string;\n date: string;\n snippet: string;\n body: string;\n provider: string;\n labels: string;\n }>;\n metadata?: { nextPageToken?: string };\n } = await executeOutlookQuery(\n graph,\n parsedQuery,\n {\n logger,\n pageSize,\n ...(nextPageToken !== undefined && { pageToken: nextPageToken }),\n includeBody: true, // Always include body for CSV export\n limit: pageSize,\n },\n (m: unknown) => {\n const message = m as MicrosoftGraph.Message;\n const to = Array.isArray(message?.toRecipients)\n ? message.toRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const cc = Array.isArray(message?.ccRecipients)\n ? message.ccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const bcc = Array.isArray(message?.bccRecipients)\n ? message.bccRecipients\n .map((r: MicrosoftGraph.Recipient) => r?.emailAddress?.address ?? (r as { address?: string })?.address)\n .filter(Boolean)\n .join(', ')\n : '';\n const fromAddr = message?.from?.emailAddress?.address ?? (message?.from as { address?: string })?.address ?? '';\n const categories = Array.isArray(message?.categories) ? message.categories.join(';') : '';\n\n // Process body based on contentType and excludeThreadHistory options\n let body = message?.body?.content ?? '';\n const isHtml = message?.body?.contentType?.toLowerCase() === 'html';\n\n if (isHtml && excludeThreadHistory) {\n body = extractCurrentMessageFromHtml(body);\n }\n\n if (isHtml && contentType === 'text') {\n body = excludeThreadHistory ? extractCurrentMessageFromHtmlToText(body) : extractCurrentMessageFromHtmlToText(message?.body?.content ?? '');\n }\n\n return {\n id: String(message?.id ?? ''),\n threadId: message?.conversationId ? String(message.conversationId) : '',\n from: fromAddr,\n to,\n cc,\n bcc,\n subject: message?.subject ?? '',\n date: message?.receivedDateTime ?? '',\n snippet: message?.bodyPreview ?? '',\n body,\n provider: 'outlook' as const,\n labels: categories,\n };\n }\n );\n\n const csvRows = exec.items.map((item) => {\n return [item.id, item.threadId, item.from, item.to, item.cc, item.bcc, item.subject, item.date, item.snippet, item.body, item.provider, item.labels];\n });\n\n // Append rows to CSV file immediately\n if (csvRows.length > 0) {\n const rowsContent = stringify(csvRows, { header: false, quoted: true, quote: '\"', escape: '\"' });\n writeStream.write(rowsContent);\n }\n\n totalRows += exec.items.length;\n nextPageToken = exec.metadata?.nextPageToken;\n\n logger.info('outlook.messages.export-csv batch written', {\n batchSize: exec.items.length,\n totalRows,\n hasMore: Boolean(nextPageToken),\n });\n\n // Exit if no more results or reached maxItems\n if (!nextPageToken || exec.items.length === 0) {\n break;\n }\n }\n\n // Close write stream\n await new Promise<void>((resolve, reject) => {\n writeStream.end(() => resolve());\n writeStream.on('error', reject);\n });\n\n const durationMs = Date.now() - started;\n const truncated = totalRows >= maxItems && Boolean(nextPageToken);\n\n logger.info('outlook.messages.export-csv completed', {\n rowCount: totalRows,\n truncated,\n durationMs,\n filename: storedName,\n });\n\n // Generate URI based on transport type (stdio: file://, HTTP: http://)\n const uri = getFileUri(storedName, transport, {\n resourceStoreUri,\n ...(baseUrl && { baseUrl }),\n endpoint: '/files',\n });\n\n const result: Output = {\n type: 'success' as const,\n uri,\n filename: storedName,\n rowCount: totalRows,\n truncated,\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 // CRITICAL: Clean up partial CSV file on error\n try {\n await unlink(fullPath);\n logger.debug('Cleaned up partial CSV file after error', { path: fullPath });\n } catch (_cleanupError) {\n logger.debug('Could not clean up CSV file (may not exist)', { path: fullPath });\n }\n\n const message = error instanceof Error ? error.message : String(error);\n logger.error('outlook.messages.export-csv error', { error: message });\n\n throw new ProtocolError(ProtocolErrorCode.InternalError, `Error exporting messages to CSV: ${message}`, {\n stack: error instanceof Error ? error.stack : undefined,\n });\n }\n}\n\nexport default function createTool() {\n return {\n name: 'messages-export-csv',\n config,\n handler,\n } satisfies ToolModule;\n}\n"],"names":["EmailContentTypeSchema","ExcludeThreadHistorySchema","extractCurrentMessageFromHtml","extractCurrentMessageFromHtmlToText","schemas","AuthRequiredBranchSchema","getFileUri","ProtocolError","ProtocolErrorCode","reserveFile","Client","stringify","createWriteStream","unlink","z","executeQuery","executeOutlookQuery","OutlookQueryParameterSchema","parseOutlookQueryParameter","DEFAULT_PAGE_SIZE","DEFAULT_MAX_ITEMS","MAX_EXPORT_ITEMS","ExportResultSchema","object","uri","string","describe","filename","rowCount","number","truncated","boolean","inputSchema","query","optional","maxItems","int","positive","max","default","trim","min","contentType","excludeThreadHistory","successBranchSchema","extend","type","literal","outputSchema","discriminatedUnion","config","description","result","handler","extra","logger","storageContext","transport","resourceStoreUri","baseUrl","reservation","storedName","fullPath","info","path","parsedQuery","accountId","authContext","graph","initWithMiddleware","authProvider","auth","csvHeaders","writeStream","encoding","headerLine","header","quoted","quote","escape","write","totalRows","nextPageToken","started","Date","now","exec","remainingItems","pageSize","Math","undefined","pageToken","includeBody","limit","m","message","to","Array","isArray","toRecipients","map","r","emailAddress","address","filter","Boolean","join","cc","ccRecipients","bcc","bccRecipients","fromAddr","from","categories","body","content","isHtml","toLowerCase","id","String","threadId","conversationId","subject","date","receivedDateTime","snippet","bodyPreview","provider","labels","csvRows","items","item","length","rowsContent","metadata","batchSize","hasMore","Promise","resolve","reject","end","on","durationMs","endpoint","text","JSON","structuredContent","error","debug","_cleanupError","Error","InternalError","stack","createTool","name"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/schemas/index.ts"],"sourcesContent":["export * from './outlook-query-schema.ts';\nexport * from './outlook-validation.ts';\n"],"names":[],"mappings":"AAAA,cAAc,4BAA4B;AAC1C,cAAc,0BAA0B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/Users/kevin/Dev/
|
|
1
|
+
{"version":3,"sources":["/Users/kevin/Dev/open-source/ai/mcp-z/mcp-outlook/src/schemas/outlook-query-schema.ts"],"sourcesContent":["import { type BaseEmailQueryFields, baseEmailQueryFields, type FieldOperator, FieldOperatorSchema } from '@mcp-z/email';\nimport { z } from 'zod';\n\n/**\n * Outlook system category values.\n * These are the built-in category types that Outlook recognizes.\n * Note: This is distinct from OutlookCategory (user-created category objects with id/displayName/color).\n */\nexport type OutlookSystemCategory = 'work' | 'personal' | 'family' | 'travel' | 'important' | 'urgent';\n\n/** Zod schema for validating OutlookSystemCategory values */\nexport const OutlookSystemCategorySchema = z.enum(['work', 'personal', 'family', 'travel', 'important', 'urgent']);\n\n/**\n * Outlook-specific query schema with recursive operators and Outlook features.\n *\n * Includes Microsoft Graph/Outlook-specific features:\n * - exactPhrase: Strict exact phrase matching via KQL $search parameter\n * - categories: Outlook system categories (work, personal, family, travel, important, urgent)\n * - label: User-created Outlook categories (case-sensitive, discovered via outlook-categories-list)\n * - importance: Message importance level (high, normal, low)\n * - kqlQuery: Escape hatch for advanced KQL (Keyword Query Language) syntax\n *\n * Plus all base fields from baseEmailQueryFields:\n * - Email addresses: from, to, cc, bcc (support string or field operators)\n * - Content: subject, body, text\n * - Flags: hasAttachment, isRead\n * - Date range: date { $gte, $lt }\n * - Logical operators: $and, $or, $not (recursive)\n *\n * Note: Cast through unknown to work around Zod's lazy schema type inference issue\n * with exactOptionalPropertyTypes. The runtime schema is correct; this cast ensures\n * TypeScript sees the strict OutlookQuery type everywhere the schema is used.\n */\nexport const OutlookQuerySchema = z.lazy(() =>\n z\n .object({\n // Logical operators for combining conditions (recursive)\n $and: z.array(OutlookQuerySchema).optional().describe('Array of conditions that must ALL match'),\n $or: z.array(OutlookQuerySchema).optional().describe('Array of conditions where ANY must match'),\n $not: OutlookQuerySchema.optional().describe('Nested condition that must NOT match'),\n\n // Spread base email query fields (from, to, subject, body, etc.)\n ...baseEmailQueryFields,\n\n // Outlook-specific features\n\n // Exact phrase matching - KQL strict search with double quotes\n exactPhrase: z.string().min(1).optional().describe('Exact phrase matching - words must appear together in exact order (strict matching). Outlook uses KQL.'),\n\n // Outlook system categories with field operator support\n categories: z\n .union([\n OutlookSystemCategorySchema,\n z\n .object({\n $any: z.array(OutlookSystemCategorySchema).optional(),\n $all: z.array(OutlookSystemCategorySchema).optional(),\n $none: z.array(OutlookSystemCategorySchema).optional(),\n })\n .strict(),\n ])\n .optional()\n .describe('Filter by Outlook system categories (work, personal, family, travel, important, urgent)'),\n\n // User-created categories\n label: z\n .union([z.string().min(1), FieldOperatorSchema])\n .optional()\n .describe('Filter by user-created categories (case-sensitive). Use outlook-categories-list to see available categories'),\n\n // Message importance level - Outlook-specific property\n importance: z.enum(['high', 'normal', 'low']).optional().describe('Filter by message importance level (high, normal, low)'),\n\n // Raw KQL query string - escape hatch for advanced syntax\n kqlQuery: z.string().min(1).optional().describe('Raw KQL (Keyword Query Language) syntax for advanced use cases. Bypasses schema validation - use sparingly.'),\n })\n .strict()\n) as unknown as z.ZodType<OutlookQuery>;\n\nconst OutlookQueryStringSchema = z\n .string()\n .min(1)\n .transform((value, ctx) => {\n try {\n return parseOutlookQueryString(value);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid query input';\n ctx.addIssue({\n code: z.ZodIssueCode.custom,\n message,\n });\n return z.NEVER;\n }\n });\n\nexport const OutlookQueryParameterSchema = z.union([OutlookQuerySchema, OutlookQueryStringSchema]) as z.ZodType<OutlookQuery | string>;\nexport type OutlookQueryParameter = z.infer<typeof OutlookQueryParameterSchema>;\n\nexport function parseOutlookQueryParameter(input: OutlookQuery | string | undefined): OutlookQuery | undefined {\n if (input === undefined) return undefined;\n if (typeof input === 'string') {\n return parseOutlookQueryString(input);\n }\n const validated = OutlookQuerySchema.safeParse(input);\n if (!validated.success) {\n throw new Error(`Invalid query JSON: ${validated.error.message}. Use {\"kqlQuery\":\"<query>\"} for KQL syntax.`);\n }\n return validated.data;\n}\n\nfunction parseOutlookQueryString(value: string): OutlookQuery {\n const raw = safeJsonParse(value, 'kqlQuery');\n const validated = OutlookQuerySchema.safeParse(raw);\n if (!validated.success) {\n throw new Error(`Invalid query JSON: ${validated.error.message}. Use {\"kqlQuery\":\"<query>\"} for KQL syntax.`);\n }\n return validated.data;\n}\n\nfunction safeJsonParse(value: string, rawField: 'kqlQuery'): unknown {\n try {\n return JSON.parse(value);\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Invalid JSON';\n throw new Error(`Query must be valid JSON. ${message}. Wrap KQL syntax in {\"${rawField}\":\"<query>\"} if needed.`);\n }\n}\n\nexport type OutlookQuery = BaseEmailQueryFields & {\n $and?: OutlookQuery[];\n $or?: OutlookQuery[];\n $not?: OutlookQuery;\n exactPhrase?: string;\n categories?:\n | OutlookSystemCategory\n | {\n $any?: OutlookSystemCategory[];\n $all?: OutlookSystemCategory[];\n $none?: OutlookSystemCategory[];\n };\n label?: string | FieldOperator;\n importance?: 'high' | 'normal' | 'low';\n kqlQuery?: string;\n};\n"],"names":["baseEmailQueryFields","FieldOperatorSchema","z","OutlookSystemCategorySchema","enum","OutlookQuerySchema","lazy","object","$and","array","optional","describe","$or","$not","exactPhrase","string","min","categories","union","$any","$all","$none","strict","label","importance","kqlQuery","OutlookQueryStringSchema","transform","value","ctx","parseOutlookQueryString","error","message","Error","addIssue","code","ZodIssueCode","custom","NEVER","OutlookQueryParameterSchema","parseOutlookQueryParameter","input","undefined","validated","safeParse","success","data","raw","safeJsonParse","rawField","JSON","parse"],"mappings":"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"}
|