Skip to main content
Glama

Lambda Performance MCP Server

by jghidalgo
index.js20.8 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import dotenv from 'dotenv'; import { LambdaAnalyzer } from './src/lambda-analyzer.js'; import { PerformanceOptimizer } from './src/performance-optimizer.js'; import { ColdStartTracker } from './src/cold-start-tracker.js'; dotenv.config(); class LambdaPerformanceMCPServer { constructor() { this.server = new Server( { name: 'lambda-performance-analyzer', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); this.lambdaAnalyzer = new LambdaAnalyzer(); this.performanceOptimizer = new PerformanceOptimizer(); this.coldStartTracker = new ColdStartTracker(); this.setupToolHandlers(); } setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'analyze_lambda_performance', description: 'Analyze Lambda function performance metrics including cold starts, duration, and errors', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function to analyze' }, timeRange: { type: 'string', enum: ['1h', '6h', '24h', '7d', '30d'], description: 'Time range for analysis (default: 24h)' }, includeDetails: { type: 'boolean', description: 'Include detailed metrics and logs (default: true)' } }, required: ['functionName'] } }, { name: 'track_cold_starts', description: 'Track and analyze cold start patterns for Lambda functions', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function' }, timeRange: { type: 'string', enum: ['1h', '6h', '24h', '7d'], description: 'Time range for cold start analysis (default: 24h)' } }, required: ['functionName'] } }, { name: 'get_optimization_recommendations', description: 'Get performance optimization recommendations for Lambda functions', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function' }, analysisType: { type: 'string', enum: ['cold-start', 'memory', 'duration', 'cost', 'all'], description: 'Type of optimization analysis (default: all)' } }, required: ['functionName'] } }, { name: 'compare_lambda_performance', description: 'Compare performance metrics between multiple Lambda functions', inputSchema: { type: 'object', properties: { functionNames: { type: 'array', items: { type: 'string' }, description: 'List of Lambda function names to compare' }, timeRange: { type: 'string', enum: ['1h', '6h', '24h', '7d'], description: 'Time range for comparison (default: 24h)' }, metrics: { type: 'array', items: { type: 'string', enum: ['duration', 'cold-starts', 'errors', 'invocations', 'cost'] }, description: 'Metrics to compare (default: all)' } }, required: ['functionNames'] } }, { name: 'list_lambda_functions', description: 'List all Lambda functions in the account with basic performance info', inputSchema: { type: 'object', properties: { runtime: { type: 'string', description: 'Filter by runtime (e.g., nodejs18.x, python3.9)' }, includeMetrics: { type: 'boolean', description: 'Include basic performance metrics (default: false)' } } } }, { name: 'analyze_memory_utilization', description: 'Analyze memory utilization and provide right-sizing recommendations', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function' }, timeRange: { type: 'string', enum: ['1h', '6h', '24h', '7d'], description: 'Time range for memory analysis (default: 24h)' } }, required: ['functionName'] } }, { name: 'get_cost_analysis', description: 'Analyze Lambda function costs and identify optimization opportunities', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function (optional for account-wide analysis)' }, timeRange: { type: 'string', enum: ['24h', '7d', '30d'], description: 'Time range for cost analysis (default: 30d)' } } } }, { name: 'monitor_real_time_performance', description: 'Get real-time performance metrics and alerts for Lambda functions', inputSchema: { type: 'object', properties: { functionName: { type: 'string', description: 'Name of the Lambda function' }, duration: { type: 'number', description: 'Monitoring duration in minutes (default: 5)' } }, required: ['functionName'] } } ] }; }); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'analyze_lambda_performance': return await this.analyzeLambdaPerformance(args); case 'track_cold_starts': return await this.trackColdStarts(args); case 'get_optimization_recommendations': return await this.getOptimizationRecommendations(args); case 'compare_lambda_performance': return await this.compareLambdaPerformance(args); case 'list_lambda_functions': return await this.listLambdaFunctions(args); case 'analyze_memory_utilization': return await this.analyzeMemoryUtilization(args); case 'get_cost_analysis': return await this.getCostAnalysis(args); case 'monitor_real_time_performance': return await this.monitorRealTimePerformance(args); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Error executing ${name}: ${error.message}` } ] }; } }); } async analyzeLambdaPerformance(args) { const { functionName, timeRange = '24h', includeDetails = true } = args; const analysis = await this.lambdaAnalyzer.analyzeFunction( functionName, timeRange, includeDetails ); return { content: [ { type: 'text', text: `# Lambda Performance Analysis: ${functionName}\n\n` + `## Summary\n` + `- **Total Invocations**: ${analysis.totalInvocations.toLocaleString()}\n` + `- **Average Duration**: ${analysis.avgDuration}ms\n` + `- **Cold Start Rate**: ${analysis.coldStartRate}%\n` + `- **Error Rate**: ${analysis.errorRate}%\n` + `- **Memory Utilization**: ${analysis.memoryUtilization}%\n\n` + `## Performance Metrics\n` + `- **P50 Duration**: ${analysis.p50Duration}ms\n` + `- **P95 Duration**: ${analysis.p95Duration}ms\n` + `- **P99 Duration**: ${analysis.p99Duration}ms\n` + `- **Max Duration**: ${analysis.maxDuration}ms\n\n` + `## Cold Start Analysis\n` + `- **Total Cold Starts**: ${analysis.coldStarts.total}\n` + `- **Average Cold Start Duration**: ${analysis.coldStarts.avgDuration}ms\n` + `- **Cold Start Pattern**: ${analysis.coldStarts.pattern}\n\n` + `${includeDetails ? this.formatDetailedMetrics(analysis.details) : ''}` } ] }; } async trackColdStarts(args) { const { functionName, timeRange = '24h' } = args; const coldStartData = await this.coldStartTracker.trackColdStarts( functionName, timeRange ); return { content: [ { type: 'text', text: `# Cold Start Analysis: ${functionName}\n\n` + `## Cold Start Statistics\n` + `- **Total Cold Starts**: ${coldStartData.total}\n` + `- **Cold Start Rate**: ${coldStartData.rate}%\n` + `- **Average Cold Start Duration**: ${coldStartData.avgDuration}ms\n` + `- **Longest Cold Start**: ${coldStartData.maxDuration}ms\n\n` + `## Cold Start Patterns\n` + `- **Peak Hours**: ${coldStartData.peakHours.join(', ')}\n` + `- **Frequency**: ${coldStartData.frequency}\n` + `- **Triggers**: ${coldStartData.triggers.join(', ')}\n\n` + `## Optimization Opportunities\n` + `${coldStartData.recommendations.map(rec => `- ${rec}`).join('\n')}\n\n` + `## Timeline\n` + `${this.formatColdStartTimeline(coldStartData.timeline)}` } ] }; } async getOptimizationRecommendations(args) { const { functionName, analysisType = 'all' } = args; const recommendations = await this.performanceOptimizer.getRecommendations( functionName, analysisType ); return { content: [ { type: 'text', text: `# Optimization Recommendations: ${functionName}\n\n` + `## Priority Recommendations\n` + `${recommendations.priority.map((rec, i) => `${i + 1}. **${rec.title}** (Impact: ${rec.impact})\n` + ` - ${rec.description}\n` + ` - Implementation: ${rec.implementation}\n` + ` - Expected Improvement: ${rec.expectedImprovement}\n` ).join('\n')}\n` + `## Additional Optimizations\n` + `${recommendations.additional.map(rec => `- ${rec}`).join('\n')}\n\n` + `## Configuration Recommendations\n` + `- **Memory**: ${recommendations.config.memory}MB\n` + `- **Timeout**: ${recommendations.config.timeout}s\n` + `- **Runtime**: ${recommendations.config.runtime}\n` + `- **Architecture**: ${recommendations.config.architecture}\n\n` + `## Cost Impact\n` + `- **Current Monthly Cost**: $${recommendations.cost.current}\n` + `- **Optimized Monthly Cost**: $${recommendations.cost.optimized}\n` + `- **Potential Savings**: $${recommendations.cost.savings} (${recommendations.cost.savingsPercent}%)` } ] }; } async compareLambdaPerformance(args) { const { functionNames, timeRange = '24h', metrics = ['duration', 'cold-starts', 'errors', 'invocations', 'cost'] } = args; const comparison = await this.lambdaAnalyzer.compareFunctions( functionNames, timeRange, metrics ); return { content: [ { type: 'text', text: `# Lambda Performance Comparison\n\n` + `## Functions Analyzed\n` + `${functionNames.map(name => `- ${name}`).join('\n')}\n\n` + `## Performance Comparison\n` + `${this.formatComparisonTable(comparison)}\n\n` + `## Key Insights\n` + `${comparison.insights.map(insight => `- ${insight}`).join('\n')}\n\n` + `## Recommendations\n` + `${comparison.recommendations.map(rec => `- ${rec}`).join('\n')}` } ] }; } async listLambdaFunctions(args) { const { runtime, includeMetrics = false } = args; const functions = await this.lambdaAnalyzer.listFunctions(runtime, includeMetrics); return { content: [ { type: 'text', text: `# Lambda Functions\n\n` + `## Summary\n` + `- **Total Functions**: ${functions.length}\n` + `- **Runtimes**: ${[...new Set(functions.map(f => f.runtime))].join(', ')}\n\n` + `## Functions List\n` + `${functions.map(func => `### ${func.name}\n` + `- **Runtime**: ${func.runtime}\n` + `- **Memory**: ${func.memory}MB\n` + `- **Timeout**: ${func.timeout}s\n` + `- **Last Modified**: ${func.lastModified}\n` + `${includeMetrics ? `- **Avg Duration**: ${func.metrics?.avgDuration || 'N/A'}ms\n` + `- **Cold Start Rate**: ${func.metrics?.coldStartRate || 'N/A'}%\n` + `- **Error Rate**: ${func.metrics?.errorRate || 'N/A'}%\n` : ''}\n` ).join('')}` } ] }; } async analyzeMemoryUtilization(args) { const { functionName, timeRange = '24h' } = args; const memoryAnalysis = await this.lambdaAnalyzer.analyzeMemoryUtilization( functionName, timeRange ); return { content: [ { type: 'text', text: `# Memory Utilization Analysis: ${functionName}\n\n` + `## Current Configuration\n` + `- **Allocated Memory**: ${memoryAnalysis.allocated}MB\n` + `- **Average Used**: ${memoryAnalysis.avgUsed}MB (${memoryAnalysis.utilizationPercent}%)\n` + `- **Peak Usage**: ${memoryAnalysis.peakUsed}MB\n` + `- **Minimum Usage**: ${memoryAnalysis.minUsed}MB\n\n` + `## Right-sizing Recommendation\n` + `- **Recommended Memory**: ${memoryAnalysis.recommended}MB\n` + `- **Reasoning**: ${memoryAnalysis.reasoning}\n` + `- **Expected Performance Impact**: ${memoryAnalysis.performanceImpact}\n` + `- **Cost Impact**: ${memoryAnalysis.costImpact}\n\n` + `## Memory Usage Patterns\n` + `${memoryAnalysis.patterns.map(pattern => `- ${pattern}`).join('\n')}` } ] }; } async getCostAnalysis(args) { const { functionName, timeRange = '30d' } = args; const costAnalysis = await this.lambdaAnalyzer.analyzeCosts( functionName, timeRange ); return { content: [ { type: 'text', text: `# Cost Analysis${functionName ? `: ${functionName}` : ' (Account-wide)'}\n\n` + `## Cost Breakdown\n` + `- **Total Cost**: $${costAnalysis.total}\n` + `- **Compute Cost**: $${costAnalysis.compute} (${costAnalysis.computePercent}%)\n` + `- **Request Cost**: $${costAnalysis.requests} (${costAnalysis.requestsPercent}%)\n` + `- **Data Transfer**: $${costAnalysis.dataTransfer}\n\n` + `## Usage Statistics\n` + `- **Total Invocations**: ${costAnalysis.invocations.toLocaleString()}\n` + `- **Total Duration**: ${costAnalysis.totalDuration}ms\n` + `- **Average Duration**: ${costAnalysis.avgDuration}ms\n\n` + `## Cost Optimization Opportunities\n` + `${costAnalysis.optimizations.map(opt => `- **${opt.type}**: ${opt.description} (Potential savings: $${opt.savings})` ).join('\n')}\n\n` + `## Trends\n` + `- **Daily Average**: $${costAnalysis.dailyAverage}\n` + `- **Trend**: ${costAnalysis.trend}\n` + `- **Peak Day**: ${costAnalysis.peakDay} ($${costAnalysis.peakCost})` } ] }; } async monitorRealTimePerformance(args) { const { functionName, duration = 5 } = args; const monitoring = await this.lambdaAnalyzer.monitorRealTime( functionName, duration ); return { content: [ { type: 'text', text: `# Real-time Performance Monitoring: ${functionName}\n\n` + `## Live Metrics (Last ${duration} minutes)\n` + `- **Active Invocations**: ${monitoring.activeInvocations}\n` + `- **Recent Invocations**: ${monitoring.recentInvocations}\n` + `- **Average Duration**: ${monitoring.avgDuration}ms\n` + `- **Error Rate**: ${monitoring.errorRate}%\n` + `- **Cold Starts**: ${monitoring.coldStarts}\n\n` + `## Performance Alerts\n` + `${monitoring.alerts.length > 0 ? monitoring.alerts.map(alert => `${alert}`).join('\n') : 'No performance issues detected'}\n\n` + `## Recent Activity\n` + `${monitoring.recentActivity.map(activity => `- ${activity.timestamp}: ${activity.event} (${activity.duration}ms)` ).join('\n')}` } ] }; } formatDetailedMetrics(details) { return `## Detailed Metrics\n` + `### Error Analysis\n` + `${details.errors.map(error => `- ${error.type}: ${error.count} occurrences`).join('\n')}\n\n` + `### Performance Trends\n` + `${details.trends.map(trend => `- ${trend}`).join('\n')}\n\n`; } formatColdStartTimeline(timeline) { return timeline.map(entry => `- ${entry.time}: ${entry.coldStarts} cold starts (${entry.duration}ms avg)` ).join('\n'); } formatComparisonTable(comparison) { const headers = ['Function', ...comparison.metrics]; const rows = comparison.functions.map(func => [ func.name, ...comparison.metrics.map(metric => func.values[metric]) ]); return `| ${headers.join(' | ')} |\n` + `| ${headers.map(() => '---').join(' | ')} |\n` + rows.map(row => `| ${row.join(' | ')} |`).join('\n'); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Lambda Performance MCP Server running on stdio'); } } const server = new LambdaPerformanceMCPServer(); server.run().catch(console.error);

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jghidalgo/lambda-performance-mcp-nodejs'

If you have feedback or need assistance with the MCP directory API, please join our Discord server