awslabs.cloudwatch-mcp-server 0.0.10__py3-none-any.whl → 0.0.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,19 +18,32 @@ import boto3
18
18
  import json
19
19
  import os
20
20
  from awslabs.cloudwatch_mcp_server import MCP_SERVER_VERSION
21
+ from awslabs.cloudwatch_mcp_server.cloudwatch_metrics.cloudformation_template_generator import (
22
+ CloudFormationTemplateGenerator,
23
+ )
24
+ from awslabs.cloudwatch_mcp_server.cloudwatch_metrics.constants import (
25
+ COMPARISON_OPERATOR_ANOMALY,
26
+ DEFAULT_ANALYSIS_PERIOD_MINUTES,
27
+ )
28
+ from awslabs.cloudwatch_mcp_server.cloudwatch_metrics.metric_analyzer import MetricAnalyzer
29
+ from awslabs.cloudwatch_mcp_server.cloudwatch_metrics.metric_data_decomposer import Seasonality
21
30
  from awslabs.cloudwatch_mcp_server.cloudwatch_metrics.models import (
22
31
  AlarmRecommendation,
23
32
  AlarmRecommendationDimension,
33
+ AlarmRecommendationResult,
24
34
  AlarmRecommendationThreshold,
35
+ AnomalyDetectionAlarmThreshold,
25
36
  Dimension,
26
37
  GetMetricDataResponse,
38
+ MetricData,
27
39
  MetricDataPoint,
28
40
  MetricDataResult,
29
41
  MetricMetadata,
30
42
  MetricMetadataIndexKey,
43
+ StaticAlarmThreshold,
31
44
  )
32
45
  from botocore.config import Config
33
- from datetime import datetime
46
+ from datetime import datetime, timedelta, timezone
34
47
  from loguru import logger
35
48
  from mcp.server.fastmcp import Context
36
49
  from pathlib import Path
@@ -48,6 +61,8 @@ class CloudWatchMetricsTools:
48
61
  self._load_and_index_metadata()
49
62
  )
50
63
  logger.info(f'Loaded {len(self.metric_metadata_index)} metric metadata entries')
64
+ self.cloudformation_generator = CloudFormationTemplateGenerator()
65
+ self.metric_analyzer = MetricAnalyzer()
51
66
 
52
67
  def _get_cloudwatch_client(self, region: str):
53
68
  """Create a CloudWatch client for the specified region."""
@@ -136,6 +151,9 @@ class CloudWatchMetricsTools:
136
151
  # Register get_metric_metadata tool
137
152
  mcp.tool(name='get_metric_metadata')(self.get_metric_metadata)
138
153
 
154
+ # Register analyze_metric tool
155
+ mcp.tool(name='analyze_metric')(self.analyze_metric)
156
+
139
157
  # Register get_recommended_metric_alarms tool
140
158
  mcp.tool(name='get_recommended_metric_alarms')(self.get_recommended_metric_alarms)
141
159
 
@@ -669,7 +687,22 @@ class CloudWatchMetricsTools:
669
687
  description='AWS region for consistency. Note: This function uses local metadata and does not make AWS API calls. Defaults to us-east-1.'
670
688
  ),
671
689
  ] = 'us-east-1',
