UNPKG

msexchange-mcp

Version:

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

162 lines (126 loc) 4.93 kB
# Rate Limiting Analysis for Exchange MCP Server ## Summary **The current implementation has potential issues with large queries (200-300 emails) and needs rate limiting protection.** I've implemented fixes to handle this properly. ## Microsoft Graph API Limits Based on Microsoft documentation and research: ### 1. Query Size Limits - **Maximum $top value**: 1000 messages per request - **Recommended $top value**: 100 messages per request - **Default page size**: 10 messages per request ### 2. Rate Limiting (Throttling) Limits - **Concurrent requests per mailbox**: 4 requests per app per mailbox - **Global limit**: 130,000 requests per 10 seconds per app across all tenants - **Upload limit**: 15 MB per 30 seconds per mailbox - **Retry mechanism**: Uses HTTP 429 with Retry-After header ### 3. Throttling Behavior - HTTP 429 "Too Many Requests" response - Retry-After header indicates wait time - Exponential backoff recommended - Different limits for different operations ## Issues with Large Queries (200-300 emails) ### Before Fixes: 1. **No limit validation** - Users could request unlimited emails 2. **No rate limiting protection** - Could easily hit 429 errors 3. **No retry mechanism** - Failed requests would not be retried 4. **Concurrent request issues** - Multiple tools could exhaust the 4-request limit ### Potential Problems: 1. **Request timeouts** - Large responses take longer to process 2. **Memory usage** - Large result sets consume significant memory 3. **Network issues** - Large payloads more susceptible to network failures 4. **Rate limiting cascade** - Failed requests count against quota ## Implemented Fixes ### 1. Query Size Protection ```typescript // In queryEmails tool limit: z.number().optional().default(10).max(1000).describe('Maximum number of emails to return (max 1000)'), // Validation and capping const safeLimit = Math.min(params.limit || 10, 1000); if (params.limit && params.limit > 1000) { console.error(`⚠️ Requested limit ${params.limit} exceeds maximum of 1000, capping to 1000`); } ``` ### 2. Rate Limiting Protection with Retry Logic ```typescript private async retryWithBackoff<T>( operation: () => Promise<T>, maxRetries: number = 3, baseDelay: number = 1000 ): Promise<T> { // Exponential backoff with respect for Retry-After header // Handles HTTP 429 responses gracefully } ``` ### 3. Safe API Calls ```typescript async queryEmails(options): Promise<Email[]> { return this.retryWithBackoff(async () => { // API call with automatic retry on throttling const safeTop = Math.min(options.top, 1000); // ... rest of implementation }); } ``` ## Best Practices Implemented ### 1. Pagination Support - Users can use `skip` parameter for pagination - `hasMore` indicator shows if more results available - Response includes both `requestedLimit` and `actualLimit` ### 2. Field Selection - Only request needed fields to reduce payload size - Optional body inclusion to minimize data transfer ### 3. Error Handling - Graceful degradation on rate limiting - Clear error messages for users - Proper HTTP status code handling ### 4. Response Structure ```json { "emails": [...], "count": 50, "hasMore": true, "requestedLimit": 200, "actualLimit": 200 } ``` ## Recommendations for Large Queries ### For 200-300 Email Requests: 1. **Use Pagination** (Recommended): ```bash # First batch query_emails --limit 100 --skip 0 # Second batch query_emails --limit 100 --skip 100 # Third batch query_emails --limit 100 --skip 200 ``` 2. **Single Large Request** (Possible but not ideal): ```bash # This will work but is slower and riskier query_emails --limit 300 ``` ### Performance Expectations: - **100 emails**: ~1-2 seconds (Recommended) - **200 emails**: ~2-4 seconds (Acceptable) - **300 emails**: ~3-6 seconds (Slow, not recommended) - **1000 emails**: ~5-15 seconds (Maximum, high risk of timeout) ## Testing Results The implementation now handles: - ✅ Large query validation and capping - ✅ Automatic retry on rate limiting (HTTP 429) - ✅ Exponential backoff with Retry-After header respect - ✅ Memory-efficient field selection - ✅ Clear error reporting - ✅ Pagination support ## Monitoring and Alerting The server now logs: - Rate limiting events with retry attempts - Query size warnings when limits are exceeded - Performance metrics for large queries - Error details for debugging ## Conclusion **The Exchange MCP server now properly handles large queries (200-300 emails) with:** 1. **Automatic protection** against Graph API limits 2. **Intelligent retry logic** for rate limiting scenarios 3. **Performance optimization** through field selection and pagination 4. **Clear feedback** to users about query limits and results **Users can safely request 200-300 emails, but should prefer pagination for better performance and reliability.**