From fa3545c218e1fd87b60353b69d3ca7d530ab143a Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Sun, 27 Jul 2025 23:54:51 +0200 Subject: [PATCH 1/3] set json format optional Signed-off-by: Dmytro Rashko --- .gitignore | 1 + Makefile | 2 +- internal/commands/builder.go | 6 +++--- internal/commands/builder_test.go | 6 +++--- pkg/k8s/k8s.go | 2 +- pkg/k8s/k8s_test.go | 8 +++++--- test/e2e/cli_test.go | 2 +- 7 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 6bd4b64..4b3d33a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ bin/ *.html /helm/kagent-tools/Chart.yaml /reports/tools-cve.csv +.dagger/ diff --git a/Makefile b/Makefile index 8f9fcf9..f16920f 100644 --- a/Makefile +++ b/Makefile @@ -138,7 +138,7 @@ DOCKER_BUILD_ARGS ?= --pull --load --platform linux/$(LOCALARCH) --builder $(BUI # tools image build args TOOLS_ISTIO_VERSION ?= 1.26.2 TOOLS_ARGO_ROLLOUTS_VERSION ?= 1.8.3 -TOOLS_KUBECTL_VERSION ?= 1.33.2 +TOOLS_KUBECTL_VERSION ?= 1.33.3 TOOLS_HELM_VERSION ?= 3.18.4 TOOLS_CILIUM_VERSION ?= 0.18.5 diff --git a/internal/commands/builder.go b/internal/commands/builder.go index e0ec477..3bced94 100644 --- a/internal/commands/builder.go +++ b/internal/commands/builder.go @@ -445,7 +445,7 @@ func GetPods(namespace string, labels map[string]string) *CommandBuilder { builder = builder.WithLabels(labels) } - return builder.WithCache(true).WithOutput("json") + return builder.WithCache(true) } // GetServices creates a command to get services @@ -460,7 +460,7 @@ func GetServices(namespace string, labels map[string]string) *CommandBuilder { builder = builder.WithLabels(labels) } - return builder.WithCache(true).WithOutput("json") + return builder.WithCache(true) } // GetDeployments creates a command to get deployments @@ -475,7 +475,7 @@ func GetDeployments(namespace string, labels map[string]string) *CommandBuilder builder = builder.WithLabels(labels) } - return builder.WithCache(true).WithOutput("json") + return builder.WithCache(true) } // DescribeResource creates a command to describe a resource diff --git a/internal/commands/builder_test.go b/internal/commands/builder_test.go index 377afeb..f8a98fc 100644 --- a/internal/commands/builder_test.go +++ b/internal/commands/builder_test.go @@ -253,7 +253,7 @@ func TestGetPods(t *testing.T) { assert.Equal(t, namespace, cb.namespace) assert.Equal(t, labels, cb.labels) assert.True(t, cb.cached) - assert.Equal(t, "json", cb.output) + assert.Empty(t, cb.output) // No default output format } func TestGetServices(t *testing.T) { @@ -268,7 +268,7 @@ func TestGetServices(t *testing.T) { assert.Equal(t, namespace, cb.namespace) assert.Equal(t, labels, cb.labels) assert.True(t, cb.cached) - assert.Equal(t, "json", cb.output) + assert.Empty(t, cb.output) // No default output format } func TestGetDeployments(t *testing.T) { @@ -283,7 +283,7 @@ func TestGetDeployments(t *testing.T) { assert.Equal(t, namespace, cb.namespace) assert.Equal(t, labels, cb.labels) assert.True(t, cb.cached) - assert.Equal(t, "json", cb.output) + assert.Empty(t, cb.output) // No default output format } func TestDescribeResource(t *testing.T) { diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go index e474df6..59f0949 100644 --- a/pkg/k8s/k8s.go +++ b/pkg/k8s/k8s.go @@ -292,7 +292,7 @@ func (k *K8sTool) handleExecCommand(ctx context.Context, request mcp.CallToolReq // Get available API resources func (k *K8sTool) handleGetAvailableAPIResources(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { - return k.runKubectlCommand(ctx, "api-resources", "-o", "json") + return k.runKubectlCommand(ctx, "api-resources") } // Kubectl describe tool diff --git a/pkg/k8s/k8s_test.go b/pkg/k8s/k8s_test.go index f3c53c4..f853302 100644 --- a/pkg/k8s/k8s_test.go +++ b/pkg/k8s/k8s_test.go @@ -37,8 +37,10 @@ func TestHandleGetAvailableAPIResources(t *testing.T) { t.Run("success", func(t *testing.T) { mock := cmd.NewMockShellExecutor() - expectedOutput := `[{"name": "pods", "singularName": "pod", "namespaced": true, "kind": "Pod"}]` - mock.AddCommandString("kubectl", []string{"api-resources", "-o", "json"}, expectedOutput, nil) + expectedOutput := `NAME SHORTNAMES APIVERSION NAMESPACED KIND +pods po v1 true Pod +services svc v1 true Service` + mock.AddCommandString("kubectl", []string{"api-resources"}, expectedOutput, nil) ctx := cmd.WithShellExecutor(ctx, mock) k8sTool := newTestK8sTool() @@ -56,7 +58,7 @@ func TestHandleGetAvailableAPIResources(t *testing.T) { t.Run("kubectl command failure", func(t *testing.T) { mock := cmd.NewMockShellExecutor() - mock.AddCommandString("kubectl", []string{"api-resources", "-o", "json"}, "", assert.AnError) + mock.AddCommandString("kubectl", []string{"api-resources"}, "", assert.AnError) ctx := cmd.WithShellExecutor(ctx, mock) k8sTool := newTestK8sTool() diff --git a/test/e2e/cli_test.go b/test/e2e/cli_test.go index 61285b0..73df2a8 100644 --- a/test/e2e/cli_test.go +++ b/test/e2e/cli_test.go @@ -44,7 +44,7 @@ var _ = Describe("KAgent Tools E2E Tests", func() { config := TestServerConfig{ Port: 8085, Stdio: false, - Timeout: 30 * time.Second, + Timeout: 60 * time.Second, } server := NewTestServer(config) From 40ea320d4d479dcd99f6824605a692c76076716d Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Mon, 28 Jul 2025 12:37:10 +0200 Subject: [PATCH 2/3] set json format optional Signed-off-by: Dmytro Rashko --- pkg/k8s/k8s.go | 4 ++-- pkg/k8s/k8s_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go index 59f0949..c8e9085 100644 --- a/pkg/k8s/k8s.go +++ b/pkg/k8s/k8s.go @@ -58,7 +58,7 @@ func (k *K8sTool) handleKubectlGetEnhanced(ctx context.Context, request mcp.Call resourceName := mcp.ParseString(request, "resource_name", "") namespace := mcp.ParseString(request, "namespace", "") allNamespaces := mcp.ParseString(request, "all_namespaces", "") == "true" - output := mcp.ParseString(request, "output", "json") + output := mcp.ParseString(request, "output", "wide") if resourceType == "" { return mcp.NewToolResultError("resource_type parameter is required"), nil @@ -567,7 +567,7 @@ func RegisterTools(s *server.MCPServer, llm llms.Model, kubeconfig string) { mcp.WithString("resource_name", mcp.Description("Name of specific resource (optional)")), mcp.WithString("namespace", mcp.Description("Namespace to query (optional)")), mcp.WithString("all_namespaces", mcp.Description("Query all namespaces (true/false)")), - mcp.WithString("output", mcp.Description("Output format (json, yaml, wide, etc.)")), + mcp.WithString("output", mcp.Description("Output format (json, yaml, wide)"), mcp.DefaultString("wide")), ), telemetry.AdaptToolHandler(telemetry.WithTracing("k8s_get_resources", k8sTool.handleKubectlGetEnhanced))) s.AddTool(mcp.NewTool("k8s_get_pod_logs", diff --git a/pkg/k8s/k8s_test.go b/pkg/k8s/k8s_test.go index f853302..e373066 100644 --- a/pkg/k8s/k8s_test.go +++ b/pkg/k8s/k8s_test.go @@ -410,8 +410,8 @@ func TestHandleKubectlGetEnhanced(t *testing.T) { t.Run("valid resource_type", func(t *testing.T) { mock := cmd.NewMockShellExecutor() - expectedOutput := `{"items": [{"metadata": {"name": "pod1"}}]}` - mock.AddCommandString("kubectl", []string{"get", "pods", "-o", "json"}, expectedOutput, nil) + expectedOutput := `NAME READY STATUS RESTARTS AGE` + mock.AddCommandString("kubectl", []string{"get", "pods", "-o", "wide"}, expectedOutput, nil) ctx := cmd.WithShellExecutor(ctx, mock) k8sTool := newTestK8sTool() From b0360cc0ed7accd86a414769bf6c1b9621699dad Mon Sep 17 00:00:00 2001 From: Dmytro Rashko Date: Mon, 28 Jul 2025 16:15:57 +0200 Subject: [PATCH 3/3] set json format optional Signed-off-by: Dmytro Rashko --- test/e2e/helpers_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/helpers_test.go b/test/e2e/helpers_test.go index 59008d8..f88b6ab 100644 --- a/test/e2e/helpers_test.go +++ b/test/e2e/helpers_test.go @@ -249,8 +249,8 @@ func InstallKAgentTools(namespace string, releaseName string) { // GetMCPClient creates a new MCP client configured for the e2e test environment using the official mcp-go client func GetMCPClient() (*MCPClient, error) { - // Create HTTP transport for the MCP server - httpTransport, err := transport.NewStreamableHTTP("http://127.0.0.1:30885/mcp", transport.WithHTTPTimeout(15*time.Second)) + // Create HTTP transport for the MCP server with timeout long enough for operations like Istio installation + httpTransport, err := transport.NewStreamableHTTP("http://127.0.0.1:30885/mcp", transport.WithHTTPTimeout(180*time.Second)) if err != nil { return nil, fmt.Errorf("failed to create HTTP transport: %w", err) }