672
- ) -> List[AlarmRecommendation]:
690
+ statistic: Annotated[
691
+ Literal[
692
+ 'AVG',
693
+ 'COUNT',
694
+ 'MAX',
695
+ 'MIN',
696
+ 'SUM',
697
+ 'Average',
698
+ 'Sum',
699
+ 'Maximum',
700
+ 'Minimum',
701
+ 'SampleCount',
702
+ ],
703
+ Field(description='The statistic to use for alarm recommendations'),
704
+ ] = 'AVG',
705
+ ) -> AlarmRecommendationResult:
673
706
  """Gets recommended alarms for a CloudWatch metric.
674
707
 
675
708
  This tool retrieves alarm recommendations for a specific CloudWatch metric
@@ -685,11 +718,19 @@ class CloudWatchMetricsTools:
685
718
  metric_name: The name of the metric (e.g., "CPUUtilization", "Duration")
686
719
  dimensions: List of dimensions with name and value pairs
687
720
  region: AWS region to query. Defaults to 'us-east-1'.
721
+ statistic: The statistic to use for alarm recommendations. Must match the metric's data type:
722
+ - Aggregate count metrics (RequestCount, Errors, Faults, Throttles, CacheHits, Connections, EventsProcessed): Use 'Sum'
723
+ - Event occurrence metrics (Invocations, CacheMisses): Use 'SampleCount'
724
+ - Utilization metrics (CPUUtilization, MemoryUtilization, DiskUtilization, NetworkUtilization): Use 'Average'
725
+ - Latency/Time metrics (Duration, Latency, ResponseTime, ProcessingTime, Delay, ExecutionTime, WaitTime): Use 'Average'
726
+ - Size metrics (PayloadSize, MessageSize, RequestSize, BodySize): Use 'Average'
727
+ If uncertain about the correct statistic for a custom metric, ask the user
728
+ to confirm the metric type before generating recommendations. Using the wrong statistic
729
+ (e.g., 'Average' on Invocations) will produce ineffective alarm thresholds
688
730
 
689
731
  Returns:
690
- List[AlarmRecommendation]: A list of alarm recommendations that match the
691
- provided dimensions. Empty list if no recommendations
692
- are found or available.
732
+ AlarmRecommendationResult: A result containing alarm recommendations and optional message.
733
+ Empty recommendations list if no recommendations are found.
693
734
 
694
735
  Example:
695
736
  recommendations = await get_recommended_metric_alarms(
@@ -714,12 +755,12 @@ class CloudWatchMetricsTools:
714
755
 
715
756
  if not metadata or 'alarmRecommendations' not in metadata:
716
757
  logger.info(f'No alarm recommendations found for {namespace}/{metric_name}')
717
- return []
718
-
719
- alarm_recommendations = metadata['alarmRecommendations']
720
- logger.info(
721
- f'Found {len(alarm_recommendations)} alarm recommendations for {namespace}/{metric_name}'
722
- )
758
+ alarm_recommendations = []
759
+ else:
760
+ alarm_recommendations = metadata['alarmRecommendations']
761
+ logger.info(
762
+ f'Found {len(alarm_recommendations)} alarm recommendations for {namespace}/{metric_name}'
763
+ )
723
764
 
724
765
  # Filter recommendations based on provided dimensions
725
766
  matching_recommendations = []
@@ -735,11 +776,58 @@ class CloudWatchMetricsTools:
735
776
  logger.warning(f'Error parsing alarm recommendation: {e}')
736
777
  continue
737
778
 
738
- logger.info(
739
- f'Returning {len(matching_recommendations)} matching alarm recommendations'
779
+ if len(matching_recommendations) > 0:
780
+ logger.info(
781
+ f'Found {len(matching_recommendations)} matching alarm recommendations'
782
+ )
783
+ return AlarmRecommendationResult(
784
+ recommendations=matching_recommendations,
785
+ message=f'Found {len(matching_recommendations)} matching alarm recommendations',
786
+ )
787
+
788
+ # Generate additional recommendations based on metric analysis
789
+ additional_recommendations = []
790
+ logger.info('No predefined recommendations found - performing metric analysis')
791
+ analysis_result = await self.analyze_metric(
792
+ ctx,
793
+ namespace,
794
+ metric_name,
795
+ dimensions,
796
+ region,
797
+ statistic,
740
798
  )
741
- return matching_recommendations
742
799
 
800
+ # Generate additional recommendations based on seasonality
801
+ seasonality_value = analysis_result.get('seasonality_seconds', 0)
802
+ seasonality = Seasonality.from_seconds(seasonality_value)
803
+
804
+ if seasonality != Seasonality.NONE:
805
+ anomaly_detector_data = self._create_anomaly_detector_data(
806
+ metric_name=metric_name,
807
+ namespace=namespace,
808
+ dimensions=dimensions,
809
+ seasonality=seasonality,
810
+ )
811
+ alarm_rec = self._parse_alarm_recommendation(anomaly_detector_data)
812
+ additional_recommendations.append(alarm_rec)
813
+ logger.info(
814
+ f'Recommended anomaly detection alarm due to seasonality: {seasonality.name}'
815
+ )
816
+
817
+ if len(additional_recommendations) > 0:
818
+ message = f'Generated {len(additional_recommendations)} alarm recommendation(s) for {namespace}/{metric_name} based on metric analysis'
819
+ logger.info(message)
820
+ return AlarmRecommendationResult(
821
+ recommendations=additional_recommendations,
822
+ message=message,
823
+ )
824
+
825
+ message = f'No alarm recommendations available for {namespace}/{metric_name} with the provided dimensions'
826
+ logger.info(message)
827
+ return AlarmRecommendationResult(
828
+ recommendations=[],
829
+ message=message,
830
+ )
743
831
  except Exception as e:
744
832
  logger.error(f'Error in get_recommended_metric_alarms: {str(e)}')
745
833
  await ctx.error(f'Error getting alarm recommendations: {str(e)}')
@@ -781,6 +869,30 @@ class CloudWatchMetricsTools:
781
869
 
782
870
  return True
783
871
 
872
+ def _create_alarm_threshold(
873
+ self, threshold_data: Dict[str, Any]
874
+ ) -> AlarmRecommendationThreshold:
875
+ """Create threshold object from threshold data.
876
+
877
+ Args:
878
+ threshold_data: Raw alarm threshold data
879
+
880
+ Returns:
881
+ AlarmRecommendationThreshold: Appropriate threshold object based on threshold type.
882
+ """
883
+ if 'sensitivity' in threshold_data:
884
+ return AnomalyDetectionAlarmThreshold(
885
+ sensitivity=threshold_data.get(
886
+ 'sensitivity', AnomalyDetectionAlarmThreshold.DEFAULT_SENSITIVITY
887
+ ),
888
+ justification=threshold_data.get('justification', ''),
889
+ )
890
+
891
+ return StaticAlarmThreshold(
892
+ staticValue=threshold_data.get('staticValue', 0.0),
893
+ justification=threshold_data.get('justification', ''),
894
+ )
895
+
784
896
  def _parse_alarm_recommendation(self, alarm_data: Dict[str, Any]) -> AlarmRecommendation:
785
897
  """Parse alarm recommendation data into AlarmRecommendation object.
