@@ -34,36 +34,6 @@ type CloseIssueInput struct {
3434// Used to extend the functionality of the githubv4 library to support closing issues as duplicates.
3535type IssueClosedStateReason string
3636
37- // IssueWriteFieldInput is a user-friendly issue field input for issue_write.
38- // Field IDs and option IDs are resolved internally before calling the REST API.
39- type IssueWriteFieldInput struct {
40- FieldName string
41- Value any
42- FieldOptionName string
43- }
44-
45- type issueFieldMetadataOption struct {
46- DatabaseID githubv4.Int `graphql:"databaseId"`
47- Name githubv4.String
48- }
49-
50- type issueFieldMetadataNode struct {
51- DatabaseID githubv4.Int `graphql:"databaseId"`
52- Name githubv4.String
53- DataType githubv4.String
54- SingleSelectField struct {
55- Options []issueFieldMetadataOption `graphql:"options"`
56- } `graphql:"... on IssueFieldSingleSelect"`
57- }
58-
59- type issueFieldMetadataQuery struct {
60- Repository struct {
61- IssueFields struct {
62- Nodes []issueFieldMetadataNode
63- } `graphql:"issueFields(first: 100)"`
64- } `graphql:"repository(owner: $owner, name: $repo)"`
65- }
66-
6737const (
6838 IssueClosedStateReasonCompleted IssueClosedStateReason = "COMPLETED"
6939 IssueClosedStateReasonDuplicate IssueClosedStateReason = "DUPLICATE"
@@ -132,127 +102,6 @@ func getCloseStateReason(stateReason string) IssueClosedStateReason {
132102 }
133103}
134104
135- func optionalIssueWriteFields (args map [string ]any ) ([]IssueWriteFieldInput , error ) {
136- issueFieldsRaw , exists := args ["issue_fields" ]
137- if ! exists {
138- return nil , nil
139- }
140-
141- var inputMaps []map [string ]any
142- switch v := issueFieldsRaw .(type ) {
143- case []any :
144- for _ , item := range v {
145- itemMap , ok := item .(map [string ]any )
146- if ! ok {
147- return nil , fmt .Errorf ("each issue_fields item must be an object" )
148- }
149- inputMaps = append (inputMaps , itemMap )
150- }
151- case []map [string ]any :
152- inputMaps = v
153- default :
154- return nil , fmt .Errorf ("issue_fields must be an array" )
155- }
156-
157- issueFields := make ([]IssueWriteFieldInput , 0 , len (inputMaps ))
158- for _ , itemMap := range inputMaps {
159- fieldName , err := RequiredParam [string ](itemMap , "field_name" )
160- if err != nil || strings .TrimSpace (fieldName ) == "" {
161- return nil , fmt .Errorf ("field_name is required for each issue_fields item" )
162- }
163-
164- fieldOptionName , err := OptionalParam [string ](itemMap , "field_option_name" )
165- if err != nil {
166- return nil , err
167- }
168-
169- value , hasValue := itemMap ["value" ]
170- if hasValue && value == nil {
171- return nil , fmt .Errorf ("value cannot be null for field %q" , fieldName )
172- }
173-
174- if hasValue && fieldOptionName != "" {
175- return nil , fmt .Errorf ("issue field %q cannot specify both value and field_option_name" , fieldName )
176- }
177-
178- if ! hasValue && fieldOptionName == "" {
179- return nil , fmt .Errorf ("issue field %q must specify either value or field_option_name" , fieldName )
180- }
181-
182- issueFields = append (issueFields , IssueWriteFieldInput {
183- FieldName : fieldName ,
184- Value : value ,
185- FieldOptionName : fieldOptionName ,
186- })
187- }
188-
189- return issueFields , nil
190- }
191-
192- func resolveIssueRequestFieldValues (ctx context.Context , gqlClient * githubv4.Client , owner , repo string , issueFields []IssueWriteFieldInput ) ([]* github.IssueRequestFieldValue , error ) {
193- if len (issueFields ) == 0 {
194- return nil , nil
195- }
196-
197- query := issueFieldMetadataQuery {}
198- vars := map [string ]any {
199- "owner" : githubv4 .String (owner ),
200- "repo" : githubv4 .String (repo ),
201- }
202- if err := gqlClient .Query (ctx , & query , vars ); err != nil {
203- return nil , fmt .Errorf ("failed to query issue fields metadata: %w" , err )
204- }
205-
206- fieldByName := make (map [string ]issueFieldMetadataNode , len (query .Repository .IssueFields .Nodes ))
207- for _ , field := range query .Repository .IssueFields .Nodes {
208- fieldByName [strings .ToLower (strings .TrimSpace (string (field .Name )))] = field
209- }
210-
211- resolved := make ([]* github.IssueRequestFieldValue , 0 , len (issueFields ))
212- for _ , fieldInput := range issueFields {
213- field , ok := fieldByName [strings .ToLower (strings .TrimSpace (fieldInput .FieldName ))]
214- if ! ok {
215- return nil , fmt .Errorf ("issue field %q was not found in %s/%s" , fieldInput .FieldName , owner , repo )
216- }
217-
218- fieldID := int64 (field .DatabaseID )
219- if fieldID == 0 {
220- return nil , fmt .Errorf ("issue field %q is missing databaseId" , fieldInput .FieldName )
221- }
222-
223- resolvedValue := fieldInput .Value
224- if fieldInput .FieldOptionName != "" {
225- if ! strings .EqualFold (string (field .DataType ), "single_select" ) {
226- return nil , fmt .Errorf ("issue field %q is %q, so field_option_name cannot be used" , fieldInput .FieldName , field .DataType )
227- }
228-
229- optionFound := false
230- for _ , option := range field .SingleSelectField .Options {
231- if strings .EqualFold (strings .TrimSpace (string (option .Name )), strings .TrimSpace (fieldInput .FieldOptionName )) {
232- optionID := int64 (option .DatabaseID )
233- if optionID == 0 {
234- return nil , fmt .Errorf ("issue field option %q on field %q is missing databaseId" , fieldInput .FieldOptionName , fieldInput .FieldName )
235- }
236- resolvedValue = optionID
237- optionFound = true
238- break
239- }
240- }
241-
242- if ! optionFound {
243- return nil , fmt .Errorf ("issue field option %q was not found for field %q" , fieldInput .FieldOptionName , fieldInput .FieldName )
244- }
245- }
246-
247- resolved = append (resolved , & github.IssueRequestFieldValue {
248- FieldID : fieldID ,
249- Value : resolvedValue ,
250- })
251- }
252-
253- return resolved , nil
254- }
255-
256105// IssueFragment represents a fragment of an issue node in the GraphQL API.
257106type IssueFragment struct {
258107 Number githubv4.Int
@@ -1204,27 +1053,6 @@ Options are:
12041053 Type : "number" ,
12051054 Description : "Issue number that this issue is a duplicate of. Only used when state_reason is 'duplicate'." ,
12061055 },
1207- "issue_fields" : {
1208- Type : "array" ,
1209- Description : "Issue field values to set. Each item requires field_name and either value or field_option_name. field_option_name is for single-select fields and is resolved to the corresponding option ID automatically." ,
1210- Items : & jsonschema.Schema {
1211- Type : "object" ,
1212- Properties : map [string ]* jsonschema.Schema {
1213- "field_name" : {
1214- Type : "string" ,
1215- Description : "Issue field name" ,
1216- },
1217- "value" : {
1218- Description : "Value for text/number/date/single-select fields. For single-select, you can use field_option_name instead." ,
1219- },
1220- "field_option_name" : {
1221- Type : "string" ,
1222- Description : "Single-select option name to resolve and set for the field" ,
1223- },
1224- },
1225- Required : []string {"field_name" },
1226- },
1227- },
12281056 },
12291057 Required : []string {"method" , "owner" , "repo" },
12301058 },
@@ -1326,11 +1154,6 @@ Options are:
13261154 return utils .NewToolResultError ("duplicate_of can only be used when state_reason is 'duplicate'" ), nil , nil
13271155 }
13281156
1329- issueFields , err := optionalIssueWriteFields (args )
1330- if err != nil {
1331- return utils .NewToolResultError (err .Error ()), nil , nil
1332- }
1333-
13341157 client , err := deps .GetClient (ctx )
13351158 if err != nil {
13361159 return utils .NewToolResultErrorFromErr ("failed to get GitHub client" , err ), nil , nil
@@ -1341,21 +1164,16 @@ Options are:
13411164 return utils .NewToolResultErrorFromErr ("failed to get GraphQL client" , err ), nil , nil
13421165 }
13431166
1344- issueFieldValues , err := resolveIssueRequestFieldValues (ctx , gqlClient , owner , repo , issueFields )
1345- if err != nil {
1346- return utils .NewToolResultError (fmt .Sprintf ("failed to resolve issue_fields: %v" , err )), nil , nil
1347- }
1348-
13491167 switch method {
13501168 case "create" :
1351- result , err := CreateIssue (ctx , client , owner , repo , title , body , assignees , labels , milestoneNum , issueType , issueFieldValues )
1169+ result , err := CreateIssue (ctx , client , owner , repo , title , body , assignees , labels , milestoneNum , issueType )
13521170 return result , nil , err
13531171 case "update" :
13541172 issueNumber , err := RequiredInt (args , "issue_number" )
13551173 if err != nil {
13561174 return utils .NewToolResultError (err .Error ()), nil , nil
13571175 }
1358- result , err := UpdateIssue (ctx , client , gqlClient , owner , repo , issueNumber , title , body , assignees , labels , milestoneNum , issueType , issueFieldValues , state , stateReason , duplicateOf )
1176+ result , err := UpdateIssue (ctx , client , gqlClient , owner , repo , issueNumber , title , body , assignees , labels , milestoneNum , issueType , state , stateReason , duplicateOf )
13591177 return result , nil , err
13601178 default :
13611179 return utils .NewToolResultError ("invalid method, must be either 'create' or 'update'" ), nil , nil
@@ -1365,18 +1183,17 @@ Options are:
13651183 return st
13661184}
13671185
1368- func CreateIssue (ctx context.Context , client * github.Client , owner string , repo string , title string , body string , assignees []string , labels []string , milestoneNum int , issueType string , issueFieldValues [] * github. IssueRequestFieldValue ) (* mcp.CallToolResult , error ) {
1186+ func CreateIssue (ctx context.Context , client * github.Client , owner string , repo string , title string , body string , assignees []string , labels []string , milestoneNum int , issueType string ) (* mcp.CallToolResult , error ) {
13691187 if title == "" {
13701188 return utils .NewToolResultError ("missing required parameter: title" ), nil
13711189 }
13721190
13731191 // Create the issue request
13741192 issueRequest := & github.IssueRequest {
1375- Title : github .Ptr (title ),
1376- Body : github .Ptr (body ),
1377- Assignees : & assignees ,
1378- Labels : & labels ,
1379- IssueFieldValues : issueFieldValues ,
1193+ Title : github .Ptr (title ),
1194+ Body : github .Ptr (body ),
1195+ Assignees : & assignees ,
1196+ Labels : & labels ,
13801197 }
13811198
13821199 if milestoneNum != 0 {
@@ -1419,7 +1236,7 @@ func CreateIssue(ctx context.Context, client *github.Client, owner string, repo
14191236 return utils .NewToolResultText (string (r )), nil
14201237}
14211238
1422- func UpdateIssue (ctx context.Context , client * github.Client , gqlClient * githubv4.Client , owner string , repo string , issueNumber int , title string , body string , assignees []string , labels []string , milestoneNum int , issueType string , issueFieldValues [] * github. IssueRequestFieldValue , state string , stateReason string , duplicateOf int ) (* mcp.CallToolResult , error ) {
1239+ func UpdateIssue (ctx context.Context , client * github.Client , gqlClient * githubv4.Client , owner string , repo string , issueNumber int , title string , body string , assignees []string , labels []string , milestoneNum int , issueType string , state string , stateReason string , duplicateOf int ) (* mcp.CallToolResult , error ) {
14231240 // Create the issue request with only provided fields
14241241 issueRequest := & github.IssueRequest {}
14251242
@@ -1448,10 +1265,6 @@ func UpdateIssue(ctx context.Context, client *github.Client, gqlClient *githubv4
14481265 issueRequest .Type = github .Ptr (issueType )
14491266 }
14501267
1451- if len (issueFieldValues ) > 0 {
1452- issueRequest .IssueFieldValues = issueFieldValues
1453- }
1454-
14551268 updatedIssue , resp , err := client .Issues .Edit (ctx , owner , repo , issueNumber , issueRequest )
14561269 if err != nil {
14571270 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
0 commit comments