From f0eeb85729fd0c4a38d85fd80599ddb56ec65443 Mon Sep 17 00:00:00 2001 From: Renee Xu Date: Tue, 16 Jun 2026 14:59:21 +0000 Subject: [PATCH 1/4] Fix enum values to match those expected by gql --- pkg/github/issues_granular.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pkg/github/issues_granular.go b/pkg/github/issues_granular.go index 3ddfd682f..1e522a51f 100644 --- a/pkg/github/issues_granular.go +++ b/pkg/github/issues_granular.go @@ -281,7 +281,7 @@ func GranularUpdateIssueLabels(t translations.TranslationHelperFunc) inventory.S ToolsetMetadataIssues, mcp.Tool{ Name: "update_issue_labels", - Description: t("TOOL_UPDATE_ISSUE_LABELS_DESCRIPTION", "Update the labels of an existing issue. This replaces the current labels with the provided list. When setting values, include a confidence level (low, medium, or high) reflecting how certain you are about the choice."), + Description: t("TOOL_UPDATE_ISSUE_LABELS_DESCRIPTION", "Update the labels of an existing issue. This replaces the current labels with the provided list. When setting values, include a confidence level (LOW, MEDIUM, or HIGH) reflecting how certain you are about the choice."), Annotations: &mcp.ToolAnnotations{ Title: t("TOOL_UPDATE_ISSUE_LABELS_USER_TITLE", "Update Issue Labels"), ReadOnlyHint: false, @@ -325,8 +325,8 @@ func GranularUpdateIssueLabels(t translations.TranslationHelperFunc) inventory.S }, "confidence": { Type: "string", - Description: "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", - Enum: []any{"low", "medium", "high"}, + Description: "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", + Enum: []any{"LOW", "MEDIUM", "HIGH"}, }, "is_suggestion": { Type: "boolean", @@ -398,8 +398,8 @@ func GranularUpdateIssueLabels(t translations.TranslationHelperFunc) inventory.S if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - if confidence != "" && confidence != "low" && confidence != "medium" && confidence != "high" { - return utils.NewToolResultError("confidence must be one of: low, medium, high"), nil, nil + if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { + return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil } isSuggestion, err := OptionalParam[bool](v, "is_suggestion") if err != nil { @@ -505,7 +505,7 @@ func GranularUpdateIssueType(t translations.TranslationHelperFunc) inventory.Ser ToolsetMetadataIssues, mcp.Tool{ Name: "update_issue_type", - Description: t("TOOL_UPDATE_ISSUE_TYPE_DESCRIPTION", "Update the type of an existing issue (e.g. 'bug', 'feature'). When setting values, include a confidence level (low, medium, or high) reflecting how certain you are about the choice."), + Description: t("TOOL_UPDATE_ISSUE_TYPE_DESCRIPTION", "Update the type of an existing issue (e.g. 'bug', 'feature'). When setting values, include a confidence level (LOW, MEDIUM, or HIGH) reflecting how certain you are about the choice."), Annotations: &mcp.ToolAnnotations{ Title: t("TOOL_UPDATE_ISSUE_TYPE_USER_TITLE", "Update Issue Type"), ReadOnlyHint: false, @@ -540,8 +540,8 @@ func GranularUpdateIssueType(t translations.TranslationHelperFunc) inventory.Ser }, "confidence": { Type: "string", - Description: "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", - Enum: []any{"low", "medium", "high"}, + Description: "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", + Enum: []any{"LOW", "MEDIUM", "HIGH"}, }, "is_suggestion": { Type: "boolean", @@ -582,8 +582,8 @@ func GranularUpdateIssueType(t translations.TranslationHelperFunc) inventory.Ser if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - if confidence != "" && confidence != "low" && confidence != "medium" && confidence != "high" { - return utils.NewToolResultError("confidence must be one of: low, medium, high"), nil, nil + if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { + return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil } isSuggestion, err := OptionalParam[bool](args, "is_suggestion") if err != nil { @@ -987,8 +987,8 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv }, "confidence": { Type: "string", - Description: "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", - Enum: []any{"low", "medium", "high"}, + Description: "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", + Enum: []any{"LOW", "MEDIUM", "HIGH"}, }, "is_suggestion": { Type: "boolean", @@ -1111,8 +1111,8 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } - if confidence != "" && confidence != "low" && confidence != "medium" && confidence != "high" { - return utils.NewToolResultError("confidence must be one of: low, medium, high"), nil, nil + if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { + return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil } if confidence != "" { input.Confidence = &confidence From 5fa69f158a85f079ee02556e76e94fa02b5447b2 Mon Sep 17 00:00:00 2001 From: Renee Xu Date: Tue, 16 Jun 2026 15:17:33 +0000 Subject: [PATCH 2/4] Update test --- pkg/github/granular_tools_test.go | 34 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/pkg/github/granular_tools_test.go b/pkg/github/granular_tools_test.go index 27e8079f9..70dd09652 100644 --- a/pkg/github/granular_tools_test.go +++ b/pkg/github/granular_tools_test.go @@ -476,12 +476,12 @@ func TestGranularUpdateIssueLabelsConfidence(t *testing.T) { "repo": "repo", "issue_number": float64(1), "labels": []any{ - map[string]any{"name": "bug", "confidence": "high"}, + map[string]any{"name": "bug", "confidence": "HIGH"}, }, }, expectedReq: map[string]any{ "labels": []any{ - map[string]any{"name": "bug", "confidence": "high"}, + map[string]any{"name": "bug", "confidence": "HIGH"}, }, }, }, @@ -492,12 +492,12 @@ func TestGranularUpdateIssueLabelsConfidence(t *testing.T) { "repo": "repo", "issue_number": float64(1), "labels": []any{ - map[string]any{"name": "bug", "rationale": "Reports a crash", "confidence": "medium"}, + map[string]any{"name": "bug", "rationale": "Reports a crash", "confidence": "MEDIUM"}, }, }, expectedReq: map[string]any{ "labels": []any{ - map[string]any{"name": "bug", "rationale": "Reports a crash", "confidence": "medium"}, + map[string]any{"name": "bug", "rationale": "Reports a crash", "confidence": "MEDIUM"}, }, }, }, @@ -528,7 +528,7 @@ func TestGranularUpdateIssueLabelsConfidence(t *testing.T) { require.NoError(t, err) errorContent := getErrorResult(t, result) - assert.Contains(t, errorContent.Text, "confidence must be one of: low, medium, high") + assert.Contains(t, errorContent.Text, "confidence must be one of: LOW, MEDIUM, HIGH") return } @@ -742,12 +742,12 @@ func TestGranularUpdateIssueTypeConfidence(t *testing.T) { "repo": "repo", "issue_number": float64(1), "issue_type": "bug", - "confidence": "high", + "confidence": "HIGH", }, expectedReq: map[string]any{ "type": map[string]any{ "value": "bug", - "confidence": "high", + "confidence": "HIGH", }, }, }, @@ -759,13 +759,13 @@ func TestGranularUpdateIssueTypeConfidence(t *testing.T) { "issue_number": float64(1), "issue_type": "feature", "rationale": "Asks for dark mode support", - "confidence": "medium", + "confidence": "MEDIUM", }, expectedReq: map[string]any{ "type": map[string]any{ "value": "feature", "rationale": "Asks for dark mode support", - "confidence": "medium", + "confidence": "MEDIUM", }, }, }, @@ -776,12 +776,12 @@ func TestGranularUpdateIssueTypeConfidence(t *testing.T) { "repo": "repo", "issue_number": float64(1), "issue_type": "bug", - "confidence": "low", + "confidence": "LOW", }, expectedReq: map[string]any{ "type": map[string]any{ "value": "bug", - "confidence": "low", + "confidence": "LOW", }, }, }, @@ -820,7 +820,7 @@ func TestGranularUpdateIssueTypeInvalidConfidence(t *testing.T) { "issue_type": "bug", "confidence": "very_high", }, - expectedErrText: "confidence must be one of: low, medium, high", + expectedErrText: "confidence must be one of: LOW, MEDIUM, HIGH", }, { name: "confidence wrong type", @@ -1599,7 +1599,7 @@ func TestGranularSetIssueFields(t *testing.T) { }) t.Run("successful set with confidence", func(t *testing.T) { - confidence := "high" + confidence := "HIGH" matchers := []githubv4mock.Matcher{ githubv4mock.NewQueryMatcher( struct { @@ -1680,7 +1680,7 @@ func TestGranularSetIssueFields(t *testing.T) { map[string]any{ "field_id": "FIELD_1", "text_value": "hello", - "confidence": "high", + "confidence": "HIGH", }, }, }) @@ -1709,11 +1709,11 @@ func TestGranularSetIssueFields(t *testing.T) { result, err := handler(ContextWithDeps(context.Background(), deps), &request) require.NoError(t, err) textContent := getTextResult(t, result) - assert.Contains(t, textContent.Text, "confidence must be one of: low, medium, high") + assert.Contains(t, textContent.Text, "confidence must be one of: LOW, MEDIUM, HIGH") }) t.Run("confidence is sent when supplied", func(t *testing.T) { - confidence := "high" + confidence := "HIGH" matchers := []githubv4mock.Matcher{ githubv4mock.NewQueryMatcher( struct { @@ -1794,7 +1794,7 @@ func TestGranularSetIssueFields(t *testing.T) { map[string]any{ "field_id": "FIELD_1", "text_value": "hello", - "confidence": "high", + "confidence": "HIGH", }, }, }) From cdb56379b87397ca321736d550d6a2861487db48 Mon Sep 17 00:00:00 2001 From: Renee Xu Date: Wed, 17 Jun 2026 07:15:16 +0000 Subject: [PATCH 3/4] Update doc and snaps --- docs/feature-flags.md | 2 +- pkg/github/__toolsnaps__/set_issue_fields.snap | 8 ++++---- pkg/github/__toolsnaps__/update_issue_labels.snap | 10 +++++----- pkg/github/__toolsnaps__/update_issue_type.snap | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/feature-flags.md b/docs/feature-flags.md index a3074bdd2..837003273 100644 --- a/docs/feature-flags.md +++ b/docs/feature-flags.md @@ -200,7 +200,7 @@ runtime behavior (such as output formatting) won't appear here. - **update_issue_type** - Update Issue Type - **Required OAuth Scopes**: `repo` - - `confidence`: How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal. (string, optional) + - `confidence`: How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal. (string, optional) - `is_suggestion`: If true, this issue type change is sent to the API as a suggestion (suggest:true) rather than an applied value. Whether the type is applied or recorded as a proposal is determined by the API. (boolean, optional) - `issue_number`: The issue number to update (number, required) - `issue_type`: The issue type to set (string, required) diff --git a/pkg/github/__toolsnaps__/set_issue_fields.snap b/pkg/github/__toolsnaps__/set_issue_fields.snap index 8f25d0969..7a98fde2a 100644 --- a/pkg/github/__toolsnaps__/set_issue_fields.snap +++ b/pkg/github/__toolsnaps__/set_issue_fields.snap @@ -12,11 +12,11 @@ "items": { "properties": { "confidence": { - "description": "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", + "description": "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", "enum": [ - "low", - "medium", - "high" + "LOW", + "MEDIUM", + "HIGH" ], "type": "string" }, diff --git a/pkg/github/__toolsnaps__/update_issue_labels.snap b/pkg/github/__toolsnaps__/update_issue_labels.snap index 21f7fea6b..2b31d756b 100644 --- a/pkg/github/__toolsnaps__/update_issue_labels.snap +++ b/pkg/github/__toolsnaps__/update_issue_labels.snap @@ -4,7 +4,7 @@ "openWorldHint": true, "title": "Update Issue Labels" }, - "description": "Update the labels of an existing issue. This replaces the current labels with the provided list. When setting values, include a confidence level (low, medium, or high) reflecting how certain you are about the choice.", + "description": "Update the labels of an existing issue. This replaces the current labels with the provided list. When setting values, include a confidence level (LOW, MEDIUM, or HIGH) reflecting how certain you are about the choice.", "inputSchema": { "properties": { "issue_number": { @@ -23,11 +23,11 @@ { "properties": { "confidence": { - "description": "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", + "description": "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", "enum": [ - "low", - "medium", - "high" + "LOW", + "MEDIUM", + "HIGH" ], "type": "string" }, diff --git a/pkg/github/__toolsnaps__/update_issue_type.snap b/pkg/github/__toolsnaps__/update_issue_type.snap index 2f39b2d3b..d07a9d43d 100644 --- a/pkg/github/__toolsnaps__/update_issue_type.snap +++ b/pkg/github/__toolsnaps__/update_issue_type.snap @@ -4,15 +4,15 @@ "openWorldHint": true, "title": "Update Issue Type" }, - "description": "Update the type of an existing issue (e.g. 'bug', 'feature'). When setting values, include a confidence level (low, medium, or high) reflecting how certain you are about the choice.", + "description": "Update the type of an existing issue (e.g. 'bug', 'feature'). When setting values, include a confidence level (LOW, MEDIUM, or HIGH) reflecting how certain you are about the choice.", "inputSchema": { "properties": { "confidence": { - "description": "How confident you are in this choice. Use 'high' for clear signal or explicit user request, 'medium' for reasonable inference with some ambiguity, 'low' for best guess with limited signal.", + "description": "How confident you are in this choice. Use 'HIGH' for clear signal or explicit user request, 'MEDIUM' for reasonable inference with some ambiguity, 'LOW' for best guess with limited signal.", "enum": [ - "low", - "medium", - "high" + "LOW", + "MEDIUM", + "HIGH" ], "type": "string" }, From 7b0850621156172ecb360a49222566895cb97d5a Mon Sep 17 00:00:00 2001 From: Renee Xu Date: Wed, 17 Jun 2026 13:07:55 +0000 Subject: [PATCH 4/4] Normalize lower case confidence values --- pkg/github/granular_tools_test.go | 34 ++++++++++++++++++++++++++++++- pkg/github/issues_granular.go | 7 +++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/github/granular_tools_test.go b/pkg/github/granular_tools_test.go index 70dd09652..4a274ac31 100644 --- a/pkg/github/granular_tools_test.go +++ b/pkg/github/granular_tools_test.go @@ -501,6 +501,22 @@ func TestGranularUpdateIssueLabelsConfidence(t *testing.T) { }, }, }, + { + name: "label confidence is normalized", + requestArgs: map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(1), + "labels": []any{ + map[string]any{"name": "bug", "confidence": " high\t"}, + }, + }, + expectedReq: map[string]any{ + "labels": []any{ + map[string]any{"name": "bug", "confidence": "HIGH"}, + }, + }, + }, { name: "invalid confidence value", requestArgs: map[string]any{ @@ -785,6 +801,22 @@ func TestGranularUpdateIssueTypeConfidence(t *testing.T) { }, }, }, + { + name: "type confidence is normalized", + requestArgs: map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(1), + "issue_type": "bug", + "confidence": " medium ", + }, + expectedReq: map[string]any{ + "type": map[string]any{ + "value": "bug", + "confidence": "MEDIUM", + }, + }, + }, } for _, tc := range tests { @@ -1680,7 +1712,7 @@ func TestGranularSetIssueFields(t *testing.T) { map[string]any{ "field_id": "FIELD_1", "text_value": "hello", - "confidence": "HIGH", + "confidence": " high ", }, }, }) diff --git a/pkg/github/issues_granular.go b/pkg/github/issues_granular.go index 1e522a51f..157d5595f 100644 --- a/pkg/github/issues_granular.go +++ b/pkg/github/issues_granular.go @@ -19,6 +19,10 @@ import ( "github.com/shurcooL/githubv4" ) +func normalizeConfidence(confidence string) string { + return strings.ToUpper(strings.TrimSpace(confidence)) +} + // issueUpdateTool is a helper to create single-field issue update tools. func issueUpdateTool( t translations.TranslationHelperFunc, @@ -398,6 +402,7 @@ func GranularUpdateIssueLabels(t translations.TranslationHelperFunc) inventory.S if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } + confidence = normalizeConfidence(confidence) if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil } @@ -582,6 +587,7 @@ func GranularUpdateIssueType(t translations.TranslationHelperFunc) inventory.Ser if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } + confidence = normalizeConfidence(confidence) if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil } @@ -1111,6 +1117,7 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv if err != nil { return utils.NewToolResultError(err.Error()), nil, nil } + confidence = normalizeConfidence(confidence) if confidence != "" && confidence != "LOW" && confidence != "MEDIUM" && confidence != "HIGH" { return utils.NewToolResultError("confidence must be one of: LOW, MEDIUM, HIGH"), nil, nil }