kubectl-mcp-server 1.15.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.
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/METADATA +34 -13
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/RECORD +24 -12
- kubectl_mcp_tool/__init__.py +1 -1
- kubectl_mcp_tool/crd_detector.py +247 -0
- kubectl_mcp_tool/k8s_config.py +19 -0
- kubectl_mcp_tool/mcp_server.py +27 -0
- kubectl_mcp_tool/tools/__init__.py +20 -0
- kubectl_mcp_tool/tools/backup.py +881 -0
- kubectl_mcp_tool/tools/capi.py +727 -0
- kubectl_mcp_tool/tools/certs.py +709 -0
- kubectl_mcp_tool/tools/cilium.py +582 -0
- kubectl_mcp_tool/tools/gitops.py +552 -0
- kubectl_mcp_tool/tools/keda.py +464 -0
- kubectl_mcp_tool/tools/kiali.py +652 -0
- kubectl_mcp_tool/tools/kubevirt.py +803 -0
- kubectl_mcp_tool/tools/policy.py +554 -0
- kubectl_mcp_tool/tools/rollouts.py +790 -0
- tests/test_browser.py +2 -2
- tests/test_ecosystem.py +331 -0
- tests/test_tools.py +70 -8
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/WHEEL +0 -0
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/entry_points.txt +0 -0
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/licenses/LICENSE +0 -0
- {kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/top_level.txt +0 -0
tests/test_browser.py
CHANGED
|
@@ -501,11 +501,11 @@ class TestServerIntegration:
|
|
|
501
501
|
tools = asyncio.run(server.server.list_tools())
|
|
502
502
|
tool_names = [t.name for t in tools]
|
|
503
503
|
|
|
504
|
-
# Should have browser tools (
|
|
504
|
+
# Should have browser tools (224 + 26 = 250)
|
|
505
505
|
assert "browser_open" in tool_names
|
|
506
506
|
assert "browser_screenshot" in tool_names
|
|
507
507
|
assert "browser_connect_cdp" in tool_names # v0.7 tool
|
|
508
|
-
assert len(tools) ==
|
|
508
|
+
assert len(tools) == 250, f"Expected 250 tools (224 + 26), got {len(tools)}"
|
|
509
509
|
|
|
510
510
|
|
|
511
511
|
import asyncio
|
tests/test_ecosystem.py
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Unit tests for ecosystem tools (GitOps, Cert-Manager, Policy, Backup).
|
|
3
|
+
|
|
4
|
+
This module tests the CRD detector and all ecosystem toolsets.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from unittest.mock import patch, MagicMock
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class TestCRDDetector:
|
|
13
|
+
"""Tests for the CRD auto-discovery framework."""
|
|
14
|
+
|
|
15
|
+
@pytest.mark.unit
|
|
16
|
+
def test_crd_detector_imports(self):
|
|
17
|
+
"""Test that CRD detector module can be imported."""
|
|
18
|
+
from kubectl_mcp_tool.crd_detector import (
|
|
19
|
+
CRD_GROUPS,
|
|
20
|
+
detect_crds,
|
|
21
|
+
crd_exists,
|
|
22
|
+
get_enabled_toolsets,
|
|
23
|
+
get_crd_status_summary,
|
|
24
|
+
FeatureNotInstalledError,
|
|
25
|
+
require_crd,
|
|
26
|
+
require_any_crd,
|
|
27
|
+
)
|
|
28
|
+
assert CRD_GROUPS is not None
|
|
29
|
+
assert callable(detect_crds)
|
|
30
|
+
assert callable(crd_exists)
|
|
31
|
+
assert callable(get_enabled_toolsets)
|
|
32
|
+
assert callable(get_crd_status_summary)
|
|
33
|
+
assert issubclass(FeatureNotInstalledError, Exception)
|
|
34
|
+
assert callable(require_crd)
|
|
35
|
+
assert callable(require_any_crd)
|
|
36
|
+
|
|
37
|
+
@pytest.mark.unit
|
|
38
|
+
def test_crd_groups_structure(self):
|
|
39
|
+
"""Test that CRD_GROUPS has expected structure."""
|
|
40
|
+
from kubectl_mcp_tool.crd_detector import CRD_GROUPS
|
|
41
|
+
|
|
42
|
+
expected_groups = ["flux", "argocd", "certmanager", "kyverno", "gatekeeper", "velero"]
|
|
43
|
+
for group in expected_groups:
|
|
44
|
+
assert group in CRD_GROUPS, f"Expected group '{group}' in CRD_GROUPS"
|
|
45
|
+
assert isinstance(CRD_GROUPS[group], list), f"CRD_GROUPS['{group}'] should be a list"
|
|
46
|
+
assert len(CRD_GROUPS[group]) > 0, f"CRD_GROUPS['{group}'] should not be empty"
|
|
47
|
+
|
|
48
|
+
@pytest.mark.unit
|
|
49
|
+
def test_detect_crds_with_mocked_kubectl(self):
|
|
50
|
+
"""Test CRD detection with mocked kubectl."""
|
|
51
|
+
from kubectl_mcp_tool.crd_detector import detect_crds, _crd_cache
|
|
52
|
+
|
|
53
|
+
# Clear cache before test
|
|
54
|
+
_crd_cache.clear()
|
|
55
|
+
|
|
56
|
+
mock_output = """NAME CREATED AT
|
|
57
|
+
applications.argoproj.io 2024-01-01T00:00:00Z
|
|
58
|
+
certificates.cert-manager.io 2024-01-01T00:00:00Z
|
|
59
|
+
"""
|
|
60
|
+
with patch("subprocess.run") as mock_run:
|
|
61
|
+
mock_run.return_value = MagicMock(
|
|
62
|
+
returncode=0,
|
|
63
|
+
stdout=mock_output
|
|
64
|
+
)
|
|
65
|
+
result = detect_crds(force_refresh=True)
|
|
66
|
+
|
|
67
|
+
assert isinstance(result, dict)
|
|
68
|
+
assert "argocd" in result
|
|
69
|
+
assert "certmanager" in result
|
|
70
|
+
|
|
71
|
+
@pytest.mark.unit
|
|
72
|
+
def test_detect_crds_handles_kubectl_failure(self):
|
|
73
|
+
"""Test CRD detection handles kubectl failure gracefully."""
|
|
74
|
+
from kubectl_mcp_tool.crd_detector import detect_crds, _crd_cache
|
|
75
|
+
|
|
76
|
+
_crd_cache.clear()
|
|
77
|
+
|
|
78
|
+
with patch("subprocess.run") as mock_run:
|
|
79
|
+
mock_run.side_effect = subprocess.SubprocessError("Command failed")
|
|
80
|
+
result = detect_crds(force_refresh=True)
|
|
81
|
+
|
|
82
|
+
assert isinstance(result, dict)
|
|
83
|
+
# All groups should be False when kubectl fails
|
|
84
|
+
for value in result.values():
|
|
85
|
+
assert value is False
|
|
86
|
+
|
|
87
|
+
@pytest.mark.unit
|
|
88
|
+
def test_feature_not_installed_error(self):
|
|
89
|
+
"""Test FeatureNotInstalledError exception."""
|
|
90
|
+
from kubectl_mcp_tool.crd_detector import FeatureNotInstalledError
|
|
91
|
+
|
|
92
|
+
error = FeatureNotInstalledError("velero", ["backups.velero.io"])
|
|
93
|
+
assert "velero" in str(error)
|
|
94
|
+
assert "backups.velero.io" in str(error)
|
|
95
|
+
assert error.toolset == "velero"
|
|
96
|
+
assert "backups.velero.io" in error.required_crds
|
|
97
|
+
|
|
98
|
+
@pytest.mark.unit
|
|
99
|
+
def test_get_crd_status_summary(self):
|
|
100
|
+
"""Test CRD status summary generation."""
|
|
101
|
+
from kubectl_mcp_tool.crd_detector import get_crd_status_summary, _crd_cache
|
|
102
|
+
|
|
103
|
+
_crd_cache.clear()
|
|
104
|
+
|
|
105
|
+
with patch("subprocess.run") as mock_run:
|
|
106
|
+
mock_run.return_value = MagicMock(
|
|
107
|
+
returncode=0,
|
|
108
|
+
stdout="applications.argoproj.io 2024-01-01T00:00:00Z\n"
|
|
109
|
+
)
|
|
110
|
+
summary = get_crd_status_summary()
|
|
111
|
+
|
|
112
|
+
# Summary returns a dict with crd_groups and enabled_toolsets
|
|
113
|
+
assert isinstance(summary, dict)
|
|
114
|
+
assert "crd_groups" in summary
|
|
115
|
+
assert "enabled_toolsets" in summary
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class TestGitOpsTools:
|
|
119
|
+
"""Tests for GitOps toolset (Flux and ArgoCD)."""
|
|
120
|
+
|
|
121
|
+
@pytest.mark.unit
|
|
122
|
+
def test_gitops_tools_import(self):
|
|
123
|
+
"""Test that GitOps tools can be imported."""
|
|
124
|
+
from kubectl_mcp_tool.tools.gitops import register_gitops_tools
|
|
125
|
+
assert callable(register_gitops_tools)
|
|
126
|
+
|
|
127
|
+
@pytest.mark.unit
|
|
128
|
+
def test_gitops_tools_register(self, mock_all_kubernetes_apis):
|
|
129
|
+
"""Test that GitOps tools register correctly."""
|
|
130
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
131
|
+
import asyncio
|
|
132
|
+
|
|
133
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
134
|
+
server = MCPServer(name="test")
|
|
135
|
+
|
|
136
|
+
async def get_tools():
|
|
137
|
+
return await server.server.list_tools()
|
|
138
|
+
|
|
139
|
+
tools = asyncio.run(get_tools())
|
|
140
|
+
tool_names = {t.name for t in tools}
|
|
141
|
+
|
|
142
|
+
gitops_tools = [
|
|
143
|
+
"gitops_apps_list_tool", "gitops_app_get_tool", "gitops_app_sync_tool",
|
|
144
|
+
"gitops_app_status_tool", "gitops_sources_list_tool", "gitops_source_get_tool",
|
|
145
|
+
"gitops_detect_engine_tool"
|
|
146
|
+
]
|
|
147
|
+
for tool in gitops_tools:
|
|
148
|
+
assert tool in tool_names, f"GitOps tool '{tool}' not registered"
|
|
149
|
+
|
|
150
|
+
@pytest.mark.unit
|
|
151
|
+
def test_gitops_non_destructive_mode(self, mock_all_kubernetes_apis):
|
|
152
|
+
"""Test that GitOps sync is blocked in non-destructive mode."""
|
|
153
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
154
|
+
|
|
155
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
156
|
+
server = MCPServer(name="test", non_destructive=True)
|
|
157
|
+
|
|
158
|
+
# Server should initialize with non_destructive=True
|
|
159
|
+
assert server.non_destructive is True
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
class TestCertManagerTools:
|
|
163
|
+
"""Tests for Cert-Manager toolset."""
|
|
164
|
+
|
|
165
|
+
@pytest.mark.unit
|
|
166
|
+
def test_certs_tools_import(self):
|
|
167
|
+
"""Test that Cert-Manager tools can be imported."""
|
|
168
|
+
from kubectl_mcp_tool.tools.certs import register_certs_tools
|
|
169
|
+
assert callable(register_certs_tools)
|
|
170
|
+
|
|
171
|
+
@pytest.mark.unit
|
|
172
|
+
def test_certs_tools_register(self, mock_all_kubernetes_apis):
|
|
173
|
+
"""Test that Cert-Manager tools register correctly."""
|
|
174
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
175
|
+
import asyncio
|
|
176
|
+
|
|
177
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
178
|
+
server = MCPServer(name="test")
|
|
179
|
+
|
|
180
|
+
async def get_tools():
|
|
181
|
+
return await server.server.list_tools()
|
|
182
|
+
|
|
183
|
+
tools = asyncio.run(get_tools())
|
|
184
|
+
tool_names = {t.name for t in tools}
|
|
185
|
+
|
|
186
|
+
certs_tools = [
|
|
187
|
+
"certs_list_tool", "certs_get_tool", "certs_issuers_list_tool", "certs_issuer_get_tool",
|
|
188
|
+
"certs_renew_tool", "certs_status_explain_tool", "certs_challenges_list_tool",
|
|
189
|
+
"certs_requests_list_tool", "certs_detect_tool"
|
|
190
|
+
]
|
|
191
|
+
for tool in certs_tools:
|
|
192
|
+
assert tool in tool_names, f"Cert-Manager tool '{tool}' not registered"
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class TestPolicyTools:
|
|
196
|
+
"""Tests for Policy toolset (Kyverno and Gatekeeper)."""
|
|
197
|
+
|
|
198
|
+
@pytest.mark.unit
|
|
199
|
+
def test_policy_tools_import(self):
|
|
200
|
+
"""Test that Policy tools can be imported."""
|
|
201
|
+
from kubectl_mcp_tool.tools.policy import register_policy_tools
|
|
202
|
+
assert callable(register_policy_tools)
|
|
203
|
+
|
|
204
|
+
@pytest.mark.unit
|
|
205
|
+
def test_policy_tools_register(self, mock_all_kubernetes_apis):
|
|
206
|
+
"""Test that Policy tools register correctly."""
|
|
207
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
208
|
+
import asyncio
|
|
209
|
+
|
|
210
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
211
|
+
server = MCPServer(name="test")
|
|
212
|
+
|
|
213
|
+
async def get_tools():
|
|
214
|
+
return await server.server.list_tools()
|
|
215
|
+
|
|
216
|
+
tools = asyncio.run(get_tools())
|
|
217
|
+
tool_names = {t.name for t in tools}
|
|
218
|
+
|
|
219
|
+
policy_tools = [
|
|
220
|
+
"policy_list_tool", "policy_get_tool", "policy_violations_list_tool",
|
|
221
|
+
"policy_explain_denial_tool", "policy_audit_tool", "policy_detect_tool"
|
|
222
|
+
]
|
|
223
|
+
for tool in policy_tools:
|
|
224
|
+
assert tool in tool_names, f"Policy tool '{tool}' not registered"
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class TestBackupTools:
|
|
228
|
+
"""Tests for Backup toolset (Velero)."""
|
|
229
|
+
|
|
230
|
+
@pytest.mark.unit
|
|
231
|
+
def test_backup_tools_import(self):
|
|
232
|
+
"""Test that Backup tools can be imported."""
|
|
233
|
+
from kubectl_mcp_tool.tools.backup import register_backup_tools
|
|
234
|
+
assert callable(register_backup_tools)
|
|
235
|
+
|
|
236
|
+
@pytest.mark.unit
|
|
237
|
+
def test_backup_tools_register(self, mock_all_kubernetes_apis):
|
|
238
|
+
"""Test that Backup tools register correctly."""
|
|
239
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
240
|
+
import asyncio
|
|
241
|
+
|
|
242
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
243
|
+
server = MCPServer(name="test")
|
|
244
|
+
|
|
245
|
+
async def get_tools():
|
|
246
|
+
return await server.server.list_tools()
|
|
247
|
+
|
|
248
|
+
tools = asyncio.run(get_tools())
|
|
249
|
+
tool_names = {t.name for t in tools}
|
|
250
|
+
|
|
251
|
+
backup_tools = [
|
|
252
|
+
"backup_list_tool", "backup_get_tool", "backup_create_tool", "backup_delete_tool",
|
|
253
|
+
"restore_list_tool", "restore_create_tool", "restore_get_tool",
|
|
254
|
+
"backup_locations_list_tool", "backup_schedules_list_tool",
|
|
255
|
+
"backup_schedule_create_tool", "backup_detect_tool"
|
|
256
|
+
]
|
|
257
|
+
for tool in backup_tools:
|
|
258
|
+
assert tool in tool_names, f"Backup tool '{tool}' not registered"
|
|
259
|
+
|
|
260
|
+
@pytest.mark.unit
|
|
261
|
+
def test_backup_non_destructive_mode(self, mock_all_kubernetes_apis):
|
|
262
|
+
"""Test that backup operations are blocked in non-destructive mode."""
|
|
263
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
264
|
+
|
|
265
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
266
|
+
server = MCPServer(name="test", non_destructive=True)
|
|
267
|
+
|
|
268
|
+
# Server should initialize with non_destructive=True
|
|
269
|
+
assert server.non_destructive is True
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
class TestEcosystemToolsIntegration:
|
|
273
|
+
"""Integration tests for ecosystem tools."""
|
|
274
|
+
|
|
275
|
+
@pytest.mark.unit
|
|
276
|
+
def test_all_ecosystem_tools_have_descriptions(self, mock_all_kubernetes_apis):
|
|
277
|
+
"""Test that all ecosystem tools have descriptions."""
|
|
278
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
279
|
+
import asyncio
|
|
280
|
+
|
|
281
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
282
|
+
server = MCPServer(name="test")
|
|
283
|
+
|
|
284
|
+
async def get_tools():
|
|
285
|
+
return await server.server.list_tools()
|
|
286
|
+
|
|
287
|
+
tools = asyncio.run(get_tools())
|
|
288
|
+
|
|
289
|
+
ecosystem_prefixes = ["gitops_", "certs_", "policy_", "backup_", "restore_"]
|
|
290
|
+
ecosystem_tools = [t for t in tools if any(t.name.startswith(p) for p in ecosystem_prefixes)]
|
|
291
|
+
|
|
292
|
+
tools_without_description = [
|
|
293
|
+
t.name for t in ecosystem_tools
|
|
294
|
+
if not t.description or len(t.description.strip()) == 0
|
|
295
|
+
]
|
|
296
|
+
assert not tools_without_description, f"Ecosystem tools without descriptions: {tools_without_description}"
|
|
297
|
+
|
|
298
|
+
@pytest.mark.unit
|
|
299
|
+
def test_ecosystem_tool_count(self, mock_all_kubernetes_apis):
|
|
300
|
+
"""Test that correct number of ecosystem tools are registered."""
|
|
301
|
+
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
302
|
+
import asyncio
|
|
303
|
+
|
|
304
|
+
with patch("kubectl_mcp_tool.mcp_server.MCPServer._check_dependencies", return_value=True):
|
|
305
|
+
server = MCPServer(name="test")
|
|
306
|
+
|
|
307
|
+
async def get_tools():
|
|
308
|
+
return await server.server.list_tools()
|
|
309
|
+
|
|
310
|
+
tools = asyncio.run(get_tools())
|
|
311
|
+
|
|
312
|
+
# Filter ecosystem tools, but exclude backup_resource which is in operations.py
|
|
313
|
+
ecosystem_tool_names = [
|
|
314
|
+
"gitops_apps_list_tool", "gitops_app_get_tool", "gitops_app_sync_tool",
|
|
315
|
+
"gitops_app_status_tool", "gitops_sources_list_tool", "gitops_source_get_tool",
|
|
316
|
+
"gitops_detect_engine_tool",
|
|
317
|
+
"certs_list_tool", "certs_get_tool", "certs_issuers_list_tool", "certs_issuer_get_tool",
|
|
318
|
+
"certs_renew_tool", "certs_status_explain_tool", "certs_challenges_list_tool",
|
|
319
|
+
"certs_requests_list_tool", "certs_detect_tool",
|
|
320
|
+
"policy_list_tool", "policy_get_tool", "policy_violations_list_tool",
|
|
321
|
+
"policy_explain_denial_tool", "policy_audit_tool", "policy_detect_tool",
|
|
322
|
+
"backup_list_tool", "backup_get_tool", "backup_create_tool", "backup_delete_tool",
|
|
323
|
+
"restore_list_tool", "restore_create_tool", "restore_get_tool",
|
|
324
|
+
"backup_locations_list_tool", "backup_schedules_list_tool",
|
|
325
|
+
"backup_schedule_create_tool", "backup_detect_tool"
|
|
326
|
+
]
|
|
327
|
+
tool_names = {t.name for t in tools}
|
|
328
|
+
ecosystem_tools = [name for name in ecosystem_tool_names if name in tool_names]
|
|
329
|
+
|
|
330
|
+
# 7 GitOps + 9 Certs + 6 Policy + 11 Backup = 33 ecosystem tools
|
|
331
|
+
assert len(ecosystem_tools) == 33, f"Expected 33 ecosystem tools, got {len(ecosystem_tools)}"
|
tests/test_tools.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Unit tests for all MCP tools in kubectl-mcp-server.
|
|
3
3
|
|
|
4
|
-
This module contains comprehensive tests for all
|
|
5
|
-
provided by the MCP server (
|
|
4
|
+
This module contains comprehensive tests for all Kubernetes tools
|
|
5
|
+
provided by the MCP server (224 total with ecosystem tools).
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import pytest
|
|
@@ -12,7 +12,7 @@ from unittest.mock import patch, MagicMock
|
|
|
12
12
|
from datetime import datetime
|
|
13
13
|
|
|
14
14
|
|
|
15
|
-
# Complete list of all
|
|
15
|
+
# Complete list of all 224 tools that must be registered (125 core + 6 UI + 93 ecosystem)
|
|
16
16
|
EXPECTED_TOOLS = [
|
|
17
17
|
# Pods (pods.py)
|
|
18
18
|
"get_pods", "get_logs", "get_pod_events", "check_pod_health", "exec_in_pod",
|
|
@@ -65,15 +65,55 @@ EXPECTED_TOOLS = [
|
|
|
65
65
|
# UI tools (ui.py) - 6 tools for MCP-UI interactive dashboards
|
|
66
66
|
"show_pod_logs_ui", "show_pods_dashboard_ui", "show_resource_yaml_ui",
|
|
67
67
|
"show_cluster_overview_ui", "show_events_timeline_ui", "render_k8s_dashboard_screenshot",
|
|
68
|
+
# GitOps tools (gitops.py) - 7 tools for Flux and ArgoCD
|
|
69
|
+
"gitops_apps_list_tool", "gitops_app_get_tool", "gitops_app_sync_tool", "gitops_app_status_tool",
|
|
70
|
+
"gitops_sources_list_tool", "gitops_source_get_tool", "gitops_detect_engine_tool",
|
|
71
|
+
# Cert-Manager tools (certs.py) - 9 tools
|
|
72
|
+
"certs_list_tool", "certs_get_tool", "certs_issuers_list_tool", "certs_issuer_get_tool",
|
|
73
|
+
"certs_renew_tool", "certs_status_explain_tool", "certs_challenges_list_tool",
|
|
74
|
+
"certs_requests_list_tool", "certs_detect_tool",
|
|
75
|
+
# Policy tools (policy.py) - 6 tools for Kyverno and Gatekeeper
|
|
76
|
+
"policy_list_tool", "policy_get_tool", "policy_violations_list_tool", "policy_explain_denial_tool",
|
|
77
|
+
"policy_audit_tool", "policy_detect_tool",
|
|
78
|
+
# Backup tools (backup.py) - 11 tools for Velero
|
|
79
|
+
"backup_list_tool", "backup_get_tool", "backup_create_tool", "backup_delete_tool",
|
|
80
|
+
"restore_list_tool", "restore_create_tool", "restore_get_tool", "backup_locations_list_tool",
|
|
81
|
+
"backup_schedules_list_tool", "backup_schedule_create_tool", "backup_detect_tool",
|
|
82
|
+
# KEDA tools (keda.py) - 7 tools for autoscaling
|
|
83
|
+
"keda_scaledobjects_list_tool", "keda_scaledobject_get_tool", "keda_scaledjobs_list_tool",
|
|
84
|
+
"keda_triggerauths_list_tool", "keda_triggerauth_get_tool", "keda_hpa_list_tool", "keda_detect_tool",
|
|
85
|
+
# Cilium tools (cilium.py) - 8 tools for network observability
|
|
86
|
+
"cilium_policies_list_tool", "cilium_policy_get_tool", "cilium_endpoints_list_tool",
|
|
87
|
+
"cilium_identities_list_tool", "cilium_nodes_list_tool", "cilium_status_tool",
|
|
88
|
+
"hubble_flows_query_tool", "cilium_detect_tool",
|
|
89
|
+
# Rollouts tools (rollouts.py) - 11 tools for progressive delivery
|
|
90
|
+
"rollouts_list_tool", "rollout_get_tool", "rollout_status_tool", "rollout_promote_tool",
|
|
91
|
+
"rollout_abort_tool", "rollout_retry_tool", "rollout_restart_tool", "analysis_runs_list_tool",
|
|
92
|
+
"flagger_canaries_list_tool", "flagger_canary_get_tool", "rollouts_detect_tool",
|
|
93
|
+
# Cluster API tools (capi.py) - 11 tools for cluster lifecycle
|
|
94
|
+
"capi_clusters_list_tool", "capi_cluster_get_tool", "capi_machines_list_tool",
|
|
95
|
+
"capi_machine_get_tool", "capi_machinedeployments_list_tool", "capi_machinedeployment_scale_tool",
|
|
96
|
+
"capi_machinesets_list_tool", "capi_machinehealthchecks_list_tool", "capi_clusterclasses_list_tool",
|
|
97
|
+
"capi_cluster_kubeconfig_tool", "capi_detect_tool",
|
|
98
|
+
# KubeVirt tools (kubevirt.py) - 13 tools for VM management
|
|
99
|
+
"kubevirt_vms_list_tool", "kubevirt_vm_get_tool", "kubevirt_vmis_list_tool",
|
|
100
|
+
"kubevirt_vm_start_tool", "kubevirt_vm_stop_tool", "kubevirt_vm_restart_tool",
|
|
101
|
+
"kubevirt_vm_pause_tool", "kubevirt_vm_unpause_tool", "kubevirt_vm_migrate_tool",
|
|
102
|
+
"kubevirt_datasources_list_tool", "kubevirt_instancetypes_list_tool",
|
|
103
|
+
"kubevirt_datavolumes_list_tool", "kubevirt_detect_tool",
|
|
104
|
+
# Istio/Kiali tools (kiali.py) - 10 tools for service mesh
|
|
105
|
+
"istio_virtualservices_list_tool", "istio_virtualservice_get_tool", "istio_destinationrules_list_tool",
|
|
106
|
+
"istio_gateways_list_tool", "istio_peerauthentications_list_tool", "istio_authorizationpolicies_list_tool",
|
|
107
|
+
"istio_proxy_status_tool", "istio_analyze_tool", "istio_sidecar_status_tool", "istio_detect_tool",
|
|
68
108
|
]
|
|
69
109
|
|
|
70
110
|
|
|
71
111
|
class TestAllToolsRegistered:
|
|
72
|
-
"""Comprehensive tests to verify all
|
|
112
|
+
"""Comprehensive tests to verify all 224 tools are registered (125 core + 6 UI + 93 ecosystem)."""
|
|
73
113
|
|
|
74
114
|
@pytest.mark.unit
|
|
75
|
-
def
|
|
76
|
-
"""Verify all
|
|
115
|
+
def test_all_164_tools_registered(self):
|
|
116
|
+
"""Verify all 224 expected tools are registered (excluding optional browser tools)."""
|
|
77
117
|
import os
|
|
78
118
|
from kubectl_mcp_tool.mcp_server import MCPServer
|
|
79
119
|
|
|
@@ -94,8 +134,8 @@ class TestAllToolsRegistered:
|
|
|
94
134
|
tools = asyncio.run(get_tools())
|
|
95
135
|
tool_names = {t.name for t in tools}
|
|
96
136
|
|
|
97
|
-
# Verify count (
|
|
98
|
-
assert len(tools) ==
|
|
137
|
+
# Verify count (224 tools = 125 core + 6 UI + 93 ecosystem, browser tools disabled)
|
|
138
|
+
assert len(tools) == 224, f"Expected 224 tools, got {len(tools)}"
|
|
99
139
|
|
|
100
140
|
# Check for missing tools
|
|
101
141
|
missing_tools = set(EXPECTED_TOOLS) - tool_names
|
|
@@ -120,6 +160,16 @@ class TestAllToolsRegistered:
|
|
|
120
160
|
register_operations_tools,
|
|
121
161
|
register_diagnostics_tools,
|
|
122
162
|
register_cost_tools,
|
|
163
|
+
register_gitops_tools,
|
|
164
|
+
register_certs_tools,
|
|
165
|
+
register_policy_tools,
|
|
166
|
+
register_backup_tools,
|
|
167
|
+
register_keda_tools,
|
|
168
|
+
register_cilium_tools,
|
|
169
|
+
register_rollouts_tools,
|
|
170
|
+
register_capi_tools,
|
|
171
|
+
register_kubevirt_tools,
|
|
172
|
+
register_istio_tools,
|
|
123
173
|
)
|
|
124
174
|
# All imports should succeed
|
|
125
175
|
assert callable(register_helm_tools)
|
|
@@ -133,6 +183,18 @@ class TestAllToolsRegistered:
|
|
|
133
183
|
assert callable(register_operations_tools)
|
|
134
184
|
assert callable(register_diagnostics_tools)
|
|
135
185
|
assert callable(register_cost_tools)
|
|
186
|
+
# Ecosystem tools
|
|
187
|
+
assert callable(register_gitops_tools)
|
|
188
|
+
assert callable(register_certs_tools)
|
|
189
|
+
assert callable(register_policy_tools)
|
|
190
|
+
assert callable(register_backup_tools)
|
|
191
|
+
# Advanced ecosystem tools
|
|
192
|
+
assert callable(register_keda_tools)
|
|
193
|
+
assert callable(register_cilium_tools)
|
|
194
|
+
assert callable(register_rollouts_tools)
|
|
195
|
+
assert callable(register_capi_tools)
|
|
196
|
+
assert callable(register_kubevirt_tools)
|
|
197
|
+
assert callable(register_istio_tools)
|
|
136
198
|
|
|
137
199
|
@pytest.mark.unit
|
|
138
200
|
def test_all_tools_have_descriptions(self):
|
|
File without changes
|
{kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/entry_points.txt
RENAMED
|
File without changes
|
{kubectl_mcp_server-1.15.0.dist-info → kubectl_mcp_server-1.16.0.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|
|
File without changes
|