Skip to content

feat: gate issue_write and get_issue behind remote_mcp_issue_fields flag#2553

Merged
SamMorrowDrums merged 4 commits into
github:kelsey/issue-fields-cleanfrom
kelsey-myers:iunia/issue-fields-flag-gating
May 27, 2026
Merged

feat: gate issue_write and get_issue behind remote_mcp_issue_fields flag#2553
SamMorrowDrums merged 4 commits into
github:kelsey/issue-fields-cleanfrom
kelsey-myers:iunia/issue-fields-flag-gating

Conversation

@kelsey-myers

@kelsey-myers kelsey-myers commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Gates issue_write and get_issue field enrichment behind the remote_mcp_issue_fields feature flag. Stacks on top of #2551.

Extends the inventory FeatureFlagEnable/FeatureFlagDisable fields from string to []string (AND semantics for enable, OR for disable) to avoid 4-way tool duplication when gating against multiple flags simultaneously.

Why

issue_write exposes issue_fields (Issues 2.0) and get_issue runs an extra GraphQL round-trip for field values — both should only happen when the flag is on, consistent with how list_issues and search_issues were gated in #2520.

What changed

  • FeatureFlagEnable/FeatureFlagDisable on ServerTool, ServerResourceTemplate, ServerPrompt changed from string to []string; featureFlagAllowed updated with range loops (enable = all must pass, disable = any blocks)
  • LegacyIssueWrite: new FeatureFlagDisable = []string{FeatureFlagIssuesGranular, FeatureFlagIssueFields} variant — no issue_fields schema param, passes nil field values
  • IssueWrite: gains FeatureFlagEnable = []string{FeatureFlagIssueFields} — only active when flag is on
  • get_issue field_values enrichment wrapped in IsFeatureEnabled(ctx, FeatureFlagIssueFields) runtime check
  • New toolsnaps: issue_write.snap (legacy) + issue_write_ff_remote_mcp_issue_fields.snap (flag-enabled), following feat(issues): gate issue-fields features behind remote_mcp_issue_fields flag #2520 convention
  • featureFlagAllowed disable loop modernised to slices.ContainsFunc

MCP impact

  • Tool schema or behavior changed — issue_write schema splits into two registrations; issue_fields param only visible when flag is on

Prompts tested (tool changes only)

  • "Create an issue in github/planning-tracking-demo with Priority P2 and Visibility Medium" → issue_write with issue_fields
  • "Get issue 1992 in github/planning-tracking-demo" → get_issue returns field_values: [{Priority: P2}, {Visibility: Medium}]

Security / limits

  • No security or limits impact

Tool renaming

  • I am not renaming tools as part of this PR

Lint & tests

  • Linted locally with ./script/lint
  • Tested locally with ./script/test

Docs

  • Updated (README / docs / examples)
- Extend FeatureFlagEnable/Disable fields from string to []string (AND
  semantics for enable, OR semantics for disable) so a tool can require
  multiple flags simultaneously.

- Add LegacyIssueWrite: the FeatureFlagIssueFields-disabled variant of
  issue_write. It exposes the pre-issue-fields schema (no issue_fields
  parameter) and skips the custom field value resolution. Both this and
  IssueWrite register under the tool name 'issue_write'; exactly one is
  active at a time via mutually exclusive flag annotations.

- Gate IssueWrite (the flag-enabled variant) with FeatureFlagEnable so
  it is only served when remote_mcp_issue_fields is on.

- Gate the get_issue field_values enrichment with a runtime
  IsFeatureEnabled check so the GraphQL round-trip is skipped when the
  flag is off.

- Add issue_write.snap (legacy) and
  issue_write_ff_remote_mcp_issue_fields.snap (flag-enabled) toolsnaps
  following the convention established by PR github#2520.

- Modernise featureFlagAllowed disableFlags loop to slices.ContainsFunc.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR gates issue-field-related issue_write schema/behavior and get_issue enrichment behind remote_mcp_issue_fields, while expanding inventory feature flag annotations to support multiple flags.

Changes:

  • Converts inventory feature flag annotations from single strings to string slices with AND enable / OR disable semantics.
  • Splits issue_write into legacy and issue-fields-enabled variants with matching toolsnaps and docs.
  • Adds a runtime feature check before get_issue GraphQL field-value enrichment.
