UNPKG

outlook-mcp

Version:

Comprehensive MCP server for Claude to access Microsoft Outlook and Teams via Microsoft Graph API - including Email, Calendar, Contacts, Tasks, Teams, Chats, and Online Meetings

156 lines (132 loc) 4.24 kB
/** * Email attachments functionality */ const { callGraphAPI } = require('../utils/graph-api'); const { ensureAuthenticated } = require('../auth'); /** * List email attachments handler * @param {object} args - Tool arguments * @returns {object} - MCP response */ async function handleListAttachments(args) { try { const { emailId } = args; if (!emailId) { return { error: { code: -32602, message: "Email ID is required" } }; } // Ensure user is authenticated const accessToken = await ensureAuthenticated(); // Build the API path const apiPath = `me/messages/${emailId}/attachments`; // Build query parameters const queryParams = { '$select': 'id,name,size,contentType,isInline,lastModifiedDateTime' }; console.error(`Fetching attachments for email: ${emailId}`); // Make API call const response = await callGraphAPI(accessToken, 'GET', apiPath, null, queryParams); const attachments = response.value || []; // Format file size const formatSize = (bytes) => { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; return { content: [ { type: "text", text: `Found ${attachments.length} attachments:\n\n${attachments.map(attachment => { const inline = attachment.isInline ? ' (Inline)' : ''; const modified = attachment.lastModifiedDateTime ? new Date(attachment.lastModifiedDateTime).toLocaleString() : 'Unknown'; return `📎 ${attachment.name}${inline} ID: ${attachment.id} Size: ${formatSize(attachment.size)} Type: ${attachment.contentType} Modified: ${modified}`; }).join('\n\n')}` } ] }; } catch (error) { console.error('Error in handleListAttachments:', error); return { error: { code: -32603, message: `Failed to list attachments: ${error.message}` } }; } } /** * Download email attachment handler * @param {object} args - Tool arguments * @returns {object} - MCP response */ async function handleDownloadAttachment(args) { try { const { emailId, attachmentId } = args; if (!emailId || !attachmentId) { return { error: { code: -32602, message: "Email ID and attachment ID are required" } }; } // Ensure user is authenticated const accessToken = await ensureAuthenticated(); // Build the API path const apiPath = `me/messages/${emailId}/attachments/${attachmentId}`; // Build query parameters - get full attachment data const queryParams = { '$select': 'id,name,size,contentType,contentBytes,isInline' }; console.error(`Downloading attachment: ${attachmentId} from email: ${emailId}`); // Make API call const attachment = await callGraphAPI(accessToken, 'GET', apiPath, null, queryParams); // Format file size const formatSize = (bytes) => { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; }; return { content: [ { type: "text", text: `✅ Attachment downloaded successfully! **File Name:** ${attachment.name} **Size:** ${formatSize(attachment.size)} **Type:** ${attachment.contentType} **Content:** The attachment content is available in base64 format. **Base64 Content:** ${attachment.contentBytes} You can decode this base64 content to save the file locally.` } ] }; } catch (error) { console.error('Error in handleDownloadAttachment:', error); return { error: { code: -32603, message: `Failed to download attachment: ${error.message}` } }; } } module.exports = { handleListAttachments, handleDownloadAttachment };