From 79188aff2001108f9b577c58fc9f1a7349ade1d8 Mon Sep 17 00:00:00 2001 From: Derek Etherton Date: Mon, 28 Jul 2025 11:18:48 -0700 Subject: [PATCH 1/2] Indicate that component filter args must always be strings --- src/cmd/root.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cmd/root.go b/src/cmd/root.go index e4f1252..21a1c1e 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -261,9 +261,9 @@ var rootCmd = &cobra.Command{ "components", mcp.WithDescription(`Filter and retrieve components in the OpsLevel catalog. Use as specific a filter as possible to narrow down results and avoid fetching a high number of components. -Components represent services, APIs, libraries, and other software artifacts with metadata such as owner (Team), language, framework, maturity level, lifecycle stage, and tier. Lower tier_index indicates greater criticality. Lower level_index indicates lower maturity level (e.g. Bronze=0, Silver=1, Gold=2). +Components represent services, APIs, libraries, and other software artifacts with metadata such as owner (Team), language, framework, maturity level, lifecycle stage, and tier. Lower tier_index indicates greater criticality. Lower level_index indicates lower maturity level (e.g. Bronze="0", Silver="1", Gold="2"). -Use the 'filter' parameter to narrow down results. +Use the 'filter' parameter to narrow down results. 'filter' "arg" must always be a string. For simple filters: { "key": "name", "type": "equals", "arg": "service-name" } From b505b6fb65ed44956951220aecafbde6867212c4 Mon Sep 17 00:00:00 2001 From: Derek Etherton Date: Mon, 28 Jul 2025 11:32:04 -0700 Subject: [PATCH 2/2] Surface filter parsing errors properly --- src/cmd/root.go | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/cmd/root.go b/src/cmd/root.go index 21a1c1e..01d8071 100644 --- a/src/cmd/root.go +++ b/src/cmd/root.go @@ -302,16 +302,17 @@ For complete reference: if filterObj, exists := args["filter"]; exists && filterObj != nil { // Marshal then unmarshal to our struct for type safety filterBytes, marshalErr := json.Marshal(filterObj) - if marshalErr == nil { - var f componentFilter - if unmarshalErr := json.Unmarshal(filterBytes, &f); unmarshalErr == nil { - filterInput = &f - } + if marshalErr != nil { + return mcp.NewToolResultErrorFromErr("failed to marshal filter argument", marshalErr), nil } + var f componentFilter + if unmarshalErr := json.Unmarshal(filterBytes, &f); unmarshalErr != nil { + return mcp.NewToolResultErrorFromErr("failed to unmarshal filter argument", unmarshalErr), nil + } + filterInput = &f } if filterInput != nil { - // Convert to ServiceFilterInput for the API serviceFilter, convertErr := convertToServiceFilterInput(*filterInput) if convertErr != nil { return mcp.NewToolResultErrorFromErr("failed to convert filter", convertErr), nil