Show a summary per file
File Description
README.md Removes issue_fields from default issue_write docs.
pkg/inventory/server_tool.go Updates tool feature flag fields to slices.
pkg/inventory/resources.go Updates resource feature flag fields to slices.
pkg/inventory/prompts.go Updates prompt feature flag fields to slices.
pkg/inventory/filters.go Implements multi-flag filtering semantics.
pkg/inventory/registry_test.go Updates inventory tests for slice-based feature flags.
pkg/http/handler_test.go Updates HTTP inventory tests for slice-based feature flags.
pkg/github/tools.go Registers the legacy issue_write variant.
pkg/github/tools_validation_test.go Updates duplicate-tool validation for slice flags.
pkg/github/pullrequests.go Migrates PR consolidated tools to slice disable flags.
pkg/github/pullrequests_granular.go Migrates PR granular tools to slice enable flags.
pkg/github/issues.go Gates get_issue enrichment and adds legacy/flagged issue_write.
pkg/github/issues_test.go Updates issue tool snapshots/tests for split variants.
pkg/github/issues_granular.go Migrates issue granular tools to slice enable flags.
pkg/github/issue_fields.go Migrates issue-fields tool to slice enable flags.
pkg/github/granular_tools_test.go Updates granular tool tests for slice flags.
pkg/github/csv_output_test.go Updates CSV wrapper tests for slice flags.
pkg/github/toolsnaps/issue_write.snap Updates base issue_write schema to legacy shape.
pkg/github/toolsnaps/issue_write_ff_remote_mcp_issue_fields.snap Adds flagged issue_write schema snapshot.
docs/insiders-features.md Documents flagged issue_write for insiders.
docs/feature-flags.md Documents flagged issue_write under remote_mcp_issue_fields.

Copilot's findings

  • Files reviewed: 21/21 changed files
  • Comments generated: 2
Comment thread pkg/github/issues_granular.go Outdated
Comment thread pkg/inventory/filters.go
@leuasseurfarrelds247-arch

This comment was marked as spam.

@kelsey-myers

Copy link
Copy Markdown
Contributor Author

Testing issue_read and issue_write locally with the flag on and off:

issue_read flag on

Input:

{ "method": "get", "owner": "github", "repo": "planning-tracking-demo", "issue_number": 1993 }

Output:

{
  "number": 1993,
  "title": "[test] flag gating sanity - flag ON",
  "state": "open",
  "issue_type": "Task",
  "field_values": [
    { "field": "Priority", "value": "P3" },
    { "field": "Visibility", "value": "Low" }
  ]
}

issue_read flag off

Input:

{ "method": "get", "owner": "github", "repo": "planning-tracking-demo", "issue_number": 1993 }

Output:

{
  "number": 1993,
  "title": "[test] flag gating sanity - flag ON",
  "state": "open",
  "issue_type": "Task"
}

For issue_write, fields are not applied when the flag is off.

@kelsey-myers kelsey-myers marked this pull request as ready for review May 26, 2026 23:20
@kelsey-myers kelsey-myers requested a review from a team as a code owner May 26, 2026 23:20
@SamMorrowDrums SamMorrowDrums merged commit 546a66a into github:kelsey/issue-fields-clean May 27, 2026
10 checks passed
SamMorrowDrums added a commit that referenced this pull request May 28, 2026
Ports the gating from PR #2553 onto main (the original merge landed on a
stack base that did not make it to main).

Changes:
- pkg/inventory: FeatureFlagDisable becomes []string (any-listed-on → hide).
  FeatureFlagEnable stays as a single string. This avoids the AND-of-enable
  semantics from the earlier proposal, which encoded dependencies rather
  than rollout knobs and had no real call site. Disable-OR is the case
  that does need the slice (LegacyIssueWrite below).
- pkg/github/issues.go: split IssueWrite into IssueWrite (flag-enabled,
  exposes issue_fields) and LegacyIssueWrite (flag-disabled, omits it).
  Both register as 'issue_write'; mutually exclusive flag annotations
  pick exactly one at runtime. Refactored into a shared buildIssueWrite
  helper instead of duplicating the ~250-line tool definition.
- pkg/github/issues.go: GetIssue field_values enrichment now requires
  the flag at runtime. The verbose REST IssueFieldValues is always
  cleared from the response.
- Existing single-flag Disable call sites converted to slices.
- New toolsnap variant issue_write_ff_remote_mcp_issue_fields.snap; the
  canonical issue_write.snap is owned by LegacyIssueWrite.
- README + flag docs regenerated.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

4 participants