From 752d5d5ddaedfc7095cc22d95adbed7351864aea Mon Sep 17 00:00:00 2001 From: ivanlysiuk-sysdig Date: Thu, 26 Feb 2026 19:09:17 -0800 Subject: [PATCH 1/3] fix(list_runtime_events): add ML event discovery and fix auditTrail filter casing The list_runtime_events tool description and filter_expr docs did not mention engine, source, or category attributes, causing AI agents to query ML detections (e.g. crypto mining, anomalous logins) using ruleName which returns no results. ML events use a separate content structure and must be queried via engine="machineLearning" or source="agentless-aws-ml"/"agentless-okta-ml". Also fix baseFilter casing: "audittrail" -> "auditTrail" to match the actual stored value. Co-Authored-By: Claude Sonnet 4.6 --- .../infra/mcp/tools/tool_list_runtime_events.go | 15 ++++++++++++--- .../mcp/tools/tool_list_runtime_events_test.go | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/internal/infra/mcp/tools/tool_list_runtime_events.go b/internal/infra/mcp/tools/tool_list_runtime_events.go index a2a2e2e..ef7287a 100644 --- a/internal/infra/mcp/tools/tool_list_runtime_events.go +++ b/internal/infra/mcp/tools/tool_list_runtime_events.go @@ -10,7 +10,7 @@ import ( "github.com/sysdiglabs/sysdig-mcp-server/internal/infra/sysdig" ) -const baseFilter = `source != "audittrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")` +const baseFilter = `source != "auditTrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")` type ToolListRuntimeEvents struct { sysdigClient sysdig.ExtendedClientWithResponsesInterface @@ -63,7 +63,7 @@ func toolRequestToEventsV1Params(request mcp.CallToolRequest, clock clock.Clock) func (h *ToolListRuntimeEvents) RegisterInServer(s *server.MCPServer) { tool := mcp.NewTool("list_runtime_events", - mcp.WithDescription("List runtime security events from the last given hours, optionally filtered by severity level."), + mcp.WithDescription("List runtime security events from the last given hours, optionally filtered by severity level. Includes both Falco-based and machine learning (ML) detections such as crypto mining, anomalous logins, and other ML-detected threats."), mcp.WithString("cursor", mcp.Description("Cursor for pagination."), ), @@ -79,7 +79,13 @@ func (h *ToolListRuntimeEvents) RegisterInServer(s *server.MCPServer) { mcp.Description(`Logical filter expression to select runtime security events. Supports operators: =, !=, in, contains, startsWith, exists. Combine with and/or/not. -Key attributes include: severity (codes "0"-"7"), originator, sourceType, ruleName, rawEventCategory, kubernetes.cluster.name, host.hostName, container.imageName, aws.accountId, azure.subscriptionId, gcp.projectId, policyId, trigger. +Key attributes include: severity (codes "0"-"7"), originator, sourceType, ruleName, rawEventCategory, engine, source, category, kubernetes.cluster.name, host.hostName, container.imageName, aws.accountId, azure.subscriptionId, gcp.projectId, policyId, trigger. + +To find machine learning (ML) detections (e.g. crypto mining, anomalous logins), use engine or source filters: +- All ML events: 'engine = "machineLearning"' +- AWS ML detections: 'source = "agentless-aws-ml"' +- Okta ML detections: 'source = "agentless-okta-ml"' +- By category: 'category = "machine-learning"' You can specify the severity of the events based on the following cases: - high-severity: 'severity in ("0","1","2","3")' @@ -96,6 +102,9 @@ You can specify the severity of the events based on the following cases: `container.imageName = "nginx:latest" and originator = "hostscanning"`, `aws.accountId = "123456789012"`, `policyId = "CIS_Docker_Benchmark"`, + `engine = "machineLearning"`, + `source = "agentless-aws-ml"`, + `engine = "machineLearning" and aws.accountId = "123456789012"`, ), ), mcp.WithOutputSchema[map[string]any](), diff --git a/internal/infra/mcp/tools/tool_list_runtime_events_test.go b/internal/infra/mcp/tools/tool_list_runtime_events_test.go index 7d33639..825baab 100644 --- a/internal/infra/mcp/tools/tool_list_runtime_events_test.go +++ b/internal/infra/mcp/tools/tool_list_runtime_events_test.go @@ -94,7 +94,7 @@ var _ = Describe("ToolListRuntimeEvents", func() { It("should use default values when no params are provided", func(ctx SpecContext) { mockClient.EXPECT().GetEventsV1WithResponse(gomock.Any(), gomock.Any()).DoAndReturn(func(_ context.Context, params *sysdig.GetEventsV1Params, _ ...sysdig.RequestEditorFn) (*sysdig.GetEventsV1Response, error) { Expect(*params.Limit).To(Equal(int32(50))) - Expect(*params.Filter).To(Equal(`source != "audittrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")`)) + Expect(*params.Filter).To(Equal(`source != "auditTrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")`)) Expect(*params.To).To(Equal(int64(946684800000000000))) Expect(*params.From).To(Equal(int64(946681200000000000))) From c850414f36b4b8a609c807e5239363a6714f1115 Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Fri, 27 Feb 2026 11:32:03 +0100 Subject: [PATCH 2/3] fix(list_runtime_events): remove redundant source filter that excluded ML events The `source != "auditTrail"` clause in the MCP baseFilter duplicated a filter already applied server-side, causing ML detections (e.g. Crypto Mining Detection) to be silently excluded from results. --- internal/infra/mcp/tools/tool_list_runtime_events.go | 2 +- internal/infra/mcp/tools/tool_list_runtime_events_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/infra/mcp/tools/tool_list_runtime_events.go b/internal/infra/mcp/tools/tool_list_runtime_events.go index ef7287a..e607796 100644 --- a/internal/infra/mcp/tools/tool_list_runtime_events.go +++ b/internal/infra/mcp/tools/tool_list_runtime_events.go @@ -10,7 +10,7 @@ import ( "github.com/sysdiglabs/sysdig-mcp-server/internal/infra/sysdig" ) -const baseFilter = `source != "auditTrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")` +const baseFilter = `not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")` type ToolListRuntimeEvents struct { sysdigClient sysdig.ExtendedClientWithResponsesInterface diff --git a/internal/infra/mcp/tools/tool_list_runtime_events_test.go b/internal/infra/mcp/tools/tool_list_runtime_events_test.go index 825baab..bbc5eb2 100644 --- a/internal/infra/mcp/tools/tool_list_runtime_events_test.go +++ b/internal/infra/mcp/tools/tool_list_runtime_events_test.go @@ -94,7 +94,7 @@ var _ = Describe("ToolListRuntimeEvents", func() { It("should use default values when no params are provided", func(ctx SpecContext) { mockClient.EXPECT().GetEventsV1WithResponse(gomock.Any(), gomock.Any()).DoAndReturn(func(_ context.Context, params *sysdig.GetEventsV1Params, _ ...sysdig.RequestEditorFn) (*sysdig.GetEventsV1Response, error) { Expect(*params.Limit).To(Equal(int32(50))) - Expect(*params.Filter).To(Equal(`source != "auditTrail" and not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")`)) + Expect(*params.Filter).To(Equal(`not originator in ("benchmarks","compliance","cloudsec","scanning","hostscanning")`)) Expect(*params.To).To(Equal(int64(946684800000000000))) Expect(*params.From).To(Equal(int64(946681200000000000))) From 5f58b493d436f63870cdb0c1bdb08d1764007c4f Mon Sep 17 00:00:00 2001 From: Fede Barcelona Date: Fri, 27 Feb 2026 11:33:47 +0100 Subject: [PATCH 3/3] docs(list_runtime_events): document max limit of 200 events --- internal/infra/mcp/tools/tool_list_runtime_events.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/infra/mcp/tools/tool_list_runtime_events.go b/internal/infra/mcp/tools/tool_list_runtime_events.go index e607796..9f1eb3b 100644 --- a/internal/infra/mcp/tools/tool_list_runtime_events.go +++ b/internal/infra/mcp/tools/tool_list_runtime_events.go @@ -72,7 +72,7 @@ func (h *ToolListRuntimeEvents) RegisterInServer(s *server.MCPServer) { mcp.DefaultNumber(1), ), mcp.WithNumber("limit", - mcp.Description("Maximum number of events to return."), + mcp.Description("Maximum number of events to return. Maximum allowed value is 200."), mcp.DefaultNumber(50), ), mcp.WithString("filter_expr",