awslabs.eks-mcp-server 0.1.1__py3-none-any.whl → 0.1.3__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.
- awslabs/__init__.py +9 -6
- awslabs/eks_mcp_server/__init__.py +9 -6
- awslabs/eks_mcp_server/aws_helper.py +12 -8
- awslabs/eks_mcp_server/cloudwatch_handler.py +75 -77
- awslabs/eks_mcp_server/cloudwatch_metrics_guidance_handler.py +141 -0
- awslabs/eks_mcp_server/consts.py +9 -6
- awslabs/eks_mcp_server/data/eks_cloudwatch_metrics_guidance.json +287 -0
- awslabs/eks_mcp_server/eks_kb_handler.py +9 -6
- awslabs/eks_mcp_server/eks_stack_handler.py +38 -8
- awslabs/eks_mcp_server/iam_handler.py +14 -6
- awslabs/eks_mcp_server/k8s_apis.py +25 -14
- awslabs/eks_mcp_server/k8s_client_cache.py +9 -6
- awslabs/eks_mcp_server/k8s_handler.py +55 -6
- awslabs/eks_mcp_server/logging_helper.py +9 -6
- awslabs/eks_mcp_server/models.py +24 -10
- awslabs/eks_mcp_server/scripts/update_eks_cloudwatch_metrics_guidance.py +280 -0
- awslabs/eks_mcp_server/server.py +16 -7
- {awslabs_eks_mcp_server-0.1.1.dist-info → awslabs_eks_mcp_server-0.1.3.dist-info}/METADATA +170 -34
- awslabs_eks_mcp_server-0.1.3.dist-info/RECORD +26 -0
- awslabs_eks_mcp_server-0.1.1.dist-info/RECORD +0 -23
- {awslabs_eks_mcp_server-0.1.1.dist-info → awslabs_eks_mcp_server-0.1.3.dist-info}/WHEEL +0 -0
- {awslabs_eks_mcp_server-0.1.1.dist-info → awslabs_eks_mcp_server-0.1.3.dist-info}/entry_points.txt +0 -0
- {awslabs_eks_mcp_server-0.1.1.dist-info → awslabs_eks_mcp_server-0.1.3.dist-info}/licenses/LICENSE +0 -0
- {awslabs_eks_mcp_server-0.1.1.dist-info → awslabs_eks_mcp_server-0.1.3.dist-info}/licenses/NOTICE +0 -0
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cluster": {
|
|
3
|
+
"metrics": [
|
|
4
|
+
{
|
|
5
|
+
"description": "The number of failed worker nodes in the cluster. A node is considered failed if it is suffering from any node conditions. For more information, see Conditions in the Kubernetes documentation.",
|
|
6
|
+
"dimensions": [
|
|
7
|
+
"ClusterName"
|
|
8
|
+
],
|
|
9
|
+
"name": "cluster_failed_node_count"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"description": "The total number of worker nodes in the cluster.",
|
|
13
|
+
"dimensions": [
|
|
14
|
+
"ClusterName"
|
|
15
|
+
],
|
|
16
|
+
"name": "cluster_node_count"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"namespace": {
|
|
21
|
+
"metrics": [
|
|
22
|
+
{
|
|
23
|
+
"description": "The number of pods running per namespace in the resource that is specified by the dimensions that you're using.",
|
|
24
|
+
"dimensions": [
|
|
25
|
+
"Namespace,ClusterName",
|
|
26
|
+
"ClusterName"
|
|
27
|
+
],
|
|
28
|
+
"name": "namespace_number_of_running_pods"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"node": {
|
|
33
|
+
"metrics": [
|
|
34
|
+
{
|
|
35
|
+
"description": "The maximum number of CPU units that can be assigned to a single node in this cluster.",
|
|
36
|
+
"dimensions": [
|
|
37
|
+
"ClusterName"
|
|
38
|
+
],
|
|
39
|
+
"name": "node_cpu_limit"
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"description": "The percentage of CPU units that are reserved for node components, such as kubelet, kube-proxy, and Docker.",
|
|
43
|
+
"dimensions": [
|
|
44
|
+
"NodeName,ClusterName,InstanceId",
|
|
45
|
+
"ClusterName"
|
|
46
|
+
],
|
|
47
|
+
"name": "node_cpu_reserved_capacity"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"description": "The number of CPU units being used on the nodes in the cluster.",
|
|
51
|
+
"dimensions": [
|
|
52
|
+
"ClusterName"
|
|
53
|
+
],
|
|
54
|
+
"name": "node_cpu_usage_total"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"description": "The total percentage of CPU units being used on the nodes in the cluster.",
|
|
58
|
+
"dimensions": [
|
|
59
|
+
"NodeName,ClusterName,InstanceId",
|
|
60
|
+
"ClusterName"
|
|
61
|
+
],
|
|
62
|
+
"name": "node_cpu_utilization"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"description": "The total number of GPU(s) available on the node.",
|
|
66
|
+
"dimensions": [
|
|
67
|
+
"ClusterName",
|
|
68
|
+
"ClusterName,InstanceId,NodeName"
|
|
69
|
+
],
|
|
70
|
+
"name": "node_gpu_limit"
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"description": "The number of GPU(s) being used by the running pods on the node.",
|
|
74
|
+
"dimensions": [
|
|
75
|
+
"ClusterName",
|
|
76
|
+
"ClusterName,InstanceId,NodeName"
|
|
77
|
+
],
|
|
78
|
+
"name": "node_gpu_usage_total"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"description": "The percentage of GPU currently being reserved on the node. The formula is, node_gpu_request / node_gpu_limit.",
|
|
82
|
+
"dimensions": [
|
|
83
|
+
"ClusterName",
|
|
84
|
+
"ClusterName,InstanceId,NodeName"
|
|
85
|
+
],
|
|
86
|
+
"name": "node_gpu_reserved_capacity"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"description": "The total percentage of file system capacity being used on nodes in the cluster.",
|
|
90
|
+
"dimensions": [
|
|
91
|
+
"NodeName,ClusterName,InstanceId",
|
|
92
|
+
"ClusterName"
|
|
93
|
+
],
|
|
94
|
+
"name": "node_filesystem_utilization"
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
"description": "The maximum amount of memory, in bytes, that can be assigned to a single node in this cluster.",
|
|
98
|
+
"dimensions": [
|
|
99
|
+
"ClusterName"
|
|
100
|
+
],
|
|
101
|
+
"name": "node_memory_limit"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"description": "The percentage of memory currently being used on the nodes in the cluster.",
|
|
105
|
+
"dimensions": [
|
|
106
|
+
"NodeName,ClusterName,InstanceId",
|
|
107
|
+
"ClusterName"
|
|
108
|
+
],
|
|
109
|
+
"name": "node_memory_reserved_capacity"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"description": "The percentage of memory currently being used by the node or nodes. It is the percentage of node memory usage divided by the node memory limitation.",
|
|
113
|
+
"dimensions": [
|
|
114
|
+
"NodeName,ClusterName,InstanceId",
|
|
115
|
+
"ClusterName"
|
|
116
|
+
],
|
|
117
|
+
"name": "node_memory_utilization"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"description": "The amount of memory, in bytes, being used in the working set of the nodes in the cluster.",
|
|
121
|
+
"dimensions": [
|
|
122
|
+
"ClusterName"
|
|
123
|
+
],
|
|
124
|
+
"name": "node_memory_working_set"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"description": "The total number of bytes per second transmitted and received over the network per node in a cluster.",
|
|
128
|
+
"dimensions": [
|
|
129
|
+
"NodeName,ClusterName,InstanceId",
|
|
130
|
+
"ClusterName"
|
|
131
|
+
],
|
|
132
|
+
"name": "node_network_total_bytes"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"description": "The number of running containers per node in a cluster.",
|
|
136
|
+
"dimensions": [
|
|
137
|
+
"NodeName,ClusterName,InstanceId",
|
|
138
|
+
"ClusterName"
|
|
139
|
+
],
|
|
140
|
+
"name": "node_number_of_running_containers"
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
"description": "The number of running pods per node in a cluster.",
|
|
144
|
+
"dimensions": [
|
|
145
|
+
"NodeName,ClusterName,InstanceId",
|
|
146
|
+
"ClusterName"
|
|
147
|
+
],
|
|
148
|
+
"name": "node_number_of_running_pods"
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
"pod": {
|
|
153
|
+
"metrics": [
|
|
154
|
+
{
|
|
155
|
+
"description": "The CPU capacity that is reserved per pod in a cluster.",
|
|
156
|
+
"dimensions": [
|
|
157
|
+
"PodName,Namespace,ClusterName",
|
|
158
|
+
"ClusterName"
|
|
159
|
+
],
|
|
160
|
+
"name": "pod_cpu_reserved_capacity"
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
"description": "The percentage of CPU units being used by pods.",
|
|
164
|
+
"dimensions": [
|
|
165
|
+
"PodName,Namespace,ClusterName",
|
|
166
|
+
"Namespace,ClusterName",
|
|
167
|
+
"Service,Namespace,ClusterName",
|
|
168
|
+
"ClusterName"
|
|
169
|
+
],
|
|
170
|
+
"name": "pod_cpu_utilization"
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
"description": "The percentage of CPU units being used by pods relative to the pod limit.",
|
|
174
|
+
"dimensions": [
|
|
175
|
+
"PodName,Namespace,ClusterName",
|
|
176
|
+
"Namespace,ClusterName",
|
|
177
|
+
"Service,Namespace,ClusterName",
|
|
178
|
+
"ClusterName"
|
|
179
|
+
],
|
|
180
|
+
"name": "pod_cpu_utilization_over_pod_limit"
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"description": "The GPU requests for the pod. This value must always be equal to pod_gpu_limit.",
|
|
184
|
+
"dimensions": [
|
|
185
|
+
"ClusterName",
|
|
186
|
+
"ClusterName,Namespace,PodName",
|
|
187
|
+
"ClusterName,FullPodName,Namespace,PodName"
|
|
188
|
+
],
|
|
189
|
+
"name": "pod_gpu_request"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"description": "The maximum number of GPU(s) that can be assigned to the pod in a node.",
|
|
193
|
+
"dimensions": [
|
|
194
|
+
"ClusterName",
|
|
195
|
+
"ClusterName,Namespace,PodName",
|
|
196
|
+
"ClusterName,FullPodName,Namespace,PodName"
|
|
197
|
+
],
|
|
198
|
+
"name": "pod_gpu_limit"
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"description": "The number of GPU(s) being allocated on the pod.",
|
|
202
|
+
"dimensions": [
|
|
203
|
+
"ClusterName",
|
|
204
|
+
"ClusterName,Namespace,PodName",
|
|
205
|
+
"ClusterName,FullPodName,Namespace,PodName"
|
|
206
|
+
],
|
|
207
|
+
"name": "pod_gpu_usage_total"
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"description": "The percentage of GPU currently being reserved for the pod. The formula is - pod_gpu_request / node_gpu_reserved_capacity.",
|
|
211
|
+
"dimensions": [
|
|
212
|
+
"ClusterName",
|
|
213
|
+
"ClusterName,Namespace,PodName",
|
|
214
|
+
"ClusterName,FullPodName,Namespace,PodName"
|
|
215
|
+
],
|
|
216
|
+
"name": "pod_gpu_reserved_capacity"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"description": "The percentage of memory that is reserved for pods.",
|
|
220
|
+
"dimensions": [
|
|
221
|
+
"PodName,Namespace,ClusterName",
|
|
222
|
+
"ClusterName"
|
|
223
|
+
],
|
|
224
|
+
"name": "pod_memory_reserved_capacity"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
"description": "The percentage of memory currently being used by the pod or pods.",
|
|
228
|
+
"dimensions": [
|
|
229
|
+
"PodName,Namespace,ClusterName",
|
|
230
|
+
"Namespace,ClusterName",
|
|
231
|
+
"Service,Namespace,ClusterName",
|
|
232
|
+
"ClusterName"
|
|
233
|
+
],
|
|
234
|
+
"name": "pod_memory_utilization"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"description": "The percentage of memory that is being used by pods relative to the pod limit. If any containers in the pod don't have a memory limit defined, this metric doesn't appear.",
|
|
238
|
+
"dimensions": [
|
|
239
|
+
"PodName,Namespace,ClusterName",
|
|
240
|
+
"Namespace,ClusterName",
|
|
241
|
+
"Service,Namespace,ClusterName",
|
|
242
|
+
"ClusterName"
|
|
243
|
+
],
|
|
244
|
+
"name": "pod_memory_utilization_over_pod_limit"
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
"description": "The number of bytes per second being received over the network by the pod.",
|
|
248
|
+
"dimensions": [
|
|
249
|
+
"PodName,Namespace,ClusterName",
|
|
250
|
+
"Namespace,ClusterName",
|
|
251
|
+
"Service,Namespace,ClusterName",
|
|
252
|
+
"ClusterName"
|
|
253
|
+
],
|
|
254
|
+
"name": "pod_network_rx_bytes"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"description": "The number of bytes per second being transmitted over the network by the pod.",
|
|
258
|
+
"dimensions": [
|
|
259
|
+
"PodName,Namespace,ClusterName",
|
|
260
|
+
"Namespace,ClusterName",
|
|
261
|
+
"Service,Namespace,ClusterName",
|
|
262
|
+
"ClusterName"
|
|
263
|
+
],
|
|
264
|
+
"name": "pod_network_tx_bytes"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"description": "The total number of container restarts in a pod.",
|
|
268
|
+
"dimensions": [
|
|
269
|
+
"PodName,Namespace,ClusterName"
|
|
270
|
+
],
|
|
271
|
+
"name": "pod_number_of_container_restarts"
|
|
272
|
+
}
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
"service": {
|
|
276
|
+
"metrics": [
|
|
277
|
+
{
|
|
278
|
+
"description": "The number of pods running the service or services in the cluster.",
|
|
279
|
+
"dimensions": [
|
|
280
|
+
"Service,Namespace,ClusterName",
|
|
281
|
+
"ClusterName"
|
|
282
|
+
],
|
|
283
|
+
"name": "service_number_of_running_pods"
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""Knowledge Base Retrival handler for the EKS MCP Server."""
|
|
13
16
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""EKS stack handler for the EKS MCP Server."""
|
|
13
16
|
|
|
@@ -36,7 +39,7 @@ from awslabs.eks_mcp_server.models import (
|
|
|
36
39
|
from mcp.server.fastmcp import Context
|
|
37
40
|
from mcp.types import EmbeddedResource, ImageContent, TextContent
|
|
38
41
|
from pydantic import Field
|
|
39
|
-
from typing import Dict, List, Optional, Tuple, Union, cast
|
|
42
|
+
from typing import Any, Dict, List, Optional, Tuple, Union, cast
|
|
40
43
|
|
|
41
44
|
|
|
42
45
|
class EksStackHandler:
|
|
@@ -135,6 +138,13 @@ class EksStackHandler:
|
|
|
135
138
|
mechanism for creating and managing EKS clusters through CloudFormation, enabling standardized
|
|
136
139
|
cluster creation, configuration updates, and resource cleanup.
|
|
137
140
|
|
|
141
|
+
IMPORTANT: Use this tool instead of 'aws eks create-cluster', 'aws eks delete-cluster',
|
|
142
|
+
'eksctl create cluster', 'eksctl delete cluster', or similar CLI commands.
|
|
143
|
+
|
|
144
|
+
IMPORTANT: Use this tool's standardized templates for creating EKS clusters with proper VPC configuration,
|
|
145
|
+
networking, security groups, and EKS auto mode. DO NOT create EKS clusters by generating CloudFormation
|
|
146
|
+
templates from scratch.
|
|
147
|
+
|
|
138
148
|
## Requirements
|
|
139
149
|
- The server must be run with the `--allow-write` flag for generate, deploy, and delete operations
|
|
140
150
|
- For deploy and delete operations, the stack must have been created by this tool
|
|
@@ -319,7 +329,7 @@ class EksStackHandler:
|
|
|
319
329
|
- Security groups for cluster communication
|
|
320
330
|
- IAM roles for the EKS cluster and worker nodes
|
|
321
331
|
- An EKS cluster in Auto Mode with:
|
|
322
|
-
- Compute configuration
|
|
332
|
+
- Compute configuration for automatic node management
|
|
323
333
|
- Kubernetes network configuration with elastic load balancing
|
|
324
334
|
- Block storage configuration
|
|
325
335
|
- API authentication mode
|
|
@@ -345,6 +355,10 @@ class EksStackHandler:
|
|
|
345
355
|
if 'Parameters' in template_yaml and 'ClusterName' in template_yaml['Parameters']:
|
|
346
356
|
template_yaml['Parameters']['ClusterName']['Default'] = cluster_name
|
|
347
357
|
|
|
358
|
+
# Remove checkov metadata from the EKS cluster resource
|
|
359
|
+
if 'Resources' in template_yaml and 'EksCluster' in template_yaml['Resources']:
|
|
360
|
+
self._remove_checkov_metadata(template_yaml['Resources']['EksCluster'])
|
|
361
|
+
|
|
348
362
|
# Convert back to YAML
|
|
349
363
|
modified_template = yaml.dump(template_yaml, default_flow_style=False)
|
|
350
364
|
|
|
@@ -589,6 +603,22 @@ class EksStackHandler:
|
|
|
589
603
|
outputs={},
|
|
590
604
|
)
|
|
591
605
|
|
|
606
|
+
def _remove_checkov_metadata(self, resource: Dict[str, Any]) -> None:
|
|
607
|
+
"""Remove checkov metadata from a resource and clean up empty Metadata sections.
|
|
608
|
+
|
|
609
|
+
Args:
|
|
610
|
+
resource: The resource dictionary to process
|
|
611
|
+
"""
|
|
612
|
+
if 'Metadata' in resource:
|
|
613
|
+
# Check if there's checkov metadata
|
|
614
|
+
if 'checkov' in resource['Metadata']:
|
|
615
|
+
# Remove only the checkov metadata
|
|
616
|
+
del resource['Metadata']['checkov']
|
|
617
|
+
|
|
618
|
+
# If Metadata is now empty, remove it entirely
|
|
619
|
+
if not resource['Metadata']:
|
|
620
|
+
del resource['Metadata']
|
|
621
|
+
|
|
592
622
|
async def _delete_stack(
|
|
593
623
|
self, ctx: Context, stack_name: str, cluster_name: str
|
|
594
624
|
) -> DeleteStackResponse:
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""IAM handler for the EKS MCP Server."""
|
|
13
16
|
|
|
@@ -63,6 +66,9 @@ class IAMHandler:
|
|
|
63
66
|
permissions, identify missing or excessive permissions, troubleshoot EKS cluster issues,
|
|
64
67
|
and verify trust relationships for service roles.
|
|
65
68
|
|
|
69
|
+
IMPORTANT: Use this tool instead of 'aws iam get-role', 'aws iam list-attached-role-policies',
|
|
70
|
+
'aws iam list-role-policies', and 'aws iam get-role-policy' commands.
|
|
71
|
+
|
|
66
72
|
## Requirements
|
|
67
73
|
- The role must exist in your AWS account
|
|
68
74
|
- Valid AWS credentials with permissions to read IAM role information
|
|
@@ -156,6 +162,8 @@ class IAMHandler:
|
|
|
156
162
|
for granting EKS clusters access to AWS services, enabling worker nodes to access resources, and
|
|
157
163
|
configuring permissions for CloudWatch logging and ECR access.
|
|
158
164
|
|
|
165
|
+
IMPORTANT: Use this tool instead of 'aws iam put-role-policy' commands.
|
|
166
|
+
|
|
159
167
|
## Requirements
|
|
160
168
|
- The server must be run with the `--allow-write` flag
|
|
161
169
|
- The role must exist in your AWS account
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""Kubernetes API client for the EKS MCP Server."""
|
|
13
16
|
|
|
14
17
|
import base64
|
|
15
18
|
import os
|
|
16
19
|
import tempfile
|
|
20
|
+
from awslabs.eks_mcp_server import __version__
|
|
17
21
|
from awslabs.eks_mcp_server.models import Operation
|
|
18
22
|
from loguru import logger
|
|
19
23
|
from typing import Any, Dict, List, Optional
|
|
@@ -72,6 +76,9 @@ class K8sApis:
|
|
|
72
76
|
# Create base API client
|
|
73
77
|
self.api_client = client.ApiClient(configuration)
|
|
74
78
|
|
|
79
|
+
# Set user-agent directly on the ApiClient
|
|
80
|
+
self.api_client.user_agent = f'awslabs/mcp/eks-mcp-server/{__version__}'
|
|
81
|
+
|
|
75
82
|
# Create dynamic client
|
|
76
83
|
self.dynamic_client = dynamic.DynamicClient(self.api_client)
|
|
77
84
|
|
|
@@ -407,22 +414,26 @@ class K8sApis:
|
|
|
407
414
|
Pod logs as a string
|
|
408
415
|
"""
|
|
409
416
|
try:
|
|
410
|
-
|
|
411
|
-
pod_resource = self.dynamic_client.resources.get(api_version='v1', kind='Pod')
|
|
417
|
+
from kubernetes import client
|
|
412
418
|
|
|
413
|
-
#
|
|
419
|
+
# Create CoreV1Api client
|
|
420
|
+
core_v1_api = client.CoreV1Api(self.api_client)
|
|
421
|
+
|
|
422
|
+
# Prepare parameters for the read_namespaced_pod_log method
|
|
414
423
|
params = {}
|
|
415
424
|
if container_name:
|
|
416
425
|
params['container'] = container_name
|
|
417
426
|
if since_seconds:
|
|
418
|
-
params['
|
|
427
|
+
params['since_seconds'] = since_seconds
|
|
419
428
|
if tail_lines:
|
|
420
|
-
params['
|
|
429
|
+
params['tail_lines'] = tail_lines
|
|
421
430
|
if limit_bytes:
|
|
422
|
-
params['
|
|
431
|
+
params['limit_bytes'] = limit_bytes
|
|
423
432
|
|
|
424
|
-
# Call the
|
|
425
|
-
logs_response =
|
|
433
|
+
# Call the read_namespaced_pod_log method
|
|
434
|
+
logs_response = core_v1_api.read_namespaced_pod_log(
|
|
435
|
+
name=pod_name, namespace=namespace, **params
|
|
436
|
+
)
|
|
426
437
|
|
|
427
438
|
return logs_response
|
|
428
439
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""Kubernetes client cache for the EKS MCP Server."""
|
|
13
16
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
2
2
|
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License")
|
|
4
|
-
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
5
6
|
#
|
|
6
|
-
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
11
14
|
|
|
12
15
|
"""Kubernetes handler for the EKS MCP Server."""
|
|
13
16
|
|
|
@@ -111,6 +114,8 @@ class K8sHandler:
|
|
|
111
114
|
and can create or update resources, useful for deploying applications, creating
|
|
112
115
|
Kubernetes resources, and applying complete application stacks.
|
|
113
116
|
|
|
117
|
+
IMPORTANT: Use this tool instead of 'kubectl apply -f' commands.
|
|
118
|
+
|
|
114
119
|
## Requirements
|
|
115
120
|
- The server must be run with the `--allow-write` flag
|
|
116
121
|
- The YAML file must exist and be accessible to the server
|
|
@@ -334,6 +339,9 @@ class K8sHandler:
|
|
|
334
339
|
custom resources, update specific fields, read detailed information, and delete
|
|
335
340
|
resources that are no longer needed.
|
|
336
341
|
|
|
342
|
+
IMPORTANT: Use this tool instead of 'kubectl create', 'kubectl edit', 'kubectl patch',
|
|
343
|
+
'kubectl delete', or 'kubectl get' commands.
|
|
344
|
+
|
|
337
345
|
## Requirements
|
|
338
346
|
- The server must be run with the `--allow-write` flag for mutating operations
|
|
339
347
|
- The server must be run with the `--allow-sensitive-data-access` flag for Secret resources
|
|
@@ -534,6 +542,8 @@ class K8sHandler:
|
|
|
534
542
|
for listing pods in a namespace, finding services with specific labels, or
|
|
535
543
|
checking resources in a specific state.
|
|
536
544
|
|
|
545
|
+
IMPORTANT: Use this tool instead of 'kubectl get' commands.
|
|
546
|
+
|
|
537
547
|
## Response Information
|
|
538
548
|
The response includes a summary of each resource with name, namespace, creation timestamp,
|
|
539
549
|
labels, and annotations.
|
|
@@ -780,6 +790,37 @@ class K8sHandler:
|
|
|
780
790
|
output_file_path='',
|
|
781
791
|
)
|
|
782
792
|
|
|
793
|
+
def _remove_checkov_skip_annotations(self, content: str) -> str:
|
|
794
|
+
"""Remove checkov skip annotations from YAML content.
|
|
795
|
+
|
|
796
|
+
Args:
|
|
797
|
+
content: YAML content as string
|
|
798
|
+
|
|
799
|
+
Returns:
|
|
800
|
+
YAML content with checkov skip annotations removed
|
|
801
|
+
"""
|
|
802
|
+
# Use yaml to parse and modify the content
|
|
803
|
+
yaml_content = yaml.safe_load(content)
|
|
804
|
+
if (
|
|
805
|
+
yaml_content
|
|
806
|
+
and 'metadata' in yaml_content
|
|
807
|
+
and 'annotations' in yaml_content['metadata']
|
|
808
|
+
):
|
|
809
|
+
# Remove all checkov skip annotations
|
|
810
|
+
annotations = yaml_content['metadata']['annotations']
|
|
811
|
+
checkov_keys = [key for key in annotations.keys() if key.startswith('checkov.io/skip')]
|
|
812
|
+
for key in checkov_keys:
|
|
813
|
+
del annotations[key]
|
|
814
|
+
|
|
815
|
+
# If annotations is now empty, remove it
|
|
816
|
+
if not annotations:
|
|
817
|
+
del yaml_content['metadata']['annotations']
|
|
818
|
+
|
|
819
|
+
# Convert back to YAML string
|
|
820
|
+
content = yaml.dump(yaml_content, default_flow_style=False)
|
|
821
|
+
|
|
822
|
+
return content
|
|
823
|
+
|
|
783
824
|
def _load_yaml_template(self, template_files: list, values: Dict[str, Any]) -> str:
|
|
784
825
|
"""Load and process Kubernetes template files.
|
|
785
826
|
|
|
@@ -804,6 +845,10 @@ class K8sHandler:
|
|
|
804
845
|
for key, value in values.items():
|
|
805
846
|
content = content.replace(key, value)
|
|
806
847
|
|
|
848
|
+
# Remove checkov skip annotations if present
|
|
849
|
+
if template_file == 'deployment.yaml':
|
|
850
|
+
content = self._remove_checkov_skip_annotations(content)
|
|
851
|
+
|
|
807
852
|
template_contents.append(content)
|
|
808
853
|
|
|
809
854
|
# Combine templates into a single YAML document with separator
|
|
@@ -840,6 +885,8 @@ class K8sHandler:
|
|
|
840
885
|
to filter by container, time range, and size. It's useful for debugging application
|
|
841
886
|
issues, monitoring behavior, investigating crashes, and verifying startup configuration.
|
|
842
887
|
|
|
888
|
+
IMPORTANT: Use this tool instead of 'kubectl logs' commands.
|
|
889
|
+
|
|
843
890
|
## Requirements
|
|
844
891
|
- The server must be run with the `--allow-sensitive-data-access` flag
|
|
845
892
|
- The pod must exist and be accessible in the specified namespace
|
|
@@ -965,6 +1012,8 @@ class K8sHandler:
|
|
|
965
1012
|
are useful for troubleshooting pod startup failures, investigating deployment issues,
|
|
966
1013
|
understanding resource modifications, and diagnosing scheduling problems.
|
|
967
1014
|
|
|
1015
|
+
IMPORTANT: Use this tool instead of 'kubectl describe' or 'kubectl get events' commands.
|
|
1016
|
+
|
|
968
1017
|
## Requirements
|
|
969
1018
|
- The server must be run with the `--allow-sensitive-data-access` flag
|
|
970
1019
|
- The resource must exist and be accessible in the specified namespace
|