Skip to content

Commit 39f8045

Browse files
committed
Create 'reprioritize sub-issue' tool
1 parent a0e757a commit 39f8045

File tree

3 files changed

+477
-0
lines changed

3 files changed

+477
-0
lines changed

pkg/github/issues.go

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
471604
func SearchIssues(getClient GetClientFn, t translations.TranslationHelperFunc) (tool mcp.Tool, handler server.ToolHandlerFunc) {
472605
return mcp.NewTool("search_issues",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy