kubectl-mcp-server 1.17.0__tar.gz → 1.18.0__tar.gz

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 (81) hide show
  1. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/PKG-INFO +48 -1
  2. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/README.md +47 -0
  3. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/PKG-INFO +48 -1
  4. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/SOURCES.txt +1 -0
  5. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/__init__.py +1 -1
  6. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/k8s_config.py +127 -1
  7. kubectl_mcp_server-1.18.0/kubectl_mcp_tool/providers.py +347 -0
  8. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/setup.py +1 -1
  9. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/LICENSE +0 -0
  10. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/dependency_links.txt +0 -0
  11. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/entry_points.txt +0 -0
  12. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/requires.txt +0 -0
  13. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_server.egg-info/top_level.txt +0 -0
  14. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/__main__.py +0 -0
  15. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/auth/__init__.py +0 -0
  16. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/auth/config.py +0 -0
  17. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/auth/scopes.py +0 -0
  18. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/auth/verifier.py +0 -0
  19. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/cli/__init__.py +0 -0
  20. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/cli/__main__.py +0 -0
  21. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/cli/cli.py +0 -0
  22. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/cli/errors.py +0 -0
  23. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/cli/output.py +0 -0
  24. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/config/__init__.py +0 -0
  25. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/config/loader.py +0 -0
  26. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/config/schema.py +0 -0
  27. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/crd_detector.py +0 -0
  28. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/diagnostics.py +0 -0
  29. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/mcp_server.py +0 -0
  30. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/observability/__init__.py +0 -0
  31. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/observability/metrics.py +0 -0
  32. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/observability/stats.py +0 -0
  33. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/observability/tracing.py +0 -0
  34. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/prompts/__init__.py +0 -0
  35. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/prompts/builtin.py +0 -0
  36. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/prompts/custom.py +0 -0
  37. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/prompts/prompts.py +0 -0
  38. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/resources/__init__.py +0 -0
  39. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/resources/resources.py +0 -0
  40. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/safety.py +0 -0
  41. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/__init__.py +0 -0
  42. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/backup.py +0 -0
  43. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/browser.py +0 -0
  44. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/capi.py +0 -0
  45. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/certs.py +0 -0
  46. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/cilium.py +0 -0
  47. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/cluster.py +0 -0
  48. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/core.py +0 -0
  49. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/cost.py +0 -0
  50. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/deployments.py +0 -0
  51. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/diagnostics.py +0 -0
  52. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/gitops.py +0 -0
  53. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/helm.py +0 -0
  54. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/keda.py +0 -0
  55. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/kiali.py +0 -0
  56. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/kubevirt.py +0 -0
  57. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/networking.py +0 -0
  58. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/operations.py +0 -0
  59. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/pods.py +0 -0
  60. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/policy.py +0 -0
  61. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/rollouts.py +0 -0
  62. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/security.py +0 -0
  63. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/storage.py +0 -0
  64. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/tools/ui.py +0 -0
  65. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/utils/__init__.py +0 -0
  66. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/kubectl_mcp_tool/utils/helpers.py +0 -0
  67. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/setup.cfg +0 -0
  68. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/__init__.py +0 -0
  69. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/conftest.py +0 -0
  70. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_auth.py +0 -0
  71. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_browser.py +0 -0
  72. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_cli.py +0 -0
  73. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_config.py +0 -0
  74. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_ecosystem.py +0 -0
  75. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_mcp_integration.py +0 -0
  76. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_observability.py +0 -0
  77. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_prompts.py +0 -0
  78. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_resources.py +0 -0
  79. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_safety.py +0 -0
  80. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_server.py +0 -0
  81. {kubectl_mcp_server-1.17.0 → kubectl_mcp_server-1.18.0}/tests/test_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kubectl-mcp-server
3
- Version: 1.17.0
3
+ Version: 1.18.0
4
4
  Summary: A Model Context Protocol (MCP) server for Kubernetes with 220+ tools, 8 resources, and 8 prompts
5
5
  Home-page: https://github.com/rohitg00/kubectl-mcp-server
6
6
  Author: Rohit Ghumare
