Skip to content

fix(issues): allow delete:false in issue_write issue_fields - #3077

Open
tgockel wants to merge 1 commit into
github:mainfrom
tgockel:issue-fields-delete-false
Open

fix(issues): allow delete:false in issue_write issue_fields#3077
tgockel wants to merge 1 commit into
github:mainfrom
tgockel:issue-fields-delete-false

Conversation

@tgockel

@tgockel tgockel commented Aug 15, 2026

Copy link
Copy Markdown

Summary

Removes Enum: []any{true} from the delete property of issue_write's issue_fields item schema, so delete: false is a legal no-op instead of a schema-validation error.

Why

delete was 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 in required — had no way to say "not deleting this field": there is no false in the enum and no null in the type. The sibling value property offers no alternative either, being typed ["string","number","boolean"] with no null, and issues.go explicitly rejects value: 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), so delete: false was rejected at validation and never reached optionalIssueWriteFields. Clients that fill every property instead sent delete: true alongside a value and hit the handler's mutual-exclusion check, so issue_write could never set an issue field for them.

What changed

  • pkg/github/issues.go: dropped Enum: []any{true} from the delete property of the issue_fields item schema; extended its description to state that omitting the property, or setting it to false, leaves the field's current value unchanged.
  • pkg/github/__toolsnaps__/issue_write.snap: regenerated via UPDATE_TOOLSNAPS=true.
  • pkg/github/issues_test.go: added Test_optionalIssueWriteFields, covering delete: false alongside a value, delete: true alone, delete omitted, and both existing error paths. This function previously had no test coverage.

No handler logic changed. optionalIssueWriteFields already reads OptionalParam[bool](itemMap, "delete") and branches on if deleteField, so false falls through to the normal value path, and the delete: true mutual-exclusion check still applies.

MCP impact

  • No tool or API changes
  • Tool schema or behavior changed
  • New tool added

issue_write.issue_fields[].delete widens from enum: [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)

  • Worked against a live GitHub repository with org-level issue fields configured.
  • Coverage is the new unit tests over optionalIssueWriteFields plus the regenerated schema snapshot.
  • The reproducing payload, from an agent framework against 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 with issue field "Start date" cannot specify 'delete' together with 'value' or 'field_option_name' on seven consecutive calls across two runs. That client also sent milestone: 0, duplicate_of: 0, and field_option_name: ""; only delete had no benign value. The equivalent prompt is "Set the Start date field on issue #5 to 2026-08-14".
  • Caveat: this does not guarantee such a client starts succeeding. Whether a given model emits false rather than true is unverified, and one copying its own prior call will keep sending true. The change removes a schema construct that forces failure on an otherwise recoverable mistake.

Security / limits

  • No security or limits impact

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: true from being combined with value is unchanged.

Tool renaming

  • I am renaming tools as part of this PR (e.g. a part of a consolidation effort)
    • I have added the new tool aliases in deprecated_tool_aliases.go
  • I am not renaming tools as part of this PR

Lint & tests

  • Linted locally with ./script/lint0 issues.
  • Tested locally with ./script/test — full suite passes, including the snapshot check without UPDATE_TOOLSNAPS set.

Docs

  • Not needed
  • Updated (README / docs / examples)

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 in issue_write.snap.

Fixes #2904.

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>
@tgockel
tgockel requested a review from a team as a code owner August 15, 2026 00:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

blocked bug from using MCP server in Antigravity IDE

1 participant