786
898
 
@@ -792,12 +904,105 @@ class CloudWatchMetricsTools:
792
904
  """
793
905
  # Parse threshold
794
906
  threshold_data = alarm_data.get('threshold', {})
795
- threshold = AlarmRecommendationThreshold(
796
- staticValue=threshold_data.get('staticValue', 0.0),
797
- justification=threshold_data.get('justification', ''),
907
+ threshold = self._create_alarm_threshold(threshold_data)
908
+
909
+ # Generate CloudFormation template only for anomaly detection alarms
910
+ cfn_template = self.cloudformation_generator.generate_metric_alarm_template(alarm_data)
911
+
912
+ # Build alarm recommendation kwargs
913
+ alarm_kwargs = {
914
+ 'alarmDescription': alarm_data.get('alarmDescription', ''),
915
+ 'metricName': alarm_data.get('metricName', ''),
916
+ 'namespace': alarm_data.get('namespace', ''),
917
+ 'threshold': threshold,
918
+ 'period': alarm_data.get('period', 300),
919
+ 'comparisonOperator': alarm_data.get('comparisonOperator', ''),
920
+ 'statistic': alarm_data.get('statistic', ''),
921
+ 'evaluationPeriods': alarm_data.get('evaluationPeriods', 1),
922
+ 'datapointsToAlarm': alarm_data.get('datapointsToAlarm', 1),
923
+ 'treatMissingData': alarm_data.get('treatMissingData', 'missing'),
924
+ 'dimensions': self._parse_metric_dimensions(alarm_data),
925
+ 'intent': alarm_data.get('intent', ''),
926
+ }
927
+
928
+ # Only include cloudformation_template if it was successfully generated
929
+ if cfn_template:
930
+ alarm_kwargs['cloudformation_template'] = cfn_template
931
+
932
+ return AlarmRecommendation(**alarm_kwargs)
933
+
934
+ def _create_anomaly_detector_data(
935
+ self,
936
+ metric_name: str,
937
+ namespace: str,
938
+ dimensions: List[Dimension],
939
+ seasonality: Seasonality,
940
+ ) -> Dict[str, Any]:
941
+ """Format Anomaly Detector data for use in alarm creation.
942
+
943
+ Args:
944
+ metric_name: The metric name
945
+ namespace: The metric namespace
946
+ dimensions: List of metric dimensions
947
+ seasonality: Detected seasonality
948
+
949
+ Returns:
950
+ Dict[str, Any]: Anomaly detector formatted data
951
+ """
952
+ # Create alarm data structure for _parse_alarm_recommendation
953
+ return {
954
+ 'alarmDescription': f'Anomaly detection alarm for {namespace}/{metric_name} (seasonality {seasonality.name})',
955
+ 'statistic': 'Average',
956
+ 'dimensions': [{'Name': dim.name, 'Value': dim.value} for dim in dimensions],
957
+ 'threshold': {
958
+ 'sensitivity': AnomalyDetectionAlarmThreshold.DEFAULT_SENSITIVITY,
959
+ 'justification': f'Metric has a seasonality of {seasonality.name} making it suitable for Anomaly Detection.',
960
+ },
961
+ 'comparisonOperator': COMPARISON_OPERATOR_ANOMALY,
962
+ 'evaluationPeriods': 2,
963
+ 'datapointsToAlarm': 2,
964
+ 'period': 300,
965
+ 'treatMissingData': 'missing',
966
+ 'intent': f'Detect anomalies in {metric_name} based on {seasonality.name} seasonal length',
967
+ 'metricName': metric_name,
968
+ 'namespace': namespace,
969
+ }
970
+
971
+ def _create_anomaly_detector_recommendation(
972
+ self,
973
+ metric_name: str,
974
+ namespace: str,
975
+ dimensions: List[Dimension],
976
+ seasonality: Seasonality,
977
+ ) -> AlarmRecommendation:
978
+ """Create an anomaly detector recommendation.
979
+
980
+ Args:
981
+ metric_name: The metric name
982
+ namespace: The metric namespace
983
+ dimensions: List of metric dimensions
984
+ seasonality: Detected seasonality
985
+
986
+ Returns:
987
+ AlarmRecommendation: Anomaly detector alarm recommendation
988
+ """
989
+ alarm_data = self._create_anomaly_detector_data(
990
+ metric_name=metric_name,
991
+ namespace=namespace,
992
+ dimensions=dimensions,
993
+ seasonality=seasonality,
798
994
  )
995
+ return self._parse_alarm_recommendation(alarm_data)
996
+
997
+ def _parse_metric_dimensions(self, alarm_data: Dict[str, Any]) -> List[str]:
998
+ """Parse metric dimensions from the alarm data.
799
999
 
