UNPKG

msexchange-mcp

Version:

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

95 lines 4.33 kB
import { z } from 'zod'; import { UnifiedSearchService } from '../services/unifiedSearch.js'; import { MailService } from '../services/mail.js'; import { formatEmailForMCP } from '../utils/formatters.js'; import { logger } from '../utils/logger.js'; const inputSchema = z.object({ user_id: z.string().describe('The user ID or email address'), query: z.string().describe('Natural language description of what emails to find (e.g., "emails from john@example.com about project X", "unread emails with attachments", "emails from KPMG")'), limit: z.number().optional().default(20).describe('Maximum number of results'), include_body: z.boolean().optional().default(false).describe('Include full email content'), date_start: z.string().optional().describe('Start date in ISO format (e.g., "2025-01-01")'), date_end: z.string().optional().describe('End date in ISO format (e.g., "2025-01-31")'), }); export const simpleEmailSearchTool = { name: 'simple_email_search', description: 'Simple, user-friendly email search that automatically handles complex query optimization. Just describe what you\'re looking for in natural language.', parameters: inputSchema, execute: async ({ user_id, query, limit, include_body, date_start, date_end }) => { try { logger.info('Simple email search (redirecting to unified search)', { user_id, query }); const mailService = MailService.getInstance(); const searchService = new UnifiedSearchService(mailService); // Build search query with date range if provided const searchQuery = { text: query, requireAllTerms: true, includeAliases: true, semanticSearch: true, limit, dateRange: (date_start || date_end) ? { start: date_start ? new Date(date_start) : undefined, end: date_end ? new Date(date_end) : undefined, } : undefined, }; // Use unified search const result = await searchService.search(searchQuery, { accountId: user_id, limit, includeBody: include_body, }); // Format response if (result.emails.length === 0) { let response = 'No emails found matching your search.\n\n'; if (result.suggestions && result.suggestions.length > 0) { response += 'Suggestions:\n'; result.suggestions.forEach(suggestion => { response += `• ${suggestion}\n`; }); } return { content: [ { type: 'text', text: response, }, ], }; } let response = `Found ${result.totalCount} email${result.totalCount !== 1 ? 's' : ''}`; if (result.searchStrategy === 'or_fallback') { response += ' (showing emails with ANY of your search terms)'; } response += '\n\n'; const formattedEmails = result.emails.map(email => formatEmailForMCP(email, { includeBody: include_body, includeHeaders: false, maxBodyLength: include_body ? 1000 : 0, })); response += formattedEmails.join('\n' + '─'.repeat(50) + '\n'); if (result.hasMore) { response += `\n\nShowing ${limit} of ${result.totalCount}+ results.`; } return { content: [ { type: 'text', text: response, }, ], }; } catch (error) { logger.error('Simple email search error', { error }); return { content: [ { type: 'text', text: `Search failed: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }, }; //# sourceMappingURL=simpleEmailSearch.js.map