@@ -69,13 +69,13 @@ func ListProjects(getClient GetClientFn, t translations.TranslationHelperFunc) (
6969
7070 var resp * github.Response
7171 var projects []* github.ProjectV2
72- minimalProjects := []MinimalProject {}
73-
7472 var queryPtr * string
73+
7574 if queryStr != "" {
7675 queryPtr = & queryStr
7776 }
7877
78+ minimalProjects := []MinimalProject {}
7979 opts := & github.ListProjectsOptions {
8080 ListProjectsPaginationOptions : github.ListProjectsPaginationOptions {PerPage : & perPage },
8181 Query : queryPtr ,
@@ -237,27 +237,19 @@ func ListProjectFields(getClient GetClientFn, t translations.TranslationHelperFu
237237 return mcp .NewToolResultError (err .Error ()), nil
238238 }
239239
240- var url string
241- if ownerType == "org" {
242- url = fmt .Sprintf ("orgs/%s/projectsV2/%d/fields" , owner , projectNumber )
243- } else {
244- url = fmt .Sprintf ("users/%s/projectsV2/%d/fields" , owner , projectNumber )
245- }
246- projectFields := []projectV2Field {}
247-
248- opts := paginationOptions {PerPage : perPage }
240+ var resp * github.Response
241+ var projectFields []* github.ProjectV2Field
249242
250- url , err = addOptions (url , opts )
251- if err != nil {
252- return nil , fmt .Errorf ("failed to add options to request: %w" , err )
243+ opts := & github.ListProjectsOptions {
244+ ListProjectsPaginationOptions : github.ListProjectsPaginationOptions {PerPage : & perPage },
253245 }
254246
255- httpRequest , err := client .NewRequest ("GET" , url , nil )
256- if err != nil {
257- return nil , fmt .Errorf ("failed to create request: %w" , err )
247+ if ownerType == "org" {
248+ projectFields , resp , err = client .Projects .ListOrganizationProjectFields (ctx , owner , projectNumber , opts )
249+ } else {
250+ projectFields , resp , err = client .Projects .ListUserProjectFields (ctx , owner , projectNumber , opts )
258251 }
259252
260- resp , err := client .Do (ctx , httpRequest , & projectFields )
261253 if err != nil {
262254 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
263255 "failed to list project fields" ,
@@ -317,7 +309,7 @@ func GetProjectField(getClient GetClientFn, t translations.TranslationHelperFunc
317309 if err != nil {
318310 return mcp .NewToolResultError (err .Error ()), nil
319311 }
320- fieldID , err := RequiredInt (req , "field_id" )
312+ fieldID , err := RequiredBigInt (req , "field_id" )
321313 if err != nil {
322314 return mcp .NewToolResultError (err .Error ()), nil
323315 }
@@ -326,21 +318,15 @@ func GetProjectField(getClient GetClientFn, t translations.TranslationHelperFunc
326318 return mcp .NewToolResultError (err .Error ()), nil
327319 }
328320
329- var url string
321+ var resp * github.Response
322+ var projectField * github.ProjectV2Field
323+
330324 if ownerType == "org" {
331- url = fmt . Sprintf ( "orgs/%s/projectsV2/%d/fields/%d" , owner , projectNumber , fieldID )
325+ projectField , resp , err = client . Projects . GetOrganizationProjectField ( ctx , owner , projectNumber , fieldID )
332326 } else {
333- url = fmt . Sprintf ( "users/%s/projectsV2/%d/fields/%d" , owner , projectNumber , fieldID )
327+ projectField , resp , err = client . Projects . GetUserProjectField ( ctx , owner , projectNumber , fieldID )
334328 }
335329
336- projectField := projectV2Field {}
337-
338- httpRequest , err := client .NewRequest ("GET" , url , nil )
339- if err != nil {
340- return nil , fmt .Errorf ("failed to create request: %w" , err )
341- }
342-
343- resp , err := client .Do (ctx , httpRequest , & projectField )
344330 if err != nil {
345331 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
346332 "failed to get project field" ,
@@ -416,41 +402,37 @@ func ListProjectItems(getClient GetClientFn, t translations.TranslationHelperFun
416402 if err != nil {
417403 return mcp .NewToolResultError (err .Error ()), nil
418404 }
419- fields , err := OptionalStringArrayParam (req , "fields" )
405+ fields , err := OptionalBigIntArrayParam (req , "fields" )
420406 if err != nil {
421407 return mcp .NewToolResultError (err .Error ()), nil
422408 }
423-
424409 client , err := getClient (ctx )
425410 if err != nil {
426411 return mcp .NewToolResultError (err .Error ()), nil
427412 }
428413
429- var url string
430- if ownerType == "org" {
431- url = fmt .Sprintf ("orgs/%s/projectsV2/%d/items" , owner , projectNumber )
432- } else {
433- url = fmt .Sprintf ("users/%s/projectsV2/%d/items" , owner , projectNumber )
434- }
435- projectItems := []projectV2Item {}
414+ var resp * github.Response
415+ var projectItems []* github.ProjectV2Item
416+ var queryPtr * string
436417
437- opts := listProjectItemsOptions {
438- paginationOptions : paginationOptions {PerPage : perPage },
439- filterQueryOptions : filterQueryOptions {Query : queryStr },
440- fieldSelectionOptions : fieldSelectionOptions {Fields : fields },
418+ if queryStr != "" {
419+ queryPtr = & queryStr
441420 }
442421
443- url , err = addOptions (url , opts )
444- if err != nil {
445- return nil , fmt .Errorf ("failed to add options to request: %w" , err )
422+ opts := & github.ListProjectItemsOptions {
423+ Fields : fields ,
424+ ListProjectsOptions : github.ListProjectsOptions {
425+ ListProjectsPaginationOptions : github.ListProjectsPaginationOptions {PerPage : & perPage },
426+ Query : queryPtr ,
427+ },
446428 }
447429
448- httpRequest , err := client .NewRequest ("GET" , url , nil )
449- if err != nil {
450- return nil , fmt .Errorf ("failed to create request: %w" , err )
430+ if ownerType == "org" {
431+ projectItems , resp , err = client .Projects .ListOrganizationProjectItems (ctx , owner , projectNumber , opts )
432+ } else {
433+ projectItems , resp , err = client .Projects .ListUserProjectItems (ctx , owner , projectNumber , opts )
451434 }
452435
453- resp , err := client .Do (ctx , httpRequest , & projectItems )
454436 if err != nil {
455437 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
456438 ProjectListFailedError ,
@@ -518,11 +500,11 @@ func GetProjectItem(getClient GetClientFn, t translations.TranslationHelperFunc)
518500 if err != nil {
519501 return mcp .NewToolResultError (err .Error ()), nil
520502 }
521- itemID , err := RequiredInt (req , "item_id" )
503+ itemID , err := RequiredBigInt (req , "item_id" )
522504 if err != nil {
523505 return mcp .NewToolResultError (err .Error ()), nil
524506 }
525- fields , err := OptionalStringArrayParam (req , "fields" )
507+ fields , err := OptionalBigIntArrayParam (req , "fields" )
526508 if err != nil {
527509 return mcp .NewToolResultError (err .Error ()), nil
528510 }
@@ -624,7 +606,7 @@ func AddProjectItem(getClient GetClientFn, t translations.TranslationHelperFunc)
624606 if err != nil {
625607 return mcp .NewToolResultError (err .Error ()), nil
626608 }
627- itemID , err := RequiredInt (req , "item_id" )
609+ itemID , err := RequiredBigInt (req , "item_id" )
628610 if err != nil {
629611 return mcp .NewToolResultError (err .Error ()), nil
630612 }
@@ -642,24 +624,20 @@ func AddProjectItem(getClient GetClientFn, t translations.TranslationHelperFunc)
642624 return mcp .NewToolResultError (err .Error ()), nil
643625 }
644626
645- var projectsURL string
646- if ownerType == "org" {
647- projectsURL = fmt .Sprintf ("orgs/%s/projectsV2/%d/items" , owner , projectNumber )
648- } else {
649- projectsURL = fmt .Sprintf ("users/%s/projectsV2/%d/items" , owner , projectNumber )
650- }
651-
652- newItem := & newProjectItem {
653- ID : int64 (itemID ),
627+ newItem := & github.AddProjectItemOptions {
628+ ID : itemID ,
654629 Type : toNewProjectType (itemType ),
655630 }
656- httpRequest , err := client .NewRequest ("POST" , projectsURL , newItem )
657- if err != nil {
658- return nil , fmt .Errorf ("failed to create request: %w" , err )
631+
632+ var resp * github.Response
633+ var addedItem * github.ProjectV2Item
634+
635+ if ownerType == "org" {
636+ addedItem , resp , err = client .Projects .AddOrganizationProjectItem (ctx , owner , projectNumber , newItem )
637+ } else {
638+ addedItem , resp , err = client .Projects .AddUserProjectItem (ctx , owner , projectNumber , newItem )
659639 }
660- addedItem := projectV2Item {}
661640
662- resp , err := client .Do (ctx , httpRequest , & addedItem )
663641 if err != nil {
664642 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
665643 ProjectAddFailedError ,
@@ -827,7 +805,7 @@ func DeleteProjectItem(getClient GetClientFn, t translations.TranslationHelperFu
827805 if err != nil {
828806 return mcp .NewToolResultError (err .Error ()), nil
829807 }
830- itemID , err := RequiredInt (req , "item_id" )
808+ itemID , err := RequiredBigInt (req , "item_id" )
831809 if err != nil {
832810 return mcp .NewToolResultError (err .Error ()), nil
833811 }
@@ -836,19 +814,13 @@ func DeleteProjectItem(getClient GetClientFn, t translations.TranslationHelperFu
836814 return mcp .NewToolResultError (err .Error ()), nil
837815 }
838816
839- var projectsURL string
817+ var resp * github. Response
840818 if ownerType == "org" {
841- projectsURL = fmt . Sprintf ( "orgs/%s/projectsV2/%d/items/%d" , owner , projectNumber , itemID )
819+ resp , err = client . Projects . DeleteOrganizationProjectItem ( ctx , owner , projectNumber , itemID )
842820 } else {
843- projectsURL = fmt . Sprintf ( "users/%s/projectsV2/%d/items/%d" , owner , projectNumber , itemID )
821+ resp , err = client . Projects . DeleteUserProjectItem ( ctx , owner , projectNumber , itemID )
844822 }
845823
846- httpRequest , err := client .NewRequest ("DELETE" , projectsURL , nil )
847- if err != nil {
848- return nil , fmt .Errorf ("failed to create request: %w" , err )
849- }
850-
851- resp , err := client .Do (ctx , httpRequest , nil )
852824 if err != nil {
853825 return ghErrors .NewGitHubAPIErrorResponse (ctx ,
854826 ProjectDeleteFailedError ,
@@ -869,9 +841,10 @@ func DeleteProjectItem(getClient GetClientFn, t translations.TranslationHelperFu
869841 }
870842}
871843
872- type newProjectItem struct {
873- ID int64 `json:"id,omitempty"`
874- Type string `json:"type,omitempty"`
844+ type fieldSelectionOptions struct {
845+ // Specific list of field IDs to include in the response. If not provided, only the title field is included.
846+ // The comma tag encodes the slice as comma-separated values: fields=102589,985201,169875
847+ Fields []int64 `url:"fields,omitempty,comma"`
875848}
876849
877850type updateProjectItemPayload struct {
@@ -883,17 +856,6 @@ type updateProjectItem struct {
883856 Value any `json:"value"`
884857}
885858
886- type projectV2Field struct {
887- ID * int64 `json:"id,omitempty"` // The unique identifier for this field.
888- NodeID string `json:"node_id,omitempty"` // The GraphQL node ID for this field.
889- Name string `json:"name,omitempty"` // The display name of the field.
890- DataType string `json:"data_type,omitempty"` // The data type of the field (e.g., "text", "number", "date", "single_select", "multi_select").
891- URL string `json:"url,omitempty"` // The API URL for this field.
892- Options []* any `json:"options,omitempty"` // Available options for single_select and multi_select fields.
893- CreatedAt * github.Timestamp `json:"created_at,omitempty"` // The time when this field was created.
894- UpdatedAt * github.Timestamp `json:"updated_at,omitempty"` // The time when this field was last updated.
895- }
896-
897859type projectV2ItemFieldValue struct {
898860 ID * int64 `json:"id,omitempty"` // The unique identifier for this field.
899861 Name string `json:"name,omitempty"` // The display name of the field.
@@ -931,26 +893,6 @@ type projectV2ItemContent struct {
931893 URL * string `json:"url,omitempty"`
932894}
933895
934- type paginationOptions struct {
935- PerPage int `url:"per_page,omitempty"`
936- }
937-
938- type filterQueryOptions struct {
939- Query string `url:"q,omitempty"`
940- }
941-
942- type fieldSelectionOptions struct {
943- // Specific list of field IDs to include in the response. If not provided, only the title field is included.
944- // Example: fields=102589,985201,169875 or fields[]=102589&fields[]=985201&fields[]=169875
945- Fields []string `url:"fields,omitempty"`
946- }
947-
948- type listProjectItemsOptions struct {
949- paginationOptions
950- filterQueryOptions
951- fieldSelectionOptions
952- }
953-
954896func toNewProjectType (projType string ) string {
955897 switch strings .ToLower (projType ) {
956898 case "issue" :
@@ -994,18 +936,28 @@ func addOptions(s string, opts any) (string, error) {
994936 return s , nil
995937 }
996938
997- u , err := url .Parse (s )
939+ origURL , err := url .Parse (s )
998940 if err != nil {
999941 return s , err
1000942 }
1001943
1002- qs , err := query .Values (opts )
944+ origValues := origURL .Query ()
945+
946+ // Use the github.com/google/go-querystring library to parse the struct
947+ newValues , err := query .Values (opts )
1003948 if err != nil {
1004949 return s , err
1005950 }
1006951
1007- u .RawQuery = qs .Encode ()
1008- return u .String (), nil
952+ // Merge the values
953+ for key , values := range newValues {
954+ for _ , value := range values {
955+ origValues .Add (key , value )
956+ }
957+ }
958+
959+ origURL .RawQuery = origValues .Encode ()
960+ return origURL .String (), nil
1009961}
1010962
1011963func ManageProjectItemsPrompt (t translations.TranslationHelperFunc ) (tool mcp.Prompt , handler server.PromptHandlerFunc ) {
0 commit comments