800
- # Parse dimensions
1000
+ Args:
1001
+ alarm_data: Raw alarm recommendation data
1002
+
1003
+ Returns:
1004
+ AlarmRecommendation: Parsed alarm recommendation object
1005
+ """
801
1006
  dimensions = []
802
1007
  for dim_data in alarm_data.get('dimensions', []):
803
1008
  alarm_dim = AlarmRecommendationDimension(
@@ -806,16 +1011,145 @@ class CloudWatchMetricsTools:
806
1011
  )
807
1012
  dimensions.append(alarm_dim)
808
1013
 
809
- # Create alarm recommendation
810
- return AlarmRecommendation(
811
- alarmDescription=alarm_data.get('alarmDescription', ''),
812
- threshold=threshold,
813
- period=alarm_data.get('period', 300),
814
- comparisonOperator=alarm_data.get('comparisonOperator', ''),
815
- statistic=alarm_data.get('statistic', ''),
816
- evaluationPeriods=alarm_data.get('evaluationPeriods', 1),
817
- datapointsToAlarm=alarm_data.get('datapointsToAlarm', 1),
818
- treatMissingData=alarm_data.get('treatMissingData', 'missing'),
819
- dimensions=dimensions,
820
- intent=alarm_data.get('intent', ''),
821
- )
1014
+ return dimensions
1015
+
1016
+ def _parse_metric_data_response(
1017
+ self, response: GetMetricDataResponse, period_seconds: int
1018
+ ) -> MetricData:
1019
+ """Parse CloudWatch GetMetricData response into MetricData."""
1020
+ timestamps = []
1021
+ values = []
1022
+
1023
+ if response.metricDataResults and response.metricDataResults[0].datapoints:
1024
+ datapoints = response.metricDataResults[0].datapoints
1025
+ timestamps_ms = [int(dp.timestamp.timestamp() * 1000) for dp in datapoints]
1026
+ raw_values = [dp.value for dp in datapoints]
1027
+
1028
+ sorted_data = sorted(zip(timestamps_ms, raw_values))
1029
+ if sorted_data:
1030
+ timestamps, values = zip(*sorted_data)
1031
+ timestamps = list(timestamps)
1032
+ values = list(values)
1033
+
1034
+ return MetricData(period_seconds=period_seconds, timestamps=timestamps, values=values)
1035
+
1036
+ async def analyze_metric(
1037
+ self,
1038
+ ctx: Context,
1039
+ namespace: str = Field(
1040
+ ..., description="The namespace of the metric (e.g., 'AWS/EC2', 'AWS/Lambda')"
1041
+ ),
1042
+ metric_name: str = Field(
1043
+ ..., description="The name of the metric (e.g., 'CPUUtilization', 'Duration')"
1044
+ ),
1045
+ dimensions: List[Dimension] = Field(
1046
+ default_factory=list,
1047
+ description='List of dimensions that identify the metric, each with name and value',
1048
+ ),
1049
+ region: Annotated[
1050
+ str,
1051
+ Field(description='AWS region to query. Defaults to us-east-1.'),
1052
+ ] = 'us-east-1',
1053
+ statistic: Annotated[
1054
+ Literal[
1055
+ 'AVG',
1056
+ 'COUNT',
1057
+ 'MAX',
1058
+ 'MIN',
1059
+ 'SUM',
1060
+ 'Average',
1061
+ 'Sum',
1062
+ 'Maximum',
1063
+ 'Minimum',
1064
+ 'SampleCount',
1065
+ ],
1066
+ Field(description='The statistic to use for the metric analysis'),
1067
+ ] = 'AVG',
1068
+ ) -> Dict[str, Any]:
1069
+ """Analyzes CloudWatch metric data to determine seasonality, trend, data density and statistical properties.
1070
+
1071
+ This tool provides RAW DATA ONLY about historical metric data and performs analysis including:
1072
+ - Seasonality detection
1073
+ - Trend analysis
1074
+ - Data density and publishing period
1075
+ - Advanced statistical measures (min/max/median, std dev, noise)
1076
+
1077
+ Usage: Use this tool to get objective metric analysis data.
1078
+
1079
+ Args:
1080
+ ctx: The MCP context object for error handling and logging.
1081
+ namespace: The metric namespace (e.g., "AWS/EC2", "AWS/Lambda")
1082
+ metric_name: The name of the metric (e.g., "CPUUtilization", "Duration")
1083
+ dimensions: List of dimensions with name and value pairs
1084
+ statistic: The statistic to use for metric analysis. For guidance on choosing the correct statistic, refer to the get_recommended_metric_alarms tool.
1085
+ region: AWS region to query. Defaults to 'us-east-1'.
1086
+
1087
+ Returns:
1088
+ Dict[str, Any]: Analysis results including:
1089
+ - message: Status message indicating success or reason for empty result
1090
+ - seasonality_seconds: Detected seasonality period in seconds
1091
+ - trend: Trend direction (INCREASING, DECREASING, or NONE)
1092
+ - statistics: Statistical measures (std_deviation, variance, etc.)
1093
+ - data_quality: Data density and publishing period information
1094
+
1095
+ Example:
1096
+ analysis = await analyze_metric(
1097
+ ctx,
1098
+ namespace="AWS/EC2",
1099
+ metric_name="CPUUtilization",
1100
+ dimensions=[
1101
+ Dimension(name="InstanceId", value="i-1234567890abcdef0")
1102
+ ]
1103
+ )
1104
+ print(f"Status: {analysis['message']}")
1105
+ print(f"Seasonality: {analysis['seasonality_seconds']} seconds")
1106
+ print(f"Trend: {analysis['trend']}")
1107
+ """
1108
+ try:
1109
+ analysis_period_minutes = DEFAULT_ANALYSIS_PERIOD_MINUTES
1110
+
1111
+ logger.info(f'Analyzing metric: {namespace}/{metric_name} in region {region}')
1112
+
1113
+ end_time = datetime.now(timezone.utc)
1114
+ start_time = end_time - timedelta(minutes=analysis_period_minutes)
1115
+
1116
+ metric_data_response = await self.get_metric_data(
1117
+ ctx=ctx,
1118
+ namespace=namespace,
1119
+ metric_name=metric_name,
1120
+ dimensions=dimensions,
1121
+ start_time=start_time.isoformat(),
1122
+ end_time=end_time.isoformat(),
1123
+ statistic=statistic,
1124
+ region=region,
1125
+ target_datapoints=analysis_period_minutes,
1126
+ )
1127
+
1128
+ # Parse response into structured data
1129
+ _, _, period_seconds = self._prepare_time_parameters(
1130
+ start_time, end_time, analysis_period_minutes
1131
+ )
1132
+ metric_data = self._parse_metric_data_response(metric_data_response, period_seconds)
1133
+ analysis_result = self.metric_analyzer.analyze_metric_data(metric_data)
1134
+
1135
+ analysis_result.update(
1136
+ {
1137
+ 'metric_info': {
1138
+ 'namespace': namespace,
1139
+ 'metric_name': metric_name,
1140
+ 'statistic': statistic,
1141
+ 'dimensions': [{'name': d.name, 'value': d.value} for d in dimensions],
1142
+ 'analysis_period_minutes': analysis_period_minutes,
1143
+ 'time_range': {
1144
+ 'start': start_time.isoformat(),
1145
+ 'end': end_time.isoformat(),
1146
+ },
1147
+ },
1148
+ }
1149
+ )
1150
+
1151
+ return analysis_result
1152
+ except Exception as e:
1153
+ logger.error(f'Error in analyze_metric: {str(e)}')
1154
+ await ctx.error(f'Error encountered when analyzing metric: {str(e)}')
1155
+ raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awslabs.cloudwatch-mcp-server
3
- Version: 0.0.10
3
+ Version: 0.0.13
4
4
  Summary: An AWS Labs Model Context Protocol (MCP) server for cloudwatch
5
5
  Project-URL: homepage, https://awslabs.github.io/mcp/
6
6
  Project-URL: docs, https://awslabs.github.io/mcp/servers/cloudwatch-mcp-server/
@@ -24,7 +24,10 @@ Requires-Python: >=3.10
24
24
  Requires-Dist: boto3>=1.38.22
25
25
  Requires-Dist: loguru>=0.7.0
26
26
  Requires-Dist: mcp[cli]>=1.11.0
27
+ Requires-Dist: numpy>=2.0.0
28
+ Requires-Dist: pandas>=2.2.3
27
29
  Requires-Dist: pydantic>=2.10.6
30
+ Requires-Dist: statsmodels>=0.14.0
28
31
  Description-Content-Type: text/markdown
29
32
 
30
33
  # AWS Labs cloudwatch MCP Server
@@ -57,7 +60,8 @@ Alarm Recommendations - Suggests recommended alarm configurations for CloudWatch
57
60
  ### Tools for CloudWatch Metrics
58
61
  * `get_metric_data` - Retrieves detailed CloudWatch metric data for any CloudWatch metric. Use this for general CloudWatch metrics that aren't specific to Application Signals. Provides ability to query any metric namespace, dimension, and statistic
59
62
  * `get_metric_metadata` - Retrieves comprehensive metadata about a specific CloudWatch metric
60
- * `get_recommended_metric_alarms` - Gets recommended alarms for a CloudWatch metric
63
+ * `get_recommended_metric_alarms` - Gets recommended alarms for a CloudWatch metric based on best practice, and trend, seasonality and statistical analysis.
64
+ * `analyze_metric` - Analyzes CloudWatch metric data to determine trend, seasonality, and statistical properties
61
65
 
62
66
  ### Tools for CloudWatch Alarms
63
67
  * `get_active_alarms` - Identifies currently active CloudWatch alarms across the account
@@ -0,0 +1,21 @@
1
+ awslabs/__init__.py,sha256=WuqxdDgUZylWNmVoPKiK7qGsTB_G4UmuXIrJ-VBwDew,731
2
+ awslabs/cloudwatch_mcp_server/__init__.py,sha256=vqzwA3x7riO_70o_CNV6Xmbi_D1krbM0JVMe4v59lI0,683
3
+ awslabs/cloudwatch_mcp_server/common.py,sha256=dbnaQlIOh4VmJvflzoJXv4JkrK7brPa1hgnrfLapJDs,2190
4
+ awslabs/cloudwatch_mcp_server/server.py,sha256=raMeiC0F8M7cIH6-5rZnU2_DZZkPEtpvRm-5_hd9tbs,2505
5
+ awslabs/cloudwatch_mcp_server/cloudwatch_alarms/models.py,sha256=wgwSE4JqLa0K7-3xhxGjDvGetXi-TZkmjbWtXRvx7CA,7202
6
+ awslabs/cloudwatch_mcp_server/cloudwatch_alarms/tools.py,sha256=ftllhM1ORWpA65FGG_oPH7h9UiGwakFCJ03lqUzrVSg,30865
7
+ awslabs/cloudwatch_mcp_server/cloudwatch_logs/models.py,sha256=wyfxHNN5E2K49LreqKBMAZ4Vyvc2MMkxMCfyGHsK-pQ,7982
8
+ awslabs/cloudwatch_mcp_server/cloudwatch_logs/tools.py,sha256=b0tobrfTkyEzKkqof0wNR649PWfOIA0euGSwT4qvevM,30018
9
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/cloudformation_template_generator.py,sha256=eHnIpd5DBrVjXpmjy1n7ZxfKZA-9JkwuxogcBUg4E4I,6944
10
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/constants.py,sha256=v1IETRSHtckgVqjm6WgzWEi0fqYqwMrIL3M3V9k1K5A,981
11
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/metric_analyzer.py,sha256=t0cmrxbIPbw7gjWQXydYWxuhKnRbH_bbyzqkm7itFag,7601
12
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/metric_data_decomposer.py,sha256=SzB7CyyXvSIk7Qfd-5OyHAThFPjk5N3ZDbx37kjVsSs,8361
13
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/models.py,sha256=38ppi8euC-PurLypCAbBxyrIgeqja-5pOImQLPukDDo,10175
14
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/tools.py,sha256=v5orz1PICegO6A059CMyQd0Q3nwYNRtKcJHmD51Hh08,47807
15
+ awslabs/cloudwatch_mcp_server/cloudwatch_metrics/data/metric_metadata.json,sha256=FlSUlfYVo1VdANrsBg50atggMNGSqZvhhZU7ca-v48c,745055
16
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/METADATA,sha256=Z2TXYNOvczxpmqNSg09jwSsFIjTTCQCkI2nJp8rNRJM,10393
17
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/entry_points.txt,sha256=u8YZn3_qq9Ai7nRux17K6K7RDssOBhTSyUNyZKrQUIk,92
19
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
20
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/licenses/NOTICE,sha256=xpvRUSHqG7LIpUZ1W_0D4sfPJG8lj51X6Mxjq1KJ6eQ,97
21
+ awslabs_cloudwatch_mcp_server-0.0.13.dist-info/RECORD,,
@@ -1,17 +0,0 @@
1
- awslabs/__init__.py,sha256=WuqxdDgUZylWNmVoPKiK7qGsTB_G4UmuXIrJ-VBwDew,731
2
- awslabs/cloudwatch_mcp_server/__init__.py,sha256=T6q1y13qcCJuD_fMN_CVKPf--GyUP6RcKNdS68ZYLpY,682
3
- awslabs/cloudwatch_mcp_server/common.py,sha256=dbnaQlIOh4VmJvflzoJXv4JkrK7brPa1hgnrfLapJDs,2190
4
- awslabs/cloudwatch_mcp_server/server.py,sha256=raMeiC0F8M7cIH6-5rZnU2_DZZkPEtpvRm-5_hd9tbs,2505
5
- awslabs/cloudwatch_mcp_server/cloudwatch_alarms/models.py,sha256=vqctogiT-EjzA_VczWUYeskaF_aAOBQJR_s5KI7NkuI,7202
6
- awslabs/cloudwatch_mcp_server/cloudwatch_alarms/tools.py,sha256=PGEm8alzSAbrz-X-JaWARGPHKU1IBXDTmNP8R7PZPfc,30865
7
- awslabs/cloudwatch_mcp_server/cloudwatch_logs/models.py,sha256=wyfxHNN5E2K49LreqKBMAZ4Vyvc2MMkxMCfyGHsK-pQ,7982
8
- awslabs/cloudwatch_mcp_server/cloudwatch_logs/tools.py,sha256=ohaVlRsmXlg8yJOL1D-KEXPPuXfJ9mVSdj8YKc-xeBw,28163
9
- awslabs/cloudwatch_mcp_server/cloudwatch_metrics/models.py,sha256=ov6aJUUrN2fz9Gom-tE4DT5h6M0PCkKwA9pEBnVv6SE,5756
10
- awslabs/cloudwatch_mcp_server/cloudwatch_metrics/tools.py,sha256=GoW0gLy35gW7MspbxtfNBghUgR8xWIa4tgcohqYE1h8,33410
11
- awslabs/cloudwatch_mcp_server/cloudwatch_metrics/data/metric_metadata.json,sha256=FlSUlfYVo1VdANrsBg50atggMNGSqZvhhZU7ca-v48c,745055
12
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/METADATA,sha256=kXSMICub-jPW9BkggBDo26IfkThHdvVK3thonk5eaSM,10115
13
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
14
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/entry_points.txt,sha256=u8YZn3_qq9Ai7nRux17K6K7RDssOBhTSyUNyZKrQUIk,92
15
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
16
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/licenses/NOTICE,sha256=xpvRUSHqG7LIpUZ1W_0D4sfPJG8lj51X6Mxjq1KJ6eQ,97
17
- awslabs_cloudwatch_mcp_server-0.0.10.dist-info/RECORD,,