@@ -467,6 +467,139 @@ func RemoveSubIssue(getClient GetClientFn, t translations.TranslationHelperFunc)
467467 }
468468}
469469
470+ // ReprioritizeSubIssue creates a tool to reprioritize a sub-issue to a different position in the parent list.
471+ func ReprioritizeSubIssue (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
472+ return mcp .NewTool ("reprioritize_sub_issue" ,
473+ mcp .WithDescription (t ("TOOL_REPRIORITIZE_SUB_ISSUE_DESCRIPTION" , "Reprioritize a sub-issue to a different position in the parent issue's sub-issue list." )),
474+ mcp .WithToolAnnotation (mcp.ToolAnnotation {
475+ Title : t ("TOOL_REPRIORITIZE_SUB_ISSUE_USER_TITLE" , "Reprioritize sub-issue" ),
476+ ReadOnlyHint : toBoolPtr (false ),
477+ }),
478+ mcp .WithString ("owner" ,
479+ mcp .Required (),
480+ mcp .Description ("Repository owner" ),
481+ ),
482+ mcp .WithString ("repo" ,
483+ mcp .Required (),
484+ mcp .Description ("Repository name" ),
485+ ),
486+ mcp .WithNumber ("issue_number" ,
487+ mcp .Required (),
488+ mcp .Description ("The number of the parent issue" ),
489+ ),
490+ mcp .WithNumber ("sub_issue_id" ,
491+ mcp .Required (),
492+ mcp .Description ("The ID of the sub-issue to reprioritize" ),
493+ ),
494+ mcp .WithNumber ("after_id" ,
495+ mcp .Description ("The ID of the sub-issue to be prioritized after (either after_id OR before_id should be specified)" ),
496+ ),
497+ mcp .WithNumber ("before_id" ,
498+ mcp .Description ("The ID of the sub-issue to be prioritized before (either after_id OR before_id should be specified)" ),
499+ ),
500+ ),
501+ func (ctx context.Context , request mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
502+ owner , err := requiredParam [string ](request , "owner" )
503+ if err != nil {
504+ return mcp .NewToolResultError (err .Error ()), nil
505+ }
506+ repo , err := requiredParam [string ](request , "repo" )
507+ if err != nil {
508+ return mcp .NewToolResultError (err .Error ()), nil
509+ }
510+ issueNumber , err := RequiredInt (request , "issue_number" )
511+ if err != nil {
512+ return mcp .NewToolResultError (err .Error ()), nil
513+ }
514+ subIssueID , err := RequiredInt (request , "sub_issue_id" )
515+ if err != nil {
516+ return mcp .NewToolResultError (err .Error ()), nil
517+ }
518+
519+ // Handle optional positioning parameters
520+ afterID , err := OptionalIntParam (request , "after_id" )
521+ if err != nil {
522+ return mcp .NewToolResultError (err .Error ()), nil
523+ }
524+ beforeID , err := OptionalIntParam (request , "before_id" )
525+ if err != nil {
526+ return mcp .NewToolResultError (err .Error ()), nil
527+ }
528+
529+ // Validate that either after_id or before_id is specified, but not both
530+ if afterID == 0 && beforeID == 0 {
531+ return mcp .NewToolResultError ("either after_id or before_id must be specified" ), nil
532+ }
533+ if afterID != 0 && beforeID != 0 {
534+ return mcp .NewToolResultError ("only one of after_id or before_id should be specified, not both" ), nil
535+ }
536+
537+ client , err := getClient (ctx )
538+ if err != nil {
539+ return nil , fmt .Errorf ("failed to get GitHub client: %w" , err )
540+ }
541+
542+ // Create the request body
543+ requestBody := map [string ]interface {}{
544+ "sub_issue_id" : subIssueID ,
545+ }
546+ if afterID != 0 {
547+ requestBody ["after_id" ] = afterID
548+ }
549+ if beforeID != 0 {
550+ requestBody ["before_id" ] = beforeID
551+ }
552+
553+ // Since the go-github library might not have sub-issues support yet,
554+ // we'll make a direct HTTP request using the client's HTTP client
555+ reqBodyBytes , err := json .Marshal (requestBody )
556+ if err != nil {
557+ return nil , fmt .Errorf ("failed to marshal request body: %w" , err )
558+ }
559+
560+ url := fmt .Sprintf ("%srepos/%s/%s/issues/%d/sub_issues/priority" ,
561+ client .BaseURL .String (), owner , repo , issueNumber )
562+ req , err := http .NewRequestWithContext (ctx , "PATCH" , url , strings .NewReader (string (reqBodyBytes )))
563+ if err != nil {
564+ return nil , fmt .Errorf ("failed to create request: %w" , err )
565+ }
566+
567+ req .Header .Set ("Accept" , "application/vnd.github+json" )
568+ req .Header .Set ("Content-Type" , "application/json" )
569+ req .Header .Set ("X-GitHub-Api-Version" , "2022-11-28" )
570+
571+ // Use the same authentication as the GitHub client
572+ httpClient := client .Client ()
573+ resp , err := httpClient .Do (req )
574+ if err != nil {
575+ return nil , fmt .Errorf ("failed to reprioritize sub-issue: %w" , err )
576+ }
577+ defer func () { _ = resp .Body .Close () }()
578+
579+ body , err := io .ReadAll (resp .Body )
580+ if err != nil {
581+ return nil , fmt .Errorf ("failed to read response body: %w" , err )
582+ }
583+
584+ if resp .StatusCode != http .StatusOK {
585+ return mcp .NewToolResultError (fmt .Sprintf ("failed to reprioritize sub-issue: %s" , string (body ))), nil
586+ }
587+
588+ // Parse and re-marshal to ensure consistent formatting
589+ var result interface {}
590+ if err := json .Unmarshal (body , & result ); err != nil {
591+ return nil , fmt .Errorf ("failed to unmarshal response: %w" , err )
592+ }
593+
594+ r , err := json .Marshal (result )
595+ if err != nil {
596+ return nil , fmt .Errorf ("failed to marshal response: %w" , err )
597+ }
598+
599+ return mcp .NewToolResultText (string (r )), nil
600+ }
601+ }
602+
470603// SearchIssues creates a tool to search for issues and pull requests.
471604func SearchIssues (getClient GetClientFn , t translations.TranslationHelperFunc ) (tool mcp.Tool , handler server.ToolHandlerFunc ) {
472605 return mcp .NewTool ("search_issues" ,
0 commit comments