kubectl-mcp-server 1.14.0__py3-none-any.whl → 1.16.0__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.
Files changed (37) hide show
  1. kubectl_mcp_server-1.16.0.dist-info/METADATA +1047 -0
  2. kubectl_mcp_server-1.16.0.dist-info/RECORD +61 -0
  3. kubectl_mcp_tool/__init__.py +1 -1
  4. kubectl_mcp_tool/crd_detector.py +247 -0
  5. kubectl_mcp_tool/k8s_config.py +304 -63
  6. kubectl_mcp_tool/mcp_server.py +27 -0
  7. kubectl_mcp_tool/tools/__init__.py +20 -0
  8. kubectl_mcp_tool/tools/backup.py +881 -0
  9. kubectl_mcp_tool/tools/capi.py +727 -0
  10. kubectl_mcp_tool/tools/certs.py +709 -0
  11. kubectl_mcp_tool/tools/cilium.py +582 -0
  12. kubectl_mcp_tool/tools/cluster.py +395 -121
  13. kubectl_mcp_tool/tools/core.py +157 -60
  14. kubectl_mcp_tool/tools/cost.py +97 -41
  15. kubectl_mcp_tool/tools/deployments.py +173 -56
  16. kubectl_mcp_tool/tools/diagnostics.py +40 -13
  17. kubectl_mcp_tool/tools/gitops.py +552 -0
  18. kubectl_mcp_tool/tools/helm.py +133 -46
  19. kubectl_mcp_tool/tools/keda.py +464 -0
  20. kubectl_mcp_tool/tools/kiali.py +652 -0
  21. kubectl_mcp_tool/tools/kubevirt.py +803 -0
  22. kubectl_mcp_tool/tools/networking.py +106 -32
  23. kubectl_mcp_tool/tools/operations.py +176 -50
  24. kubectl_mcp_tool/tools/pods.py +162 -50
  25. kubectl_mcp_tool/tools/policy.py +554 -0
  26. kubectl_mcp_tool/tools/rollouts.py +790 -0
  27. kubectl_mcp_tool/tools/security.py +89 -36
  28. kubectl_mcp_tool/tools/storage.py +35 -16
  29. tests/test_browser.py +2 -2
  30. tests/test_ecosystem.py +331 -0
  31. tests/test_tools.py +73 -10
  32. kubectl_mcp_server-1.14.0.dist-info/METADATA +0 -780
  33. kubectl_mcp_server-1.14.0.dist-info/RECORD +0 -49
  34. {kubectl_mcp_server-1.14.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/WHEEL +0 -0
  35. {kubectl_mcp_server-1.14.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/entry_points.txt +0 -0
  36. {kubectl_mcp_server-1.14.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/licenses/LICENSE +0 -0
  37. {kubectl_mcp_server-1.14.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/top_level.txt +0 -0
@@ -11,6 +11,20 @@ from mcp.types import ToolAnnotations
11
11
  logger = logging.getLogger("mcp-server")
12
12
 
13
13
 
14
+ def _get_helm_context_args(context: str) -> List[str]:
15
+ """Get helm kube-context arguments if context is specified."""
16
+ if context:
17
+ return ["--kube-context", context]
18
+ return []
19
+
20
+
21
+ def _get_kubectl_context_args(context: str) -> List[str]:
22
+ """Get kubectl context arguments if context is specified."""
23
+ if context:
24
+ return ["--context", context]
25
+ return []
26
+
27
+
14
28
  def register_helm_tools(
15
29
  server,
16
30
  non_destructive: bool,
@@ -35,9 +49,19 @@ def register_helm_tools(
35
49
  chart: str,
36
50
  namespace: str,
37
51
  repo: Optional[str] = None,
38
- values: Optional[dict] = None
52
+ values: Optional[dict] = None,
53
+ context: str = ""
39
54
  ) -> Dict[str, Any]:
40
- """Install a Helm chart."""
55
+ """Install a Helm chart.
56
+
57
+ Args:
58
+ name: Release name
59
+ chart: Chart reference
60
+ namespace: Target namespace
61
+ repo: Repository in format 'repo_name=repo_url'
62
+ values: Values to override
63
+ context: Kubernetes context to use (optional, uses current context if not specified)
64
+ """
41
65
  if non_destructive:
42
66
  return {"success": False, "error": "Blocked: non-destructive mode"}
43
67
  if not check_helm_fn():
@@ -65,14 +89,14 @@ def register_helm_tools(
65
89
  logger.error(f"Error adding Helm repo: {e.stderr if hasattr(e, 'stderr') else str(e)}")
66
90
  return {"success": False, "error": f"Failed to add Helm repo: {e.stderr if hasattr(e, 'stderr') else str(e)}"}
67
91
 
68
- cmd = ["helm", "install", name, chart, "-n", namespace]
92
+ cmd = ["helm"] + _get_helm_context_args(context) + ["install", name, chart, "-n", namespace]
69
93
 
70
94
  try:
71
- ns_cmd = ["kubectl", "get", "namespace", namespace]
95
+ ns_cmd = ["kubectl"] + _get_kubectl_context_args(context) + ["get", "namespace", namespace]
72
96
  subprocess.check_output(ns_cmd, stderr=subprocess.PIPE, text=True)
73
97
  except subprocess.CalledProcessError:
74
98
  logger.info(f"Namespace {namespace} not found, creating it")
75
- create_ns_cmd = ["kubectl", "create", "namespace", namespace]
99
+ create_ns_cmd = ["kubectl"] + _get_kubectl_context_args(context) + ["create", "namespace", namespace]
76
100
  try:
77
101
  subprocess.check_output(create_ns_cmd, stderr=subprocess.PIPE, text=True)
78
102
  except subprocess.CalledProcessError as e:
@@ -92,6 +116,7 @@ def register_helm_tools(
92
116
 
93
117
  return {
94
118
  "success": True,
119
+ "context": context or "current",
95
120
  "message": f"Helm chart {chart} installed as {name} in {namespace}",
96
121
  "details": result
97
122
  }
@@ -117,9 +142,19 @@ def register_helm_tools(
117
142
  chart: str,
118
143
  namespace: str,
119
144
  repo: Optional[str] = None,
120
- values: Optional[dict] = None
145
+ values: Optional[dict] = None,
146
+ context: str = ""
121
147
  ) -> Dict[str, Any]:
122
- """Upgrade a Helm release."""
148
+ """Upgrade a Helm release.
149
+
150
+ Args:
151
+ name: Release name
152
+ chart: Chart reference
153
+ namespace: Target namespace
154
+ repo: Repository in format 'repo_name=repo_url'
155
+ values: Values to override
156
+ context: Kubernetes context to use (optional, uses current context if not specified)
157
+ """
123
158
  if non_destructive:
124
159
  return {"success": False, "error": "Blocked: non-destructive mode"}
125
160
  if not check_helm_fn():
@@ -147,7 +182,7 @@ def register_helm_tools(
147
182
  logger.error(f"Error adding Helm repo: {e.stderr if hasattr(e, 'stderr') else str(e)}")
148
183
  return {"success": False, "error": f"Failed to add Helm repo: {e.stderr if hasattr(e, 'stderr') else str(e)}"}
149
184
 
150
- cmd = ["helm", "upgrade", name, chart, "-n", namespace]
185
+ cmd = ["helm"] + _get_helm_context_args(context) + ["upgrade", name, chart, "-n", namespace]
151
186
 
152
187
  values_file = None
153
188
  try:
@@ -162,6 +197,7 @@ def register_helm_tools(
162
197
 
163
198
  return {
164
199
  "success": True,
200
+ "context": context or "current",
165
201
  "message": f"Helm release {name} upgraded with chart {chart} in {namespace}",
166
202
  "details": result
167
203
  }
@@ -182,21 +218,28 @@ def register_helm_tools(
182
218
  destructiveHint=True,
183
219
  ),
184
220
  )
185
- def uninstall_helm_chart(name: str, namespace: str) -> Dict[str, Any]:
186
- """Uninstall a Helm release."""
221
+ def uninstall_helm_chart(name: str, namespace: str, context: str = "") -> Dict[str, Any]:
222
+ """Uninstall a Helm release.
223
+
224
+ Args:
225
+ name: Release name to uninstall
226
+ namespace: Target namespace
227
+ context: Kubernetes context to use (optional, uses current context if not specified)
228
+ """
187
229
  if non_destructive:
188
230
  return {"success": False, "error": "Blocked: non-destructive mode"}
189
231
  if not check_helm_fn():
190
232
  return {"success": False, "error": "Helm is not available on this system"}
191
233
 
192
234
  try:
193
- cmd = ["helm", "uninstall", name, "-n", namespace]
235
+ cmd = ["helm"] + _get_helm_context_args(context) + ["uninstall", name, "-n", namespace]
194
236
  logger.debug(f"Running command: {' '.join(cmd)}")
195
237
 
196
238
  try:
197
239
  result = subprocess.check_output(cmd, stderr=subprocess.PIPE, text=True)
198
240
  return {
199
241
  "success": True,
242
+ "context": context or "current",
200
243
  "message": f"Helm release {name} uninstalled from {namespace}",
201
244
  "details": result
202
245
  }
@@ -222,7 +265,8 @@ def register_helm_tools(
222
265
  failed: bool = False,
223
266
  pending: bool = False,
224
267
  uninstalled: bool = False,
225
- superseded: bool = False
268
+ superseded: bool = False,
269
+ context: str = ""
226
270
  ) -> Dict[str, Any]:
227
271
  """List Helm releases with optional filtering.
228
272
 
@@ -235,12 +279,13 @@ def register_helm_tools(
235
279
  pending: Show pending releases only
236
280
  uninstalled: Show uninstalled releases (if kept with --keep-history)
237
281
  superseded: Show superseded releases only
282
+ context: Kubernetes context to use (optional, uses current context if not specified)
238
283
  """
239
284
  if not check_helm_fn():
240
285
  return {"success": False, "error": "Helm is not available on this system"}
241
286
 
242
287
  try:
243
- cmd = ["helm", "list", "--output", "json"]
288
+ cmd = ["helm"] + _get_helm_context_args(context) + ["list", "--output", "json"]
244
289
 
245
290
  if all_namespaces:
246
291
  cmd.append("--all-namespaces")
@@ -270,6 +315,7 @@ def register_helm_tools(
270
315
  releases = json.loads(result.stdout) if result.stdout.strip() else []
271
316
  return {
272
317
  "success": True,
318
+ "context": context or "current",
273
319
  "releases": releases,
274
320
  "count": len(releases)
275
321
  }
@@ -290,7 +336,8 @@ def register_helm_tools(
290
336
  namespace: str = "default",
291
337
  revision: Optional[int] = None,
292
338
  show_desc: bool = False,
293
- show_resources: bool = False
339
+ show_resources: bool = False,
340
+ context: str = ""
294
341
  ) -> Dict[str, Any]:
295
342
  """Get the status of a Helm release.
296
343
 
@@ -300,12 +347,13 @@ def register_helm_tools(
300
347
  revision: Show status for a specific revision (default: latest)
301
348
  show_desc: Show description of the release
302
349
  show_resources: Show resources created by the release
350
+ context: Kubernetes context to use (optional, uses current context if not specified)
303
351
  """
304
352
  if not check_helm_fn():
305
353
  return {"success": False, "error": "Helm is not available on this system"}
306
354
 
307
355
  try:
308
- cmd = ["helm", "status", release_name, "-n", namespace, "--output", "json"]
356
+ cmd = ["helm"] + _get_helm_context_args(context) + ["status", release_name, "-n", namespace, "--output", "json"]
309
357
 
310
358
  if revision:
311
359
  cmd.extend(["--revision", str(revision)])
@@ -319,7 +367,7 @@ def register_helm_tools(
319
367
 
320
368
  if result.returncode == 0:
321
369
  status = json.loads(result.stdout) if result.stdout.strip() else {}
322
- return {"success": True, "status": status}
370
+ return {"success": True, "context": context or "current", "status": status}
323
371
  else:
324
372
  return {"success": False, "error": result.stderr.strip()}
325
373
  except Exception as e:
@@ -335,7 +383,8 @@ def register_helm_tools(
335
383
  def helm_history(
336
384
  release_name: str,
337
385
  namespace: str = "default",
338
- max_revisions: int = 256
386
+ max_revisions: int = 256,
387
+ context: str = ""
339
388
  ) -> Dict[str, Any]:
340
389
  """Get the revision history of a Helm release.
341
390
 
@@ -343,12 +392,13 @@ def register_helm_tools(
343
392
  release_name: Name of the release
344
393
  namespace: Kubernetes namespace
345
394
  max_revisions: Maximum number of revisions to return
395
+ context: Kubernetes context to use (optional, uses current context if not specified)
346
396
  """
347
397
  if not check_helm_fn():
348
398
  return {"success": False, "error": "Helm is not available on this system"}
349
399
 
350
400
  try:
351
- cmd = ["helm", "history", release_name, "-n", namespace, "--output", "json", "--max", str(max_revisions)]
401
+ cmd = ["helm"] + _get_helm_context_args(context) + ["history", release_name, "-n", namespace, "--output", "json", "--max", str(max_revisions)]
352
402
 
353
403
  logger.debug(f"Running command: {' '.join(cmd)}")
354
404
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
@@ -357,6 +407,7 @@ def register_helm_tools(
357
407
  history = json.loads(result.stdout) if result.stdout.strip() else []
358
408
  return {
359
409
  "success": True,
410
+ "context": context or "current",
360
411
  "history": history,
361
412
  "revisions": len(history)
362
413
  }
@@ -376,7 +427,8 @@ def register_helm_tools(
376
427
  release_name: str,
377
428
  namespace: str = "default",
378
429
  all_values: bool = False,
379
- revision: Optional[int] = None
430
+ revision: Optional[int] = None,
431
+ context: str = ""
380
432
  ) -> Dict[str, Any]:
381
433
  """Get the values used for a Helm release.
382
434
 
@@ -385,12 +437,13 @@ def register_helm_tools(
385
437
  namespace: Kubernetes namespace
386
438
  all_values: Include computed (default + user) values
387
439
  revision: Get values for a specific revision
440
+ context: Kubernetes context to use (optional, uses current context if not specified)
388
441
  """
389
442
  if not check_helm_fn():
390
443
  return {"success": False, "error": "Helm is not available on this system"}
391
444
 
392
445
  try:
393
- cmd = ["helm", "get", "values", release_name, "-n", namespace, "--output", "yaml"]
446
+ cmd = ["helm"] + _get_helm_context_args(context) + ["get", "values", release_name, "-n", namespace, "--output", "yaml"]
394
447
 
395
448
  if all_values:
396
449
  cmd.append("--all")
@@ -402,7 +455,7 @@ def register_helm_tools(
402
455
 
403
456
  if result.returncode == 0:
404
457
  values = yaml.safe_load(result.stdout) if result.stdout.strip() else {}
405
- return {"success": True, "values": values, "raw": result.stdout}
458
+ return {"success": True, "context": context or "current", "values": values, "raw": result.stdout}
406
459
  else:
407
460
  return {"success": False, "error": result.stderr.strip()}
408
461
  except Exception as e:
@@ -418,7 +471,8 @@ def register_helm_tools(
418
471
  def helm_get_manifest(
419
472
  release_name: str,
420
473
  namespace: str = "default",
421
- revision: Optional[int] = None
474
+ revision: Optional[int] = None,
475
+ context: str = ""
422
476
  ) -> Dict[str, Any]:
423
477
  """Get the manifest (rendered templates) of a Helm release.
424
478
 
@@ -426,12 +480,13 @@ def register_helm_tools(
426
480
  release_name: Name of the release
427
481
  namespace: Kubernetes namespace
428
482
  revision: Get manifest for a specific revision
483
+ context: Kubernetes context to use (optional, uses current context if not specified)
429
484
  """
430
485
  if not check_helm_fn():
431
486
  return {"success": False, "error": "Helm is not available on this system"}
432
487
 
433
488
  try:
434
- cmd = ["helm", "get", "manifest", release_name, "-n", namespace]
489
+ cmd = ["helm"] + _get_helm_context_args(context) + ["get", "manifest", release_name, "-n", namespace]
435
490
 
436
491
  if revision:
437
492
  cmd.extend(["--revision", str(revision)])
@@ -440,7 +495,7 @@ def register_helm_tools(
440
495
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
441
496
 
442
497
  if result.returncode == 0:
443
- return {"success": True, "manifest": result.stdout}
498
+ return {"success": True, "context": context or "current", "manifest": result.stdout}
444
499
  else:
445
500
  return {"success": False, "error": result.stderr.strip()}
446
501
  except Exception as e:
@@ -456,7 +511,8 @@ def register_helm_tools(
456
511
  def helm_get_notes(
457
512
  release_name: str,
458
513
  namespace: str = "default",
459
- revision: Optional[int] = None
514
+ revision: Optional[int] = None,
515
+ context: str = ""
460
516
  ) -> Dict[str, Any]:
461
517
  """Get the notes (post-install message) of a Helm release.
462
518
 
@@ -464,12 +520,13 @@ def register_helm_tools(
464
520
  release_name: Name of the release
465
521
  namespace: Kubernetes namespace
466
522
  revision: Get notes for a specific revision
523
+ context: Kubernetes context to use (optional, uses current context if not specified)
467
524
  """
468
525
  if not check_helm_fn():
469
526
  return {"success": False, "error": "Helm is not available on this system"}
470
527
 
471
528
  try:
472
- cmd = ["helm", "get", "notes", release_name, "-n", namespace]
529
+ cmd = ["helm"] + _get_helm_context_args(context) + ["get", "notes", release_name, "-n", namespace]
473
530
 
474
531
  if revision:
475
532
  cmd.extend(["--revision", str(revision)])
@@ -478,7 +535,7 @@ def register_helm_tools(
478
535
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
479
536
 
480
537
  if result.returncode == 0:
481
- return {"success": True, "notes": result.stdout}
538
+ return {"success": True, "context": context or "current", "notes": result.stdout}
482
539
  else:
483
540
  return {"success": False, "error": result.stderr.strip()}
484
541
  except Exception as e:
@@ -494,7 +551,8 @@ def register_helm_tools(
494
551
  def helm_get_hooks(
495
552
  release_name: str,
496
553
  namespace: str = "default",
497
- revision: Optional[int] = None
554
+ revision: Optional[int] = None,
555
+ context: str = ""
498
556
  ) -> Dict[str, Any]:
499
557
  """Get the hooks of a Helm release.
500
558
 
@@ -502,12 +560,13 @@ def register_helm_tools(
502
560
  release_name: Name of the release
503
561
  namespace: Kubernetes namespace
504
562
  revision: Get hooks for a specific revision
563
+ context: Kubernetes context to use (optional, uses current context if not specified)
505
564
  """
506
565
  if not check_helm_fn():
507
566
  return {"success": False, "error": "Helm is not available on this system"}
508
567
 
509
568
  try:
510
- cmd = ["helm", "get", "hooks", release_name, "-n", namespace]
569
+ cmd = ["helm"] + _get_helm_context_args(context) + ["get", "hooks", release_name, "-n", namespace]
511
570
 
512
571
  if revision:
513
572
  cmd.extend(["--revision", str(revision)])
@@ -516,7 +575,7 @@ def register_helm_tools(
516
575
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
517
576
 
518
577
  if result.returncode == 0:
519
- return {"success": True, "hooks": result.stdout}
578
+ return {"success": True, "context": context or "current", "hooks": result.stdout}
520
579
  else:
521
580
  return {"success": False, "error": result.stderr.strip()}
522
581
  except Exception as e:
@@ -532,7 +591,8 @@ def register_helm_tools(
532
591
  def helm_get_all(
533
592
  release_name: str,
534
593
  namespace: str = "default",
535
- revision: Optional[int] = None
594
+ revision: Optional[int] = None,
595
+ context: str = ""
536
596
  ) -> Dict[str, Any]:
537
597
  """Get all information about a Helm release (values, manifest, hooks, notes).
538
598
 
@@ -540,12 +600,13 @@ def register_helm_tools(
540
600
  release_name: Name of the release
541
601
  namespace: Kubernetes namespace
542
602
  revision: Get info for a specific revision
603
+ context: Kubernetes context to use (optional, uses current context if not specified)
543
604
  """
544
605
  if not check_helm_fn():
545
606
  return {"success": False, "error": "Helm is not available on this system"}
546
607
 
547
608
  try:
548
- cmd = ["helm", "get", "all", release_name, "-n", namespace]
609
+ cmd = ["helm"] + _get_helm_context_args(context) + ["get", "all", release_name, "-n", namespace]
549
610
 
550
611
  if revision:
551
612
  cmd.extend(["--revision", str(revision)])
@@ -554,7 +615,7 @@ def register_helm_tools(
554
615
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
555
616
 
556
617
  if result.returncode == 0:
557
- return {"success": True, "release_info": result.stdout}
618
+ return {"success": True, "context": context or "current", "release_info": result.stdout}
558
619
  else:
559
620
  return {"success": False, "error": result.stderr.strip()}
560
621
  except Exception as e:
@@ -1031,7 +1092,8 @@ def register_helm_tools(
1031
1092
  recreate_pods: bool = False,
1032
1093
  cleanup_on_fail: bool = False,
1033
1094
  wait: bool = False,
1034
- timeout: str = "5m0s"
1095
+ timeout: str = "5m0s",
1096
+ context: str = ""
1035
1097
  ) -> Dict[str, Any]:
1036
1098
  """Rollback a Helm release to a previous revision.
1037
1099
 
@@ -1044,6 +1106,7 @@ def register_helm_tools(
1044
1106
  cleanup_on_fail: Delete newly created resources on failure
1045
1107
  wait: Wait until all resources are ready
1046
1108
  timeout: Timeout for waiting
1109
+ context: Kubernetes context to use (optional, uses current context if not specified)
1047
1110
  """
1048
1111
  if non_destructive:
1049
1112
  return {"success": False, "error": "Blocked: non-destructive mode"}
@@ -1051,7 +1114,7 @@ def register_helm_tools(
1051
1114
  return {"success": False, "error": "Helm is not available on this system"}
1052
1115
 
1053
1116
  try:
1054
- cmd = ["helm", "rollback", release_name, str(revision), "-n", namespace]
1117
+ cmd = ["helm"] + _get_helm_context_args(context) + ["rollback", release_name, str(revision), "-n", namespace]
1055
1118
 
1056
1119
  if force:
1057
1120
  cmd.append("--force")
@@ -1069,6 +1132,7 @@ def register_helm_tools(
1069
1132
  if result.returncode == 0:
1070
1133
  return {
1071
1134
  "success": True,
1135
+ "context": context or "current",
1072
1136
  "message": f"Release '{release_name}' rolled back to revision {revision}",
1073
1137
  "details": result.stdout.strip()
1074
1138
  }
@@ -1089,7 +1153,8 @@ def register_helm_tools(
1089
1153
  namespace: str = "default",
1090
1154
  timeout: str = "5m0s",
1091
1155
  logs: bool = True,
1092
- filter: Optional[str] = None
1156
+ filter: Optional[str] = None,
1157
+ context: str = ""
1093
1158
  ) -> Dict[str, Any]:
1094
1159
  """Run tests for a Helm release.
1095
1160
 
@@ -1099,12 +1164,13 @@ def register_helm_tools(
1099
1164
  timeout: Timeout for tests
1100
1165
  logs: Show test pod logs
1101
1166
  filter: Filter tests by name
1167
+ context: Kubernetes context to use (optional, uses current context if not specified)
1102
1168
  """
1103
1169
  if not check_helm_fn():
1104
1170
  return {"success": False, "error": "Helm is not available on this system"}
1105
1171
 
1106
1172
  try:
1107
- cmd = ["helm", "test", release_name, "-n", namespace, "--timeout", timeout]
1173
+ cmd = ["helm"] + _get_helm_context_args(context) + ["test", release_name, "-n", namespace, "--timeout", timeout]
1108
1174
 
1109
1175
  if logs:
1110
1176
  cmd.append("--logs")
@@ -1117,6 +1183,7 @@ def register_helm_tools(
1117
1183
  if result.returncode == 0:
1118
1184
  return {
1119
1185
  "success": True,
1186
+ "context": context or "current",
1120
1187
  "message": f"Tests passed for release '{release_name}'",
1121
1188
  "output": result.stdout.strip()
1122
1189
  }
@@ -1507,18 +1574,28 @@ def register_helm_tools(
1507
1574
  name: str,
1508
1575
  namespace: str = "default",
1509
1576
  repo: Optional[str] = None,
1510
- values: Optional[str] = None
1577
+ values: Optional[str] = None,
1578
+ context: str = ""
1511
1579
  ) -> Dict[str, Any]:
1512
- """Render Helm chart templates locally without installing."""
1580
+ """Render Helm chart templates locally without installing.
1581
+
1582
+ Args:
1583
+ chart: Chart reference
1584
+ name: Release name for template
1585
+ namespace: Target namespace
1586
+ repo: Repository URL
1587
+ values: Set values on command line
1588
+ context: Kubernetes context to use (optional, uses current context if not specified)
1589
+ """
1513
1590
  try:
1514
- cmd = ["helm", "template", name, chart, "-n", namespace]
1591
+ cmd = ["helm"] + _get_helm_context_args(context) + ["template", name, chart, "-n", namespace]
1515
1592
  if repo:
1516
1593
  cmd.extend(["--repo", repo])
1517
1594
  if values:
1518
1595
  cmd.extend(["--set", values])
1519
1596
  result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
1520
1597
  if result.returncode == 0:
1521
- return {"success": True, "manifest": result.stdout}
1598
+ return {"success": True, "context": context or "current", "manifest": result.stdout}
1522
1599
  else:
1523
1600
  return {"success": False, "error": result.stderr.strip()}
1524
1601
  except Exception as e:
@@ -1536,13 +1613,23 @@ def register_helm_tools(
1536
1613
  name: str,
1537
1614
  namespace: str = "default",
1538
1615
  repo: Optional[str] = None,
1539
- values: Optional[str] = None
1616
+ values: Optional[str] = None,
1617
+ context: str = ""
1540
1618
  ) -> Dict[str, Any]:
1541
- """Render and apply Helm chart (bypasses Tiller/auth issues)."""
1619
+ """Render and apply Helm chart (bypasses Tiller/auth issues).
1620
+
1621
+ Args:
1622
+ chart: Chart reference
1623
+ name: Release name for template
1624
+ namespace: Target namespace
1625
+ repo: Repository URL
1626
+ values: Set values on command line
1627
+ context: Kubernetes context to use (optional, uses current context if not specified)
1628
+ """
1542
1629
  if non_destructive:
1543
1630
  return {"success": False, "error": "Operation blocked: non-destructive mode enabled"}
1544
1631
  try:
1545
- cmd = ["helm", "template", name, chart, "-n", namespace]
1632
+ cmd = ["helm"] + _get_helm_context_args(context) + ["template", name, chart, "-n", namespace]
1546
1633
  if repo:
1547
1634
  cmd.extend(["--repo", repo])
1548
1635
  if values:
@@ -1550,10 +1637,10 @@ def register_helm_tools(
1550
1637
  template_result = subprocess.run(cmd, capture_output=True, text=True, timeout=60)
1551
1638
  if template_result.returncode != 0:
1552
1639
  return {"success": False, "error": template_result.stderr.strip()}
1553
- apply_cmd = ["kubectl", "apply", "-f", "-", "-n", namespace]
1640
+ apply_cmd = ["kubectl"] + _get_kubectl_context_args(context) + ["apply", "-f", "-", "-n", namespace]
1554
1641
  apply_result = subprocess.run(apply_cmd, input=template_result.stdout, capture_output=True, text=True, timeout=60)
1555
1642
  if apply_result.returncode == 0:
1556
- return {"success": True, "output": apply_result.stdout.strip()}
1643
+ return {"success": True, "context": context or "current", "output": apply_result.stdout.strip()}
1557
1644
  else:
1558
1645
  return {"success": False, "error": apply_result.stderr.strip()}
1559
1646
  except Exception as e: