@@ -1760,17 +1760,34 @@ func UpdatePullRequestBranch(t translations.TranslationHelperFunc) inventory.Ser
17601760}
17611761
17621762type PullRequestReviewWriteParams struct {
1763- Method string
1764- Owner string
1765- Repo string
1766- PullNumber int32
1767- Body string
1768- Event string
1769- CommitID * string
1770- ThreadID string
1763+ Method string
1764+ Owner string
1765+ Repo string
1766+ PullNumber int32
1767+ Body string
1768+ Event string
1769+ CommitID * string
1770+ ThreadID string
1771+ ResolutionReason * string
17711772}
17721773
17731774func PullRequestReviewWrite (t translations.TranslationHelperFunc ) inventory.ServerTool {
1775+ return pullRequestReviewWrite (t , false , toolConfig {})
1776+ }
1777+
1778+ // PullRequestReviewWriteWithResolutionReason creates the feature-gated review write variant with resolution reasons.
1779+ func PullRequestReviewWriteWithResolutionReason (t translations.TranslationHelperFunc , opts ... ToolOption ) inventory.ServerTool {
1780+ cfg := newToolConfig (opts )
1781+ st := pullRequestReviewWrite (t , true , cfg )
1782+ if cfg .hostType == utils .HostTypeGHES {
1783+ st .Enabled = func (context.Context ) (bool , error ) { return false , nil }
1784+ }
1785+ return st
1786+ }
1787+
1788+ func pullRequestReviewWrite (t translations.TranslationHelperFunc , withResolutionReason bool , cfg toolConfig ) inventory.ServerTool {
1789+ withResolutionReason = withResolutionReason && cfg .hostType != utils .HostTypeGHES
1790+
17741791 schema := & jsonschema.Schema {
17751792 Type : "object" ,
17761793 Properties : map [string ]* jsonschema.Schema {
@@ -1814,6 +1831,12 @@ func PullRequestReviewWrite(t translations.TranslationHelperFunc) inventory.Serv
18141831 },
18151832 Required : []string {"method" , "owner" , "repo" , "pullNumber" },
18161833 }
1834+ if withResolutionReason {
1835+ schema .Properties ["resolutionReason" ] = & jsonschema.Schema {
1836+ Type : "string" ,
1837+ Description : "Optional reason for resolving a Copilot code review thread: addressed, wont-fix, or invalid." ,
1838+ }
1839+ }
18171840
18181841 st := NewTool (
18191842 ToolsetMetadataPullRequests ,
@@ -1858,7 +1881,11 @@ Available methods:
18581881 result , err := DeletePendingPullRequestReview (ctx , client , params )
18591882 return result , nil , err
18601883 case "resolve_thread" :
1861- result , err := ResolveReviewThread (ctx , client , params .ThreadID , true )
1884+ if ! withResolutionReason {
1885+ result , err := ResolveReviewThread (ctx , client , params .ThreadID , true )
1886+ return result , nil , err
1887+ }
1888+ result , err := ResolveReviewThreadWithReason (ctx , client , params .ThreadID , params .ResolutionReason , true )
18621889 return result , nil , err
18631890 case "unresolve_thread" :
18641891 result , err := ResolveReviewThread (ctx , client , params .ThreadID , false )
@@ -1867,7 +1894,15 @@ Available methods:
18671894 return utils .NewToolResultError (fmt .Sprintf ("unknown method: %s" , params .Method )), nil , nil
18681895 }
18691896 })
1870- st .FeatureFlagDisable = []string {FeatureFlagPullRequestsGranular }
1897+ if withResolutionReason {
1898+ st .FeatureFlagEnable = FeatureFlagThreadResolutionReason
1899+ st .FeatureFlagDisable = []string {FeatureFlagPullRequestsGranular }
1900+ } else {
1901+ st .FeatureFlagDisable = []string {FeatureFlagPullRequestsGranular }
1902+ if cfg .hostType != utils .HostTypeGHES {
1903+ st .FeatureFlagDisable = append (st .FeatureFlagDisable , FeatureFlagThreadResolutionReason )
1904+ }
1905+ }
18711906 return st
18721907}
18731908
@@ -2094,8 +2129,19 @@ func DeletePendingPullRequestReview(ctx context.Context, client *githubv4.Client
20942129 return utils .NewToolResultText ("pending pull request review successfully deleted" ), nil
20952130}
20962131
2132+ // ResolveReviewThreadInput is the GraphQL input for resolving a review thread.
2133+ type ResolveReviewThreadInput struct {
2134+ ThreadID githubv4.ID `json:"threadId"`
2135+ ResolutionReason * githubv4.String `json:"resolutionReason,omitempty"`
2136+ }
2137+
20972138// ResolveReviewThread resolves or unresolves a PR review thread using GraphQL mutations.
20982139func ResolveReviewThread (ctx context.Context , client * githubv4.Client , threadID string , resolve bool ) (* mcp.CallToolResult , error ) {
2140+ return ResolveReviewThreadWithReason (ctx , client , threadID , nil , resolve )
2141+ }
2142+
2143+ // ResolveReviewThreadWithReason resolves or unresolves a PR review thread with an optional resolution reason.
2144+ func ResolveReviewThreadWithReason (ctx context.Context , client * githubv4.Client , threadID string , resolutionReason * string , resolve bool ) (* mcp.CallToolResult , error ) {
20992145 if threadID == "" {
21002146 return utils .NewToolResultError ("threadId is required for resolve_thread and unresolve_thread methods" ), nil
21012147 }
@@ -2110,8 +2156,9 @@ func ResolveReviewThread(ctx context.Context, client *githubv4.Client, threadID
21102156 } `graphql:"resolveReviewThread(input: $input)"`
21112157 }
21122158
2113- input := githubv4.ResolveReviewThreadInput {
2114- ThreadID : githubv4 .ID (threadID ),
2159+ input := ResolveReviewThreadInput {
2160+ ThreadID : githubv4 .ID (threadID ),
2161+ ResolutionReason : newGQLStringlikePtr [githubv4.String ](resolutionReason ),
21152162 }
21162163
21172164 if err := client .Mutate (ctx , & mutation , input , nil ); err != nil {
0 commit comments