Add custom field filtering to list_issues#2480
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Adds custom field filtering to list_issues by threading an issueFieldValues GraphQL variable through all four ListIssuesQuery* variants and opting into the issue_fields GraphQL feature flag via header. A new field_filters array parameter accepts entries with field_name plus exactly one typed value (single-select/text/number/date), enforced by a new parseFieldFilters helper.
Changes:
- New
IssueFieldValueFilterstruct andfield_filtersMCP parameter onlist_issues, withparseFieldFiltersvalidating exactly one typed value per entry (treatingnumber_value: 0as set). - All four
ListIssuesQuery*variants now includefilterBy: {issueFieldValues: $issueFieldValues}; the variable is always sent (empty slice = no-op) and the request context carriesGraphQL-Features: issue_fields. - Comprehensive unit tests for each query variant, each typed value, validation errors, the
number_value: 0edge case, and aGraphQL-Featuresheader regression guard.
Show a summary per file
| File | Description |
|---|---|
| pkg/github/issues.go | Adds IssueFieldValueFilter, field_filters schema, parseFieldFilters, threads issueFieldValues and feature header through list_issues. |
| pkg/github/issues_test.go | Updates existing test vars/queries and adds Test_ListIssues_FieldFilters covering all variants, validation, and header behavior. |
| pkg/github/toolsnaps/list_issues.snap | Toolsnap regenerated to include the new field_filters schema. |
| README.md | Auto-generated doc entry for the new field_filters parameter. |
Copilot's findings
- Files reviewed: 4/4 changed files
- Comments generated: 0
a66606f to
c77ac79
Compare
| "single_select_value": { | ||
| Type: "string", | ||
| Description: "For single-select fields, the option name to match (e.g. \"P1\").", | ||
| }, | ||
| "text_value": { | ||
| Type: "string", | ||
| Description: "For text fields, the text value to match.", | ||
| }, | ||
| "number_value": { | ||
| Type: "number", | ||
| Description: "For number fields, the numeric value to match.", | ||
| }, | ||
| "date_value": { | ||
| Type: "string", | ||
| Description: "For date fields, the date to match (YYYY-MM-DD).", | ||
| }, |
There was a problem hiding this comment.
Can't we do the same we did on the other side, and collapse this into a single input field? Tool schema is expensive (in terms of tokens for models). so I'd rather have a singular value field, and then look up the field to determine the right place to put the value.
|
Did some testing with the updated schema:
Inputs & outputsRepos used: Single-select — match { "owner": "lemongrasss", "repo": "ubiquitous-octo-waffle",
"field_filters": [{ "field_name": "Animal", "value": "Tiger" }] }Single-select — case-insensitive field name, no match { "field_filters": [{ "field_name": "animal", "value": "Lion" }] }→ Single-select — match against github/issues { "owner": "github", "repo": "issues",
"field_filters": [{ "field_name": "Priority", "value": "P1" }] }→ 1 issue. Text — match { "field_filters": [{ "field_name": "DRI", "value": "valid-name" }] }→ 1 issue with Text — no match { "field_filters": [{ "field_name": "DRI", "value": "kelsey-myers" }] }→ Number — match { "field_filters": [{ "field_name": "Engineering Staffing", "value": "1" }] }→ multiple matches. Date — match { "field_filters": [{ "field_name": "Target Date", "value": "2026-04-07" }] }→ 1 issue with Error — invalid date { "field_filters": [{ "field_name": "Target Date", "value": "04/07/2026" }] }→ Error — unknown field { "field_filters": [{ "field_name": "NotARealField", "value": "x" }] }→ Error — non-numeric value for number field { "field_filters": [{ "field_name": "Engineering Staffing", "value": "not-a-number" }] }→ |
Summary
Extend
list_issuesso callers can filter issues by custom field values (single-select, text, number, date) alongside the existing label, state, andsincefilters.Why
The
IssueFilters.issueFieldValuesargument is available in the GraphQL schema (gated by theissue_fieldsfeature flag) and the existinglist_issuestool returns field values on each issue, but there was no way to filter by them. Without this, agents have to fetch all issues and filter client-side which doesn't scale and is wasteful.Stacked on top of #2466 — will retarget once that merges. Until then this PR shows both sets of commits.
What changed
field_filtersarray parameter tolist_issues. Each entry takes afield_nameplus exactly one ofsingle_select_value,text_value,number_value, ordate_value.ListIssuesQuery*variants via a newissueFieldValuesGraphQL variable. The variable is always sent (empty slice when no filters are supplied), the resolver treats an empty list as a no-op.parseFieldFiltershelper that validates exactly one typed value per filter and propagates type errors uniformly.GraphQL-Features: issue_fieldson outgoing requests via the existingGraphQLFeaturesTransportso the gated input type resolves while the flag is still rolling out. Safe to keep after rollout (no-op).number_value: 0(must be treated as set), and a regression guard that theGraphQL-Featuresheader is sent.MCP impact
list_issuesgains an optionalfield_filtersparameter. Default behaviour (nofield_filters) is unchanged.Prompts tested (tool changes only)
sincepath (regression)github/issuesSecurity / limits
No new auth surface. Uses the same scopes as
list_issuestoday. TheGraphQL-Featuresheader opts into a schema-level feature flag and does not bypass any authorization.Tool renaming
Lint & tests
./script/lint./script/testDocs
script/generate-docsregeneratedREADME.mdand thelist_issuestoolsnap.