diff --git a/pkg/k8s/k8s.go b/pkg/k8s/k8s.go index 6def2f2..738be34 100644 --- a/pkg/k8s/k8s.go +++ b/pkg/k8s/k8s.go @@ -93,6 +93,7 @@ func (k *K8sTool) handleKubectlLogsEnhanced(ctx context.Context, request mcp.Cal namespace := mcp.ParseString(request, "namespace", "default") container := mcp.ParseString(request, "container", "") tailLines := mcp.ParseInt(request, "tail_lines", 50) + previous := mcp.ParseBoolean(request, "previous", false) if podName == "" { return mcp.NewToolResultError("pod_name parameter is required"), nil @@ -104,6 +105,10 @@ func (k *K8sTool) handleKubectlLogsEnhanced(ctx context.Context, request mcp.Cal args = append(args, "-c", container) } + if previous { + args = append(args, "--previous") + } + if tailLines > 0 { args = append(args, "--tail", fmt.Sprintf("%d", tailLines)) } @@ -661,6 +666,7 @@ func RegisterTools(s *server.MCPServer, llm llms.Model, kubeconfig string, readO mcp.WithString("namespace", mcp.Description("Namespace of the pod (default: default)")), mcp.WithString("container", mcp.Description("Container name (for multi-container pods)")), mcp.WithNumber("tail_lines", mcp.Description("Number of lines to show from the end (default: 50)")), + mcp.WithBoolean("previous", mcp.Description("Return logs from the previous terminated container (kubectl logs --previous)")), ), telemetry.AdaptToolHandler(telemetry.WithTracing("k8s_get_pod_logs", k8sTool.handleKubectlLogsEnhanced))) s.AddTool(mcp.NewTool("k8s_get_events", diff --git a/pkg/k8s/k8s_test.go b/pkg/k8s/k8s_test.go index 6c008a2..20aa4b9 100644 --- a/pkg/k8s/k8s_test.go +++ b/pkg/k8s/k8s_test.go @@ -597,6 +597,30 @@ log line 2` assert.NotNil(t, result) assert.False(t, result.IsError) }) + + t.Run("previous container logs", func(t *testing.T) { + mock := cmd.NewMockShellExecutor() + expectedOutput := `previous log line` + mock.AddCommandString("kubectl", []string{"logs", "test-pod", "-n", "default", "-c", "app", "--previous", "--tail", "200"}, expectedOutput, nil) + ctx := cmd.WithShellExecutor(ctx, mock) + + k8sTool := newTestK8sTool() + req := mcp.CallToolRequest{} + req.Params.Arguments = map[string]interface{}{ + "pod_name": "test-pod", + "container": "app", + "previous": true, + "tail_lines": float64(200), + } + result, err := k8sTool.handleKubectlLogsEnhanced(ctx, req) + assert.NoError(t, err) + assert.NotNil(t, result) + assert.False(t, result.IsError) + + callLog := mock.GetCallLog() + require.Len(t, callLog, 1) + assert.Equal(t, []string{"logs", "test-pod", "-n", "default", "-c", "app", "--previous", "--tail", "200"}, callLog[0].Args) + }) } func TestHandleApplyManifest(t *testing.T) {