import type { Tool } from '@modelcontextprotocol/sdk/types.js';
import { CloudWatchClient, GetMetricStatisticsCommand } from '@aws-sdk/client-cloudwatch';
import { credentialManager } from '../utils/credential-manager.js';
import type { CloudProvider, Metric } from '../types/index.js';
export const monitoringTools: Tool[] = [
{
name: 'get_metrics',
description: 'Get metrics for a cloud resource',
inputSchema: {
type: 'object',
properties: {
provider: {
type: 'string',
enum: ['aws', 'azure', 'gcp'],
description: 'Cloud provider',
},
resourceId: {
type: 'string',
description: 'Resource ID',
},
metricName: {
type: 'string',
description: 'Metric name (e.g., CPUUtilization, NetworkIn)',
},
startTime: {
type: 'string',
description: 'Start time (ISO 8601)',
},
endTime: {
type: 'string',
description: 'End time (ISO 8601)',
},
period: {
type: 'number',
description: 'Period in seconds',
default: 3600,
},
},
required: ['provider', 'resourceId', 'metricName', 'startTime', 'endTime'],
},
},
{
name: 'list_alarms',
description: 'List monitoring alarms',
inputSchema: {
type: 'object',
properties: {
provider: {
type: 'string',
enum: ['aws', 'azure', 'gcp'],
description: 'Cloud provider',
},
resourceId: {
type: 'string',
description: 'Resource ID (optional)',
},
},
required: ['provider'],
},
},
{
name: 'get_resource_health',
description: 'Get health status of a cloud resource',
inputSchema: {
type: 'object',
properties: {
provider: {
type: 'string',
enum: ['aws', 'azure', 'gcp'],
description: 'Cloud provider',
},
resourceId: {
type: 'string',
description: 'Resource ID',
},
resourceType: {
type: 'string',
enum: ['instance', 'storage', 'database', 'function'],
description: 'Resource type',
},
},
required: ['provider', 'resourceId', 'resourceType'],
},
},
];
export async function handleMonitoringTool(name: string, args: unknown): Promise<unknown> {
const params = args as Record<string, unknown>;
const provider = params.provider as CloudProvider;
switch (name) {
case 'get_metrics': {
const resourceId = params.resourceId as string;
const metricName = params.metricName as string;
const startTime = params.startTime as string;
const endTime = params.endTime as string;
const period = (params.period as number) || 3600;
if (provider === 'aws') {
return await getAWSMetrics(resourceId, metricName, startTime, endTime, period);
}
return { message: `Metrics not yet implemented for ${provider}` };
}
case 'list_alarms': {
return { message: `Alarm listing not yet fully implemented for ${provider}` };
}
case 'get_resource_health': {
const resourceId = params.resourceId as string;
const resourceType = params.resourceType as string;
return {
provider,
resourceId,
resourceType,
health: 'unknown',
message: 'Resource health check not yet fully implemented',
};
}
default:
throw new Error(`Unknown monitoring tool: ${name}`);
}
}
async function getAWSMetrics(
resourceId: string,
metricName: string,
startTime: string,
endTime: string,
period: number
): Promise<Metric[]> {
try {
const credentials = await credentialManager.getCredentials('aws');
if (!credentials) {
throw new Error('AWS credentials not found');
}
const client = new CloudWatchClient({
region: credentials.region || 'us-east-1',
credentials: credentials.accessKeyId && credentials.secretAccessKey
? {
accessKeyId: credentials.accessKeyId,
secretAccessKey: credentials.secretAccessKey,
}
: undefined,
});
// Determine namespace based on resource type
let namespace = 'AWS/EC2';
if (resourceId.includes('lambda')) {
namespace = 'AWS/Lambda';
} else if (resourceId.includes('rds')) {
namespace = 'AWS/RDS';
}
const command = new GetMetricStatisticsCommand({
Namespace: namespace,
MetricName: metricName,
Dimensions: [
{
Name: namespace === 'AWS/EC2' ? 'InstanceId' : 'FunctionName',
Value: resourceId,
},
],
StartTime: new Date(startTime),
EndTime: new Date(endTime),
Period: period,
Statistics: ['Average', 'Maximum', 'Minimum'],
});
const response = await client.send(command);
const metrics: Metric[] = [];
if (response.Datapoints) {
for (const datapoint of response.Datapoints) {
if (datapoint.Timestamp && datapoint.Average !== undefined) {
metrics.push({
name: metricName,
value: datapoint.Average,
unit: datapoint.Unit || 'Count',
timestamp: datapoint.Timestamp,
});
}
}
}
return metrics.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
} catch (error) {
throw new Error(`Failed to get AWS metrics: ${error instanceof Error ? error.message : String(error)}`);
}
}