msexchange-mcp
Version:
MCP server for Microsoft Exchange/Outlook email operations via Microsoft Graph API
112 lines (108 loc) • 5.06 kB
JavaScript
import { z } from 'zod';
import { MailService } from '../mail/mailService.js';
import accountsConfig from '../config/accountsLoader.js';
export const createDraftTool = {
name: 'create_draft',
description: `Create a draft email message for later editing or sending.
Features:
- Save emails as drafts for later completion
- Support for HTML and plain text formats
- Add attachments up to 4MB each
- Multiple recipients (to, cc, bcc)
- Returns draft ID for future operations
Use cases:
- Compose complex emails over time
- Create templates for repeated use
- Prepare emails for review before sending
- Stage emails with attachments
Examples:
- Simple draft: {"to": ["recipient@example.com"], "subject": "Draft", "body": "To be completed..."}
- HTML template: {"subject": "Weekly Report Template", "body": "<h1>Weekly Report</h1><p>Status: [TODO]</p>", "body_type": "HTML"}
- With attachment ready: {"to": ["team@company.com"], "subject": "Proposal", "body": "Please review", "attachments": [{"name": "proposal.pdf", "content": "base64..."}]}
Best practices:
- Use drafts for emails requiring multiple edits
- Create template drafts for recurring emails
- Add attachments to drafts to verify size limits
- Save draft ID for future updates`,
parameters: z.object({
user_id: z.string().describe('The user ID or email address'),
to: z.array(z.string()).optional().describe('Array of recipient email addresses'),
cc: z.array(z.string()).optional().describe('Array of CC recipient email addresses'),
bcc: z.array(z.string()).optional().describe('Array of BCC recipient email addresses'),
subject: z.string().describe('Email subject'),
body: z.string().describe('Email body content'),
body_type: z.enum(['Text', 'HTML']).default('Text').describe('Body content type'),
attachments: z.array(z.object({
name: z.string().describe('Attachment filename'),
content: z.string().describe('Base64 encoded file content'),
contentType: z.string().optional().describe('MIME type (e.g., "application/pdf", "image/jpeg")')
})).optional().describe('Array of file attachments (max 4MB each)'),
}),
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);
const draft = {
subject: params.subject,
body: {
contentType: params.body_type || 'Text',
content: params.body,
},
toRecipients: params.to?.map(email => ({
emailAddress: { address: email }
})),
ccRecipients: params.cc?.map(email => ({
emailAddress: { address: email }
})),
bccRecipients: params.bcc?.map(email => ({
emailAddress: { address: email }
})),
};
// Add attachments if provided
if (params.attachments && params.attachments.length > 0) {
draft.attachments = params.attachments.map(att => ({
'@odata.type': '#microsoft.graph.fileAttachment',
name: att.name,
contentType: att.contentType || 'application/octet-stream',
contentBytes: att.content,
}));
// Check attachment sizes (rough estimate - base64 is ~33% larger than binary)
for (const att of params.attachments) {
const estimatedSize = (att.content.length * 3) / 4;
if (estimatedSize > 4 * 1024 * 1024) {
throw new Error(`Attachment "${att.name}" exceeds 4MB limit`);
}
}
}
const createdDraft = await mailService.createDraft(draft);
return {
content: [
{
type: 'text',
text: JSON.stringify({
message: 'Draft created successfully',
draftId: createdDraft.id,
subject: createdDraft.subject,
hasAttachments: createdDraft.hasAttachments || false,
attachmentCount: params.attachments?.length || 0,
}, null, 2),
},
],
};
}
catch (error) {
return {
content: [
{
type: 'text',
text: `Error creating draft: ${error instanceof Error ? error.message : 'Unknown error'}`,
},
],
};
}
},
};
//# sourceMappingURL=createDraft.js.map