msexchange-mcp
Version:
MCP server for Microsoft Exchange/Outlook email operations via Microsoft Graph API
162 lines (126 loc) • 4.93 kB
Markdown
# 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.**