(ctx context.Context, client *githubv4.Client, args map[string]any)
| 758 | } |
| 759 | |
| 760 | func replyToDiscussionComment(ctx context.Context, client *githubv4.Client, args map[string]any) (*mcp.CallToolResult, any, error) { |
| 761 | commentNodeID, err := requiredCommentNodeID(args) |
| 762 | if err != nil { |
| 763 | return utils.NewToolResultError(err.Error()), nil, nil |
| 764 | } |
| 765 | |
| 766 | owner, err := RequiredParam[string](args, "owner") |
| 767 | if err != nil { |
| 768 | return utils.NewToolResultError(err.Error()), nil, nil |
| 769 | } |
| 770 | repo, err := RequiredParam[string](args, "repo") |
| 771 | if err != nil { |
| 772 | return utils.NewToolResultError(err.Error()), nil, nil |
| 773 | } |
| 774 | discussionNumber, err := RequiredInt(args, "discussionNumber") |
| 775 | if err != nil { |
| 776 | return utils.NewToolResultError(err.Error()), nil, nil |
| 777 | } |
| 778 | body, err := RequiredParam[string](args, "body") |
| 779 | if err != nil { |
| 780 | return utils.NewToolResultError(err.Error()), nil, nil |
| 781 | } |
| 782 | |
| 783 | // The GitHub API silently ignores an invalid ReplyToID and creates a top-level |
| 784 | // comment instead of returning an error, so we validate upfront that the node |
| 785 | // exists and is a DiscussionComment to give callers a clear failure. |
| 786 | var nodeQuery struct { |
| 787 | Node struct { |
| 788 | DiscussionComment struct { |
| 789 | ID *githubv4.ID |
| 790 | Discussion struct { |
| 791 | ID githubv4.ID |
| 792 | } `graphql:"discussion"` |
| 793 | } `graphql:"... on DiscussionComment"` |
| 794 | } `graphql:"node(id: $replyToID)"` |
| 795 | } |
| 796 | if err := client.Query(ctx, &nodeQuery, map[string]any{ |
| 797 | "replyToID": githubv4.ID(commentNodeID), |
| 798 | }); err != nil { |
| 799 | return utils.NewToolResultError(fmt.Sprintf("failed to validate commentNodeID: %v", err)), nil, nil |
| 800 | } |
| 801 | if nodeQuery.Node.DiscussionComment.ID == nil || *nodeQuery.Node.DiscussionComment.ID == "" { |
| 802 | return utils.NewToolResultError(fmt.Sprintf("commentNodeID %q does not resolve to a valid discussion comment", commentNodeID)), nil, nil |
| 803 | } |
| 804 | |
| 805 | // Get the discussion's node ID using its number |
| 806 | var q struct { |
| 807 | Repository struct { |
| 808 | Discussion struct { |
| 809 | ID githubv4.ID |
| 810 | } `graphql:"discussion(number: $discussionNumber)"` |
| 811 | } `graphql:"repository(owner: $owner, name: $repo)"` |
| 812 | } |
| 813 | vars := map[string]any{ |
| 814 | "owner": githubv4.String(owner), |
| 815 | "repo": githubv4.String(repo), |
| 816 | "discussionNumber": githubv4.Int(discussionNumber), // #nosec G115 - discussion numbers are always small positive integers |
| 817 | } |
no test coverage detected