@@ -121,6 +121,7 @@ pip install kubectl-mcp-server[ui]
121
121
  - [In-Cluster Deployment](#in-cluster-deployment)
122
122
  - [Multi-Cluster Support](#multi-cluster-support)
123
123
  - [Architecture](#architecture)
124
+ - [Agent Skills](#agent-skills-24-skills-for-ai-coding-agents)
124
125
  - [Development & Testing](#development--testing)
125
126
  - [Contributing](#contributing)
126
127
  - [Support & Community](#support--community)
@@ -875,6 +876,52 @@ kubectl_mcp_tool/
875
876
  └── cli/ # CLI interface
876
877
  ```
877
878
 
879
+ ## Agent Skills (24 Skills for AI Coding Agents)
880
+
881
+ Extend your AI coding agent with Kubernetes expertise using our [Agent Skills](https://agentskills.io) library. Skills provide specialized knowledge and workflows that agents can load on demand.
882
+
883
+ ### Quick Install
884
+
885
+ ```bash
886
+ # Copy all skills to Claude
887
+ cp -r kubernetes-skills/claude/* ~/.claude/skills/
888
+
889
+ # Or install specific skills
890
+ cp -r kubernetes-skills/claude/k8s-helm ~/.claude/skills/
891
+ ```
892
+
893
+ ### Available Skills (24)
894
+
895
+ | Category | Skills |
896
+ |----------|--------|
897
+ | **Core Resources** | k8s-core, k8s-networking, k8s-storage |
898
+ | **Workloads** | k8s-deploy, k8s-operations, k8s-helm |
899
+ | **Observability** | k8s-diagnostics, k8s-troubleshoot, k8s-incident |
900
+ | **Security** | k8s-security, k8s-policy, k8s-certs |
901
+ | **GitOps** | k8s-gitops, k8s-rollouts |
902
+ | **Scaling** | k8s-autoscaling, k8s-cost, k8s-backup |
903
+ | **Multi-Cluster** | k8s-multicluster, k8s-capi, k8s-kubevirt |
904
+ | **Networking** | k8s-service-mesh, k8s-cilium |
905
+ | **Tools** | k8s-browser, k8s-cli |
906
+
907
+ ### Convert to Other Agents
908
+
909
+ Use [SkillKit](https://github.com/rohitg00/skillkit) to convert skills to your preferred AI agent format:
910
+
911
+ ```bash
912
+ npm install -g skillkit
913
+
914
+ # Convert to Cursor format
915
+ skillkit translate kubernetes-skills/claude --to cursor --output .cursor/rules/
916
+
917
+ # Convert to Codex format
918
+ skillkit translate kubernetes-skills/claude --to codex --output ./
919
+ ```
920
+
921
+ **Supported agents:** Claude, Cursor, Codex, Gemini CLI, GitHub Copilot, Goose, Windsurf, Roo, Amp, and more.
922
+
923
+ See [kubernetes-skills/README.md](kubernetes-skills/README.md) for full documentation.
924
+
878
925
  ## Multi-Cluster Support
879
926
 
880
927
  Seamlessly manage multiple Kubernetes clusters through natural language. **Every tool** supports an optional `context` parameter to target any cluster without switching contexts.
@@ -63,6 +63,7 @@ pip install kubectl-mcp-server[ui]
63
63
  - [In-Cluster Deployment](#in-cluster-deployment)
64
64
  - [Multi-Cluster Support](#multi-cluster-support)
65
65
  - [Architecture](#architecture)
66
+ - [Agent Skills](#agent-skills-24-skills-for-ai-coding-agents)
66
67
  - [Development & Testing](#development--testing)
67
68
  - [Contributing](#contributing)
68
69
  - [Support & Community](#support--community)
@@ -817,6 +818,52 @@ kubectl_mcp_tool/
817
818
  └── cli/ # CLI interface
818
819
  ```
819
820
 
821
+ ## Agent Skills (24 Skills for AI Coding Agents)
822
+
823
+ Extend your AI coding agent with Kubernetes expertise using our [Agent Skills](https://agentskills.io) library. Skills provide specialized knowledge and workflows that agents can load on demand.
824
+
825
+ ### Quick Install
826
+
827
+ ```bash
828
+ # Copy all skills to Claude
829
+ cp -r kubernetes-skills/claude/* ~/.claude/skills/
830
+
831
+ # Or install specific skills
832
+ cp -r kubernetes-skills/claude/k8s-helm ~/.claude/skills/
833
+ ```
834
+
835
+ ### Available Skills (24)
836
+
837
+ | Category | Skills |
838
+ |----------|--------|
839
+ | **Core Resources** | k8s-core, k8s-networking, k8s-storage |
840
+ | **Workloads** | k8s-deploy, k8s-operations, k8s-helm |
841
+ | **Observability** | k8s-diagnostics, k8s-troubleshoot, k8s-incident |
842
+ | **Security** | k8s-security, k8s-policy, k8s-certs |
843
+ | **GitOps** | k8s-gitops, k8s-rollouts |
844
+ | **Scaling** | k8s-autoscaling, k8s-cost, k8s-backup |
845
+ | **Multi-Cluster** | k8s-multicluster, k8s-capi, k8s-kubevirt |
846
+ | **Networking** | k8s-service-mesh, k8s-cilium |
847
+ | **Tools** | k8s-browser, k8s-cli |
848
+
849
+ ### Convert to Other Agents
850
+
851
+ Use [SkillKit](https://github.com/rohitg00/skillkit) to convert skills to your preferred AI agent format:
852
+
853
+ ```bash
854
+ npm install -g skillkit
855
+
856
+ # Convert to Cursor format
857
+ skillkit translate kubernetes-skills/claude --to cursor --output .cursor/rules/
858
+
859
+ # Convert to Codex format
860
+ skillkit translate kubernetes-skills/claude --to codex --output ./
861
+ ```
862
+
863
+ **Supported agents:** Claude, Cursor, Codex, Gemini CLI, GitHub Copilot, Goose, Windsurf, Roo, Amp, and more.
864
+
865
+ See [kubernetes-skills/README.md](kubernetes-skills/README.md) for full documentation.
866
+
820
867
  ## Multi-Cluster Support
821
868
 
822
869
  Seamlessly manage multiple Kubernetes clusters through natural language. **Every tool** supports an optional `context` parameter to target any cluster without switching contexts.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kubectl-mcp-server
3
- Version: 1.17.0
3
+ Version: 1.18.0
4
4
  Summary: A Model Context Protocol (MCP) server for Kubernetes with 220+ tools, 8 resources, and 8 prompts
5
5
  Home-page: https://github.com/rohitg00/kubectl-mcp-server
6
6
  Author: Rohit Ghumare
@@ -121,6 +121,7 @@ pip install kubectl-mcp-server[ui]
121
121
  - [In-Cluster Deployment](#in-cluster-deployment)
122
122
  - [Multi-Cluster Support](#multi-cluster-support)
123
123
  - [Architecture](#architecture)
124
+ - [Agent Skills](#agent-skills-24-skills-for-ai-coding-agents)
124
125
  - [Development & Testing](#development--testing)
125
126
  - [Contributing](#contributing)
126
127
  - [Support & Community](#support--community)
@@ -875,6 +876,52 @@ kubectl_mcp_tool/
875
876
  └── cli/ # CLI interface
876
877
  ```
877
878
 
879
+ ## Agent Skills (24 Skills for AI Coding Agents)
880
+
881
+ Extend your AI coding agent with Kubernetes expertise using our [Agent Skills](https://agentskills.io) library. Skills provide specialized knowledge and workflows that agents can load on demand.
882
+
883
+ ### Quick Install
884
+
885
+ ```bash
886
+ # Copy all skills to Claude
887
+ cp -r kubernetes-skills/claude/* ~/.claude/skills/
888
+
889
+ # Or install specific skills
890
+ cp -r kubernetes-skills/claude/k8s-helm ~/.claude/skills/
891
+ ```
892
+
893
+ ### Available Skills (24)
894
+
895
+ | Category | Skills |
896
+ |----------|--------|
897
+ | **Core Resources** | k8s-core, k8s-networking, k8s-storage |
898
+ | **Workloads** | k8s-deploy, k8s-operations, k8s-helm |
899
+ | **Observability** | k8s-diagnostics, k8s-troubleshoot, k8s-incident |
900
+ | **Security** | k8s-security, k8s-policy, k8s-certs |
901
+ | **GitOps** | k8s-gitops, k8s-rollouts |
902
+ | **Scaling** | k8s-autoscaling, k8s-cost, k8s-backup |
903
+ | **Multi-Cluster** | k8s-multicluster, k8s-capi, k8s-kubevirt |
904
+ | **Networking** | k8s-service-mesh, k8s-cilium |
905
+ | **Tools** | k8s-browser, k8s-cli |
906
+
907
+ ### Convert to Other Agents
908
+
909
+ Use [SkillKit](https://github.com/rohitg00/skillkit) to convert skills to your preferred AI agent format:
910
+
911
+ ```bash
912
+ npm install -g skillkit
913
+
914
+ # Convert to Cursor format
915
+ skillkit translate kubernetes-skills/claude --to cursor --output .cursor/rules/
916
+
917
+ # Convert to Codex format
918
+ skillkit translate kubernetes-skills/claude --to codex --output ./
919
+ ```
920
+
921
+ **Supported agents:** Claude, Cursor, Codex, Gemini CLI, GitHub Copilot, Goose, Windsurf, Roo, Amp, and more.
922
+
923
+ See [kubernetes-skills/README.md](kubernetes-skills/README.md) for full documentation.
924
+
878
925
  ## Multi-Cluster Support
879
926
 
880
927
  Seamlessly manage multiple Kubernetes clusters through natural language. **Every tool** supports an optional `context` parameter to target any cluster without switching contexts.
@@ -13,6 +13,7 @@ kubectl_mcp_tool/crd_detector.py
13
13
  kubectl_mcp_tool/diagnostics.py
14
14
  kubectl_mcp_tool/k8s_config.py
15
15
  kubectl_mcp_tool/mcp_server.py
16
+ kubectl_mcp_tool/providers.py
16
17
  kubectl_mcp_tool/safety.py
17
18
  kubectl_mcp_tool/auth/__init__.py
18
19
  kubectl_mcp_tool/auth/config.py
@@ -7,7 +7,7 @@ with Kubernetes clusters through natural language commands.
7
7
  For more information, see: https://github.com/rohitg00/kubectl-mcp-server
8
8
  """
9
9
 
10
- __version__ = "1.17.0"
10
+ __version__ = "1.18.0"
11
11
 
12
12
  from .mcp_server import MCPServer
13
13
  from .diagnostics import run_diagnostics, check_kubectl_installation, check_cluster_connection
@@ -6,14 +6,39 @@ Supports multi-cluster operations with context targeting.
6
6
 
7
7
  This module provides context-aware client creation for multi-cluster support.
8
8
  All get_*_client() functions accept an optional 'context' parameter.
9
+
10
+ Environment Variables:
11
+ MCP_K8S_PROVIDER: Provider type (kubeconfig, in-cluster, single)
12
+ MCP_K8S_KUBECONFIG: Path to kubeconfig file
13
+ MCP_K8S_CONTEXT: Default context for single provider
14
+ MCP_K8S_QPS: API rate limit (default: 100)
15
+ MCP_K8S_BURST: API burst limit (default: 200)
16
+ MCP_K8S_TIMEOUT: Request timeout in seconds (default: 30)
9
17
  """
10
18
 
11
19
  import os
12
20
  import logging
13
- from typing import Optional, Any
21
+ from typing import Optional, Any, List, Dict
14
22
 
15
23
  logger = logging.getLogger("mcp-server")
16
24
 
25
+ # Try to import provider module for enhanced features
26
+ try:
27
+ from .providers import (
28
+ KubernetesProvider,
29
+ ProviderConfig,
30
+ ProviderType,
31
+ UnknownContextError,
32
+ get_provider,
33
+ get_context_names,
34
+ get_current_context as provider_get_current_context,
35
+ validate_context,
36
+ )
37
+ _HAS_PROVIDER = True
38
+ except ImportError:
39
+ _HAS_PROVIDER = False
40
+ logger.debug("Provider module not available, using basic config")
41
+
17
42
  _config_loaded = False
18
43
  _original_load_kube_config = None
19
44
 
@@ -114,12 +139,29 @@ def _load_config_for_context(context: str = "") -> Any:
114
139
  """
115
140
  Load kubernetes config for a specific context and return ApiClient.
116
141
 
142
+ Uses the provider module for caching when available.
143
+
117
144
  Args:
118
145
  context: Context name (empty for default)
119
146
 
120
147
  Returns:
121
148
  kubernetes.client.ApiClient configured for the context
149
+
150
+ Raises:
151
+ UnknownContextError: If context is not found (when provider available)
152
+ RuntimeError: If config cannot be loaded
122
153
  """
154
+ # Use provider module if available (provides caching and validation)
155
+ if _HAS_PROVIDER:
156
+ try:
157
+ provider = get_provider()
158
+ return provider.get_api_client(context)
159
+ except UnknownContextError:
160
+ raise
161
+ except Exception as e:
162
+ logger.warning(f"Provider failed, falling back to basic config: {e}")
163
+
164
+ # Fallback to basic config loading
123
165
  from kubernetes import client, config
124
166
  from kubernetes.config.config_exception import ConfigException
125
167
 
@@ -454,6 +496,25 @@ def list_contexts() -> list:
454
496
  Returns:
455
497
  List of context dictionaries with name, cluster, user, namespace
456
498
  """
499
+ # Use provider if available
500
+ if _HAS_PROVIDER:
501
+ try:
502
+ provider = get_provider()
503
+ contexts = provider.list_contexts()
504
+ return [
505
+ {
506
+ "name": ctx.name,
507
+ "cluster": ctx.cluster,
508
+ "user": ctx.user,
509
+ "namespace": ctx.namespace,
510
+ "active": ctx.is_active
511
+ }
512
+ for ctx in contexts
513
+ ]
514
+ except Exception as e:
515
+ logger.warning(f"Provider list_contexts failed: {e}")
516
+
517
+ # Fallback to direct kubeconfig reading
457
518
  from kubernetes import config
458
519
 
459
520
  try:
@@ -484,6 +545,14 @@ def get_active_context() -> Optional[str]:
484
545
  Returns:
485
546
  Active context name or None
486
547
  """
548
+ # Use provider if available
549
+ if _HAS_PROVIDER:
550
+ try:
551
+ return provider_get_current_context()
552
+ except Exception as e:
553
+ logger.warning(f"Provider get_current_context failed: {e}")
554
+
555
+ # Fallback to direct kubeconfig reading
487
556
  from kubernetes import config
488
557
 
489
558
  try:
@@ -528,3 +597,60 @@ def _get_kubectl_context_args(context: str = "") -> list:
528
597
  if context and context.strip():
529
598
  return ["--context", context.strip()]
530
599
  return []
600
+
601
+
602
+ # Re-export provider types for convenience
603
+ if _HAS_PROVIDER:
604
+ __all__ = [
605
+ # Client functions
606
+ "get_k8s_client",
607
+ "get_apps_client",
608
+ "get_rbac_client",
609
+ "get_networking_client",
610
+ "get_storage_client",
611
+ "get_batch_client",
612
+ "get_autoscaling_client",
613
+ "get_policy_client",
614
+ "get_custom_objects_client",
615
+ "get_version_client",
616
+ "get_admissionregistration_client",
617
+ "get_apiextensions_client",
618
+ "get_coordination_client",
619
+ "get_events_client",
620
+ # Config functions
621
+ "load_kubernetes_config",
622
+ "patch_kubernetes_config",
623
+ # Context functions
624
+ "list_contexts",
625
+ "get_active_context",
626
+ "context_exists",
627
+ # Provider types (when available)
628
+ "KubernetesProvider",
629
+ "ProviderConfig",
630
+ "ProviderType",
631
+ "UnknownContextError",
632
+ "get_provider",
633
+ "validate_context",
634
+ ]
635
+ else:
636
+ __all__ = [
637
+ "get_k8s_client",
638
+ "get_apps_client",
639
+ "get_rbac_client",
640
+ "get_networking_client",
641
+ "get_storage_client",
642
+ "get_batch_client",
643
+ "get_autoscaling_client",
644
+ "get_policy_client",
645
+ "get_custom_objects_client",
646
+ "get_version_client",
647
+ "get_admissionregistration_client",
648
+ "get_apiextensions_client",
649
+ "get_coordination_client",
650
+ "get_events_client",
651
+ "load_kubernetes_config",
652
+ "patch_kubernetes_config",
653
+ "list_contexts",
654
+ "get_active_context",
655
+ "context_exists",
656
+ ]
@@ -0,0 +1,347 @@
1
+ import os
2
+ import logging
3
+ from enum import Enum
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+ from dataclasses import dataclass, field
6
+ from functools import lru_cache
7
+
8
+ logger = logging.getLogger("mcp-server")
9
+
10
+
11
+ class ProviderType(Enum):
12
+ """Kubernetes provider types."""
13
+ KUBECONFIG = "kubeconfig"
14
+ IN_CLUSTER = "in-cluster"
15
+ SINGLE = "single"
16
+
17
+
18
+ class UnknownContextError(Exception):
19
+ """Raised when a requested context is not found."""
20
+ def __init__(self, context: str, available: List[str] = None):
21
+ self.context = context
22
+ self.available = available or []
23
+ msg = f"Context '{context}' not found"
24
+ if self.available:
25
+ msg += f". Available contexts: {', '.join(self.available)}"
26
+ super().__init__(msg)
27
+
28
+
29
+ class ProviderError(Exception):
30
+ """Raised when provider configuration is invalid."""
31
+ pass
32
+
33
+
34
+ @dataclass
35
+ class ProviderConfig:
36
+ """Configuration for Kubernetes provider."""
37
+ provider_type: ProviderType = ProviderType.KUBECONFIG
38
+ kubeconfig_path: str = ""
39
+ context: str = ""
40
+ qps: float = 100.0
41
+ burst: int = 200
42
+ timeout: int = 30
43
+
44
+ @classmethod
45
+ def from_env(cls) -> "ProviderConfig":
46
+ """Create config from environment variables."""
47
+ provider_str = os.environ.get("MCP_K8S_PROVIDER", "kubeconfig").lower()
48
+
49
+ try:
50
+ provider_type = ProviderType(provider_str)
51
+ except ValueError:
52
+ logger.warning(f"Unknown provider type '{provider_str}', using kubeconfig")
53
+ provider_type = ProviderType.KUBECONFIG
54
+
55
+ kubeconfig_path = os.environ.get(
56
+ "MCP_K8S_KUBECONFIG",
57
+ os.environ.get("KUBECONFIG", "~/.kube/config")
58
+ )
59
+ kubeconfig_path = os.path.expanduser(kubeconfig_path)
60
+
61
+ return cls(
62
+ provider_type=provider_type,
63
+ kubeconfig_path=kubeconfig_path,
64
+ context=os.environ.get("MCP_K8S_CONTEXT", ""),
65
+ qps=float(os.environ.get("MCP_K8S_QPS", "100")),
66
+ burst=int(os.environ.get("MCP_K8S_BURST", "200")),
67
+ timeout=int(os.environ.get("MCP_K8S_TIMEOUT", "30")),
68
+ )
69
+
70
+
71
+ @dataclass
72
+ class ContextInfo:
73
+ """Information about a kubeconfig context."""
74
+ name: str
75
+ cluster: str
76
+ user: str
77
+ namespace: str = "default"
78
+ is_active: bool = False
79
+
80
+
81
+ class KubernetesProvider:
82
+ """
83
+ Multi-cluster Kubernetes provider.
84
+
85
+ Manages connections to multiple Kubernetes clusters based on
86
+ kubeconfig contexts or in-cluster configuration.
87
+ """
88
+
89
+ _instance: Optional["KubernetesProvider"] = None
90
+
91
+ def __init__(self, config: Optional[ProviderConfig] = None):
92
+ """Initialize provider with configuration."""
93
+ self.config = config or ProviderConfig.from_env()
94
+ self._api_clients: Dict[str, Any] = {}
95
+ self._in_cluster = False
96
+ self._contexts_cache: Optional[List[ContextInfo]] = None
97
+ self._active_context: Optional[str] = None
98
+
99
+ self._initialize()
100
+
101
+ @classmethod
102
+ def get_instance(cls) -> "KubernetesProvider":
103
+ """Get singleton provider instance."""
104
+ if cls._instance is None:
105
+ cls._instance = cls()
106
+ return cls._instance
107
+
108
+ @classmethod
109
+ def reset_instance(cls):
110
+ """Reset singleton instance (for testing)."""
111
+ cls._instance = None
112
+
113
+ def _initialize(self):
114
+ """Initialize the provider based on type."""
115
+ if self.config.provider_type == ProviderType.IN_CLUSTER:
116
+ self._initialize_in_cluster()
117
+ elif self.config.provider_type == ProviderType.SINGLE:
118
+ self._initialize_single()
119
+ else:
120
+ self._initialize_kubeconfig()
121
+
122
+ def _initialize_in_cluster(self):
123
+ """Initialize for in-cluster provider."""
124
+ from kubernetes import config
125
+ from kubernetes.config.config_exception import ConfigException
126
+
127
+ try:
128
+ config.load_incluster_config()
129
+ self._in_cluster = True
130
+ self._active_context = "in-cluster"
131
+ logger.info("Initialized in-cluster Kubernetes provider")
132
+ except ConfigException as e:
133
+ raise ProviderError(f"Failed to load in-cluster config: {e}")
134
+
135
+ def _initialize_single(self):
136
+ """Initialize for single-context provider."""
137
+ if not self.config.context:
138
+ raise ProviderError("MCP_K8S_CONTEXT must be set for 'single' provider")
139
+
140
+ from kubernetes import config
141
+
142
+ try:
143
+ config.load_kube_config(
144
+ config_file=self.config.kubeconfig_path,
145
+ context=self.config.context
146
+ )
147
+ self._active_context = self.config.context
148
+ logger.info(f"Initialized single-context provider: {self.config.context}")
149
+ except Exception as e:
150
+ raise ProviderError(f"Failed to load context '{self.config.context}': {e}")
151
+
152
+ def _initialize_kubeconfig(self):
153
+ """Initialize for multi-cluster kubeconfig provider."""
154
+ from kubernetes import config
155
+
156
+ try:
157
+ contexts, active = config.list_kube_config_contexts(
158
+ config_file=self.config.kubeconfig_path
159
+ )
160
+
161
+ if active:
162
+ self._active_context = active.get("name")
163
+
164
+ self._contexts_cache = [
165
+ ContextInfo(
166
+ name=ctx.get("name", ""),
167
+ cluster=ctx.get("context", {}).get("cluster", ""),
168
+ user=ctx.get("context", {}).get("user", ""),
169
+ namespace=ctx.get("context", {}).get("namespace", "default"),
170
+ is_active=ctx.get("name") == self._active_context
171
+ )
172
+ for ctx in contexts
173
+ ]
174
+
175
+ logger.info(
176
+ f"Initialized kubeconfig provider with {len(self._contexts_cache)} contexts, "
177
+ f"active: {self._active_context}"
178
+ )
179
+ except Exception as e:
180
+ logger.warning(f"Failed to list contexts: {e}")
181
+ self._contexts_cache = []
182
+
183
+ def list_contexts(self) -> List[ContextInfo]:
184
+ """
185
+ List all available contexts.
186
+
187
+ Returns:
188
+ List of ContextInfo objects
189
+ """
190
+ if self._in_cluster:
191
+ return [ContextInfo(
192
+ name="in-cluster",
193
+ cluster="in-cluster",
194
+ user="service-account",
195
+ namespace="default",
196
+ is_active=True
197
+ )]
198
+
199
+ if self.config.provider_type == ProviderType.SINGLE:
200
+ from kubernetes import config
201
+ try:
202
+ contexts, _ = config.list_kube_config_contexts(
203
+ config_file=self.config.kubeconfig_path
204
+ )
205
+ for ctx in contexts:
206
+ if ctx.get("name") == self.config.context:
207
+ return [ContextInfo(
208
+ name=ctx.get("name", ""),
209
+ cluster=ctx.get("context", {}).get("cluster", ""),
210
+ user=ctx.get("context", {}).get("user", ""),
211
+ namespace=ctx.get("context", {}).get("namespace", "default"),
212
+ is_active=True
213
+ )]
214
+ except Exception:
215
+ pass
216
+ return []
217
+
218
+ self._refresh_contexts_cache()
219
+ return self._contexts_cache or []
220
+
221
+ def _refresh_contexts_cache(self):
222
+ """Refresh the contexts cache from kubeconfig."""
223
+ if self._in_cluster or self.config.provider_type == ProviderType.SINGLE:
224
+ return
225
+
226
+ from kubernetes import config
227
+ try:
228
+ contexts, active = config.list_kube_config_contexts(
229
+ config_file=self.config.kubeconfig_path
230
+ )
231
+ self._active_context = active.get("name") if active else None
232
+ self._contexts_cache = [
233
+ ContextInfo(
234
+ name=ctx.get("name", ""),
235
+ cluster=ctx.get("context", {}).get("cluster", ""),
236
+ user=ctx.get("context", {}).get("user", ""),
237
+ namespace=ctx.get("context", {}).get("namespace", "default"),
238
+ is_active=ctx.get("name") == self._active_context
239
+ )
240
+ for ctx in contexts
241
+ ]
242
+ except Exception as e:
243
+ logger.warning(f"Failed to refresh contexts: {e}")
244
+
245
+ def get_current_context(self) -> Optional[str]:
246
+ """Get the current active context name."""
247
+ if self._in_cluster:
248
+ return "in-cluster"
249
+ return self._active_context
250
+
251
+ def _get_context_names(self) -> List[str]:
252
+ """Get list of available context names."""
253
+ contexts = self.list_contexts()
254
+ return [ctx.name for ctx in contexts]
255
+
256
+ def validate_context(self, context: str) -> str:
257
+ """
258
+ Validate and resolve a context name.
259
+
260
+ Args:
261
+ context: Context name (empty string uses default)
262
+
263
+ Returns:
264
+ Resolved context name
265
+
266
+ Raises:
267
+ UnknownContextError: If context is not found
268
+ """
269
+ if self._in_cluster:
270
+ return "in-cluster"
271
+
272
+ if self.config.provider_type == ProviderType.SINGLE:
273
+ if context and context != self.config.context:
274
+ raise UnknownContextError(
275
+ context,
276
+ [self.config.context]
277
+ )
278
+ return self.config.context
279
+
280
+ if not context:
281
+ return self._active_context or ""
282
+
283
+ available = self._get_context_names()
284
+ if context not in available:
285
+ raise UnknownContextError(context, available)
286
+
287
+ return context
288
+
289
+ def get_api_client(self, context: str = "") -> Any:
290
+ """
291
+ Get an API client configuration for a specific context.
292
+
293
+ Args:
294
+ context: Context name (empty uses default)
295
+
296
+ Returns:
297
+ kubernetes.client.ApiClient configured for the context
298
+ """
299
+ from kubernetes import client, config
300
+
301
+ resolved_context = self.validate_context(context)
302
+
303
+ if resolved_context in self._api_clients:
304
+ return self._api_clients[resolved_context]
305
+
306
+ if self._in_cluster:
307
+ api_client = client.ApiClient()
308
+ else:
309
+ api_config = client.Configuration()
310
+ config.load_kube_config(
311
+ config_file=self.config.kubeconfig_path,
312
+ context=resolved_context,
313
+ client_configuration=api_config
314
+ )
315
+ api_client = client.ApiClient(configuration=api_config)
316
+
317
+ self._api_clients[resolved_context] = api_client
318
+
319
+ return api_client
320
+
321
+ def clear_client_cache(self, context: str = ""):
322
+ """Clear cached API client(s)."""
323
+ if context:
324
+ self._api_clients.pop(context, None)
325
+ else:
326
+ self._api_clients.clear()
327
+
328
+
329
+ def get_provider() -> KubernetesProvider:
330
+ """Get the global Kubernetes provider instance."""
331
+ return KubernetesProvider.get_instance()
332
+
333
+
334
+ def get_context_names() -> List[str]:
335
+ """Get list of available context names."""
336
+ provider = get_provider()
337
+ return [ctx.name for ctx in provider.list_contexts()]
338
+
339
+
340
+ def get_current_context() -> Optional[str]:
341
+ """Get the current active context name."""
342
+ return get_provider().get_current_context()
343
+
344
+
345
+ def validate_context(context: str) -> str:
346
+ """Validate and resolve a context name."""
347
+ return get_provider().validate_context(context)
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="kubectl-mcp-server",
8
- version="1.17.0",
8
+ version="1.18.0",
9
9
  author="Rohit Ghumare",
10
10
  author_email="ghumare64@gmail.com",
11
11
  description="A Model Context Protocol (MCP) server for Kubernetes with 220+ tools, 8 resources, and 8 prompts",