fix(issues): allow delete:false in issue_write issue_fields - #3077
Open
tgockel wants to merge 1 commit into
Open
fix(issues): allow delete:false in issue_write issue_fields#3077tgockel wants to merge 1 commit into
tgockel wants to merge 1 commit into
Conversation
The `delete` property of issue_write's issue_fields items was declared with
Enum: []any{true}, making true its only legal value. The property is optional,
but a client that fills every property of a schema -- common, since
OpenAI-style strict function calling requires every property to appear in
`required` -- had no way to express "not deleting this field": there is no
false in the enum and no null in the type. `value` offers no alternative
either, being typed ["string","number","boolean"] with no null.
The MCP Go SDK validates arguments against the resolved input schema before
the handler runs, so delete: false was rejected at schema validation and never
reached optionalIssueWriteFields. Such clients sent delete: true alongside a
value instead and hit the handler's mutual-exclusion check, so issue_write
could never set an issue field for them.
Remove the enum so false is a legal no-op, and document that omitting the
property or setting it to false leaves the field unchanged. No handler change
is needed: the code already branches on `if deleteField`, so false falls
through to the normal value path, and the mutual-exclusion check for
delete: true still applies. Add tests for optionalIssueWriteFields, which had
none.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes
Enum: []any{true}from thedeleteproperty ofissue_write'sissue_fieldsitem schema, sodelete: falseis a legal no-op instead of a schema-validation error.Why
deletewas declared{"type": "boolean", "enum": [true]}. The property is optional, but a client that fills every property of a schema — common, since OpenAI-style strict function calling requires every property to appear inrequired— had no way to say "not deleting this field": there is nofalsein the enum and nonullin the type. The siblingvalueproperty offers no alternative either, being typed["string","number","boolean"]with nonull, andissues.goexplicitly rejectsvalue: null.This is not only cosmetic. The MCP Go SDK validates arguments against the resolved input schema before the handler runs (
go-sdk@v1.7.0/mcp/server.go,applySchema), sodelete: falsewas rejected at validation and never reachedoptionalIssueWriteFields. Clients that fill every property instead sentdelete: truealongside avalueand hit the handler's mutual-exclusion check, soissue_writecould never set an issue field for them.What changed
pkg/github/issues.go: droppedEnum: []any{true}from thedeleteproperty of theissue_fieldsitem schema; extended its description to state that omitting the property, or setting it tofalse, leaves the field's current value unchanged.pkg/github/__toolsnaps__/issue_write.snap: regenerated viaUPDATE_TOOLSNAPS=true.pkg/github/issues_test.go: addedTest_optionalIssueWriteFields, coveringdelete: falsealongside a value,delete: truealone,deleteomitted, and both existing error paths. This function previously had no test coverage.No handler logic changed.
optionalIssueWriteFieldsalready readsOptionalParam[bool](itemMap, "delete")and branches onif deleteField, sofalsefalls through to the normal value path, and thedelete: truemutual-exclusion check still applies.MCP impact
issue_write.issue_fields[].deletewidens fromenum: [true]to any boolean, and its description gains the no-op case. Strictly a relaxation: every payload valid before is still valid and behaves identically.Prompts tested (tool changes only)
optionalIssueWriteFieldsplus the regenerated schema snapshot.api.githubcopilot.com/mcp/, was{"method": "update", "issue_number": 5, "issue_fields": [{"field_name": "Start date", "value": "2026-08-14", "delete": true, "field_option_name": ""}]}— rejected withissue field "Start date" cannot specify 'delete' together with 'value' or 'field_option_name'on seven consecutive calls across two runs. That client also sentmilestone: 0,duplicate_of: 0, andfield_option_name: ""; onlydeletehad no benign value. The equivalent prompt is "Set the Start date field on issue #5 to 2026-08-14".falserather thantrueis unverified, and one copying its own prior call will keep sendingtrue. The change removes a schema construct that forces failure on an otherwise recoverable mistake.Security / limits
Input validation is relaxed for one boolean that routes to an existing code path. No auth, permission, data-exposure, or size-limit surface is touched, and the mutual-exclusion check that prevents
delete: truefrom being combined withvalueis unchanged.Tool renaming
deprecated_tool_aliases.goLint & tests
./script/lint—0 issues../script/test— full suite passes, including the snapshot check withoutUPDATE_TOOLSNAPSset.Docs
Ran
./script/generate-docs; it produced no diff. The generated tables do not include nested item-property descriptions, and a repo-wide grep found the old description only inissue_write.snap.Fixes #2904.