From 2261f9ccfc281a7b78f6cfe5447a47e90b04dda1 Mon Sep 17 00:00:00 2001 From: JuggerGrimrod88 Date: Tue, 7 Jul 2026 21:18:38 -0400 Subject: [PATCH] fix(labels): mark label_write as destructive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit label_write's delete method removes a label at the repository level, detaching it from every issue and PR in the repo — an operation whose effects cannot be automatically restored even if the label is recreated with the same name. Unlike remove_sub_issue and delete_pending_pull_request_review, label_write omitted DestructiveHint, so MCP clients received no destructive-operation signal and could execute the deletion without confirming with the user. Set DestructiveHint: true on the tool. This matches the convention already used by the other method-dispatched tools capable of destruction (projects_write, actions_run_trigger), which set the hint statically on a tool whose method set includes a destructive one. Closes #2723 Co-Authored-By: Claude --- pkg/github/__toolsnaps__/label_write.snap | 1 + pkg/github/labels.go | 5 +++-- pkg/github/labels_test.go | 4 ++++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkg/github/__toolsnaps__/label_write.snap b/pkg/github/__toolsnaps__/label_write.snap index 6eeb9fd730..e9fdcf0d83 100644 --- a/pkg/github/__toolsnaps__/label_write.snap +++ b/pkg/github/__toolsnaps__/label_write.snap @@ -1,5 +1,6 @@ { "annotations": { + "destructiveHint": true, "idempotentHint": false, "readOnlyHint": false, "title": "Write operations on repository labels" diff --git a/pkg/github/labels.go b/pkg/github/labels.go index 0e49968496..29ae3d5323 100644 --- a/pkg/github/labels.go +++ b/pkg/github/labels.go @@ -226,8 +226,9 @@ func LabelWrite(t translations.TranslationHelperFunc) inventory.ServerTool { Name: "label_write", Description: t("TOOL_LABEL_WRITE_DESCRIPTION", "Perform write operations on repository labels. To set labels on issues, use the 'update_issue' tool."), Annotations: &mcp.ToolAnnotations{ - Title: t("TOOL_LABEL_WRITE_TITLE", "Write operations on repository labels"), - ReadOnlyHint: false, + Title: t("TOOL_LABEL_WRITE_TITLE", "Write operations on repository labels"), + ReadOnlyHint: false, + DestructiveHint: jsonschema.Ptr(true), }, InputSchema: &jsonschema.Schema{ Type: "object", diff --git a/pkg/github/labels_test.go b/pkg/github/labels_test.go index 88102ba3c9..4407b4b4af 100644 --- a/pkg/github/labels_test.go +++ b/pkg/github/labels_test.go @@ -247,6 +247,10 @@ func TestWriteLabel(t *testing.T) { assert.Equal(t, "label_write", tool.Name) assert.NotEmpty(t, tool.Description) assert.False(t, tool.Annotations.ReadOnlyHint, "label_write tool should not be read-only") + // label_write can delete a label repo-wide (removing it from every issue/PR), + // so clients must treat the tool as destructive and confirm before running it. + require.NotNil(t, tool.Annotations.DestructiveHint, "label_write should set DestructiveHint") + assert.True(t, *tool.Annotations.DestructiveHint, "label_write should be destructive") tests := []struct { name string