Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ runtime behavior (such as output formatting) won't appear here.
- `assignees`: Usernames to assign to this issue (string[], optional)
- `body`: Issue body content (string, optional)
- `duplicate_of`: Issue number that this issue is a duplicate of. Only used when state_reason is 'duplicate'. (number, optional)
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', or 'delete: true'. (object[], optional)
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', 'field_option_names', or 'delete: true'. (object[], optional)
- `issue_number`: Issue number to update (number, optional)
- `labels`: Labels to apply to this issue (string[], optional)
- `method`: Write operation to perform on a single issue.
Expand All @@ -104,7 +104,7 @@ runtime behavior (such as output formatting) won't appear here.
- **Required OAuth Scopes**: `repo`
- `after`: Cursor for pagination. Use the endCursor from the previous page's PageInfo for GraphQL APIs. (string, optional)
- `direction`: Order direction. If provided, the 'orderBy' also needs to be provided. (string, optional)
- `field_filters`: Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date). (object[], optional)
- `field_filters`: Filter by custom issue field values. Each entry takes a field_name and either 'value' (text, number, YYYY-MM-DD date, or single-select option name) or 'values' (multi-select option names). For multi-select fields, all listed values must be set on an issue for it to match (AND semantics) — to match any-of, make multiple list_issues calls and union the results. (object[], optional)
- `labels`: Filter by labels (string[], optional)
- `orderBy`: Order issues by field. If provided, the 'direction' also needs to be provided. (string, optional)
- `owner`: Repository owner (string, required)
Expand Down
4 changes: 2 additions & 2 deletions docs/insiders-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The list below is generated from the Go source. It covers tool **inventory and s
- `assignees`: Usernames to assign to this issue (string[], optional)
- `body`: Issue body content (string, optional)
- `duplicate_of`: Issue number that this issue is a duplicate of. Only used when state_reason is 'duplicate'. (number, optional)
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', or 'delete: true'. (object[], optional)
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', 'field_option_names', or 'delete: true'. (object[], optional)
- `issue_number`: Issue number to update (number, optional)
- `labels`: Labels to apply to this issue (string[], optional)
- `method`: Write operation to perform on a single issue.
Expand All @@ -98,7 +98,7 @@ The list below is generated from the Go source. It covers tool **inventory and s
- **Required OAuth Scopes**: `repo`
- `after`: Cursor for pagination. Use the endCursor from the previous page's PageInfo for GraphQL APIs. (string, optional)
- `direction`: Order direction. If provided, the 'orderBy' also needs to be provided. (string, optional)
- `field_filters`: Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date). (object[], optional)
- `field_filters`: Filter by custom issue field values. Each entry takes a field_name and either 'value' (text, number, YYYY-MM-DD date, or single-select option name) or 'values' (multi-select option names). For multi-select fields, all listed values must be set on an issue for it to match (AND semantics) — to match any-of, make multiple list_issues calls and union the results. (object[], optional)
- `labels`: Filter by labels (string[], optional)
- `orderBy`: Order issues by field. If provided, the 'direction' also needs to be provided. (string, optional)
- `owner`: Repository owner (string, required)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
"type": "number"
},
"issue_fields": {
"description": "Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', or 'delete: true'.",
"description": "Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', 'field_option_names', or 'delete: true'.",
"items": {
"additionalProperties": false,
"properties": {
"delete": {
"description": "Set to true to clear this field's current value on the issue. Cannot be combined with 'value' or 'field_option_name'.",
"description": "Set to true to clear this field's current value on the issue. Cannot be combined with 'value', 'field_option_name', or 'field_option_names'.",
"enum": [
true
],
Expand All @@ -46,11 +46,18 @@
"type": "string"
},
"field_option_name": {
"description": "Option name for single-select fields. Validated against the field's options before the API call. Cannot be combined with 'value' or 'delete'.",
"description": "Option name for single-select fields. Validated against the field's options before the API call. Cannot be combined with 'value', 'field_option_names', or 'delete'.",
"type": "string"
},
"field_option_names": {
"description": "Option names for multi-select fields. All names are validated against the field's options before the API call. An empty array is rejected — use 'delete: true' to clear the field. Cannot be combined with 'value', 'field_option_name', or 'delete'.",
"items": {
"type": "string"
},
"type": "array"
},
"value": {
"description": "Value to set. Use for text, number, and date fields (date as YYYY-MM-DD). For single-select fields, prefer 'field_option_name' so the option is validated before the API call. Cannot be combined with 'field_option_name' or 'delete'.",
"description": "Value to set. Use for text, number, and date fields (date as YYYY-MM-DD). For single-select fields, prefer 'field_option_name' so the option is validated before the API call. Cannot be combined with 'field_option_name', 'field_option_names', or 'delete'.",
"type": [
"string",
"number",
Expand Down
2 changes: 1 addition & 1 deletion pkg/github/__toolsnaps__/list_issue_fields.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"readOnlyHint": true,
"title": "List issue fields"
},
"description": "List issue fields for a repository or organization. Returns field definitions including name, type (text, number, date, single_select), and for single_select fields the list of valid option names. When repo is omitted, returns org-level fields directly.",
"description": "List issue fields for a repository or organization. Returns field definitions including name, type (text, number, date, single_select, multi_select), and for single_select and multi_select fields the list of valid option names. When repo is omitted, returns org-level fields directly.",
"inputSchema": {
"properties": {
"owner": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,27 @@
"type": "string"
},
"field_filters": {
"description": "Filter by custom issue field values. Each entry takes a field_name and a value; the server looks up the field and coerces the value to its type (single-select option name, text, number, or YYYY-MM-DD date).",
"description": "Filter by custom issue field values. Each entry takes a field_name and either 'value' (text, number, YYYY-MM-DD date, or single-select option name) or 'values' (multi-select option names). For multi-select fields, all listed values must be set on an issue for it to match (AND semantics) — to match any-of, make multiple list_issues calls and union the results.",
"items": {
"properties": {
"field_name": {
"description": "Name of the custom field (e.g. \"Priority\"). Case-insensitive.",
"type": "string"
},
"value": {
"description": "Value to filter on. For single-select fields, the option name (e.g. \"P1\"). For dates, YYYY-MM-DD. For numbers, the numeric value as a string. For text, the text value.",
"description": "Value to filter on for text, number, date, or single-select fields. For single-select, the option name (e.g. \"P1\"). For dates, YYYY-MM-DD. For numbers, the numeric value as a string. For text, the text value. Cannot be combined with 'values'.",
"type": "string"
},
"values": {
"description": "Option names to filter on for multi-select fields. Matches issues that have ALL of these options set (AND semantics). To match any-of, make multiple list_issues calls. Cannot be combined with 'value'.",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"field_name",
"value"
"field_name"
],
"type": "object"
},
Expand Down
37 changes: 36 additions & 1 deletion pkg/github/issue_fields.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ type issueFieldNode struct {
Priority *int
}
} `graphql:"... on IssueFieldSingleSelect"`
IssueFieldMultiSelect struct {
ID githubv4.ID
FullDatabaseID githubv4.String `graphql:"fullDatabaseId"`
Name githubv4.String
Description githubv4.String
DataType githubv4.String
Visibility githubv4.String
Options []struct {
ID githubv4.ID
Name githubv4.String
Description githubv4.String
Color githubv4.String
Priority *int
}
} `graphql:"... on IssueFieldMultiSelect"`
}

// issueFieldsRepoQuery is the GraphQL query for listing issue fields on a repository.
Expand Down Expand Up @@ -109,7 +124,7 @@ func ListIssueFields(t translations.TranslationHelperFunc) inventory.ServerTool
ToolsetMetadataIssues,
mcp.Tool{
Name: "list_issue_fields",
Description: t("TOOL_LIST_ISSUE_FIELDS_DESCRIPTION", "List issue fields for a repository or organization. Returns field definitions including name, type (text, number, date, single_select), and for single_select fields the list of valid option names. When repo is omitted, returns org-level fields directly."),
Description: t("TOOL_LIST_ISSUE_FIELDS_DESCRIPTION", "List issue fields for a repository or organization. Returns field definitions including name, type (text, number, date, single_select, multi_select), and for single_select and multi_select fields the list of valid option names. When repo is omitted, returns org-level fields directly."),
Annotations: &mcp.ToolAnnotations{
Title: t("TOOL_LIST_ISSUE_FIELDS_USER_TITLE", "List issue fields"),
ReadOnlyHint: true,
Expand Down Expand Up @@ -215,6 +230,26 @@ func issueFieldsFromNodes(nodes []issueFieldNode) []IssueField {
Visibility: string(node.IssueFieldSingleSelect.Visibility),
Options: opts,
}
case "IssueFieldMultiSelect":
opts := make([]IssueSingleSelectFieldOption, 0, len(node.IssueFieldMultiSelect.Options))
for _, o := range node.IssueFieldMultiSelect.Options {
opts = append(opts, IssueSingleSelectFieldOption{
ID: fmt.Sprintf("%v", o.ID),
Name: string(o.Name),
Description: string(o.Description),
Color: string(o.Color),
Priority: o.Priority,
})
}
f = IssueField{
ID: fmt.Sprintf("%v", node.IssueFieldMultiSelect.ID),
DatabaseID: parseFullDatabaseID(string(node.IssueFieldMultiSelect.FullDatabaseID)),
Name: string(node.IssueFieldMultiSelect.Name),
Description: string(node.IssueFieldMultiSelect.Description),
DataType: string(node.IssueFieldMultiSelect.DataType),
Visibility: string(node.IssueFieldMultiSelect.Visibility),
Options: opts,
}
case "IssueFieldText":
f = IssueField{
ID: fmt.Sprintf("%v", node.IssueFieldText.ID),
Expand Down
Loading
Loading