UNPKG

msexchange-mcp

Version:

MCP server for Microsoft Exchange/Outlook email operations via Microsoft Graph API

155 lines 7.98 kB
import { z } from 'zod'; import { MailService } from '../mail/mailService.js'; import accountsConfig from '../config/accountsLoader.js'; export const modifyMailRuleTool = { name: 'modify_mail_rule', description: 'Modify an existing mail rule or change its enabled status', parameters: z.object({ user_id: z.string().describe('The user ID or email address'), rule_id: z.string().describe('ID of the rule to modify'), rule_name: z.string().optional().describe('New name for the mail rule'), conditions: z.object({ from_addresses: z.array(z.string()).optional().describe('Email addresses to match in From field'), subject_contains: z.array(z.string()).optional().describe('Keywords that must be in subject'), body_contains: z.array(z.string()).optional().describe('Keywords that must be in body'), to_me: z.boolean().optional().describe('Email is addressed to me'), cc_me: z.boolean().optional().describe('Email has me in CC'), sent_to: z.array(z.string()).optional().describe('Email is sent to these addresses'), importance: z.enum(['low', 'normal', 'high']).optional().describe('Message importance level'), has_attachments: z.boolean().optional().describe('Email has attachments'), }).optional().describe('Updated conditions that trigger the rule'), actions: z.object({ move_to_folder: z.string().optional().describe('Folder ID to move emails to'), copy_to_folder: z.string().optional().describe('Folder ID to copy emails to'), add_categories: z.array(z.string()).optional().describe('Categories to add to the email'), mark_as_read: z.boolean().optional().describe('Mark email as read'), mark_importance: z.enum(['low', 'normal', 'high']).optional().describe('Set importance level'), forward_to: z.string().optional().describe('Email address to forward to'), delete_message: z.boolean().optional().describe('Delete the message'), stop_processing: z.boolean().optional().describe('Stop processing additional rules'), }).optional().describe('Updated actions to perform when conditions are met'), enabled: z.boolean().optional().describe('Whether the rule is enabled'), sequence: z.number().optional().describe('Rule execution order (lower numbers run first)'), }), execute: async (params) => { try { const account = accountsConfig.accounts.find(acc => acc.id === params.user_id || acc.email === params.user_id); if (!account) { throw new Error(`User not found: ${params.user_id}`); } const mailService = new MailService(account.email); // Get existing rule first const existingRule = await mailService.getMailRule(params.rule_id); if (!existingRule) { throw new Error(`Rule not found: ${params.rule_id}`); } // Build update data, only including provided fields const updateData = {}; if (params.rule_name !== undefined) { updateData.displayName = params.rule_name; } if (params.enabled !== undefined) { updateData.isEnabled = params.enabled; } if (params.sequence !== undefined) { updateData.sequence = params.sequence; } // Build updated conditions if provided if (params.conditions) { const graphConditions = {}; if (params.conditions.from_addresses?.length > 0) { graphConditions.fromAddresses = params.conditions.from_addresses.map((addr) => ({ emailAddress: { address: addr } })); } if (params.conditions.subject_contains?.length > 0) { graphConditions.subjectContains = params.conditions.subject_contains; } if (params.conditions.body_contains?.length > 0) { graphConditions.bodyContains = params.conditions.body_contains; } if (params.conditions.sent_to?.length > 0) { graphConditions.recipientContains = params.conditions.sent_to.map((addr) => ({ emailAddress: { address: addr } })); } if (params.conditions.importance) { graphConditions.importance = params.conditions.importance; } if (params.conditions.has_attachments !== undefined) { graphConditions.hasAttachments = params.conditions.has_attachments; } if (params.conditions.to_me) { graphConditions.sentToMe = true; } if (params.conditions.cc_me) { graphConditions.sentCcMe = true; } updateData.conditions = graphConditions; } // Build updated actions if provided if (params.actions) { const graphActions = {}; if (params.actions.move_to_folder) { graphActions.moveToFolder = params.actions.move_to_folder; } if (params.actions.copy_to_folder) { graphActions.copyToFolder = params.actions.copy_to_folder; } if (params.actions.add_categories?.length > 0) { graphActions.assignCategories = params.actions.add_categories; } if (params.actions.mark_as_read !== undefined) { graphActions.markAsRead = params.actions.mark_as_read; } if (params.actions.mark_importance) { graphActions.markImportance = params.actions.mark_importance; } if (params.actions.forward_to) { graphActions.forwardTo = { emailAddress: { address: params.actions.forward_to } }; } if (params.actions.delete_message) { graphActions.delete = true; } if (params.actions.stop_processing !== undefined) { graphActions.stopProcessingRules = params.actions.stop_processing; } updateData.actions = graphActions; } const updatedRule = await mailService.updateMailRule(params.rule_id, updateData); return { content: [ { type: 'text', text: JSON.stringify({ success: true, rule: { id: updatedRule.id, displayName: updatedRule.displayName, sequence: updatedRule.sequence, isEnabled: updatedRule.isEnabled, conditions: updatedRule.conditions, actions: updatedRule.actions, }, changes_made: Object.keys(updateData), message: `Successfully updated mail rule '${updatedRule.displayName}'`, }, null, 2), }, ], }; } catch (error) { return { content: [ { type: 'text', text: `Error modifying mail rule: ${error instanceof Error ? error.message : 'Unknown error'}`, }, ], }; } }, }; //# sourceMappingURL=modifyMailRule.js.map