Skip to content

Commit af5286f

Browse files
Merge branch 'main' into make-mcp-apps-client-aware-submit
2 parents 91cd327 + 391990a commit af5286f

12 files changed

+367
-25
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,11 +1097,12 @@ The following sets of tools are available:
10971097
Possible options:
10981098
1. get - Get details of a specific pull request.
10991099
2. get_diff - Get the diff of a pull request.
1100-
3. get_status - Get status of a head commit in a pull request. This reflects status of builds and checks.
1100+
3. get_status - Get combined commit status of a head commit in a pull request.
11011101
4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.
11021102
5. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results.
11031103
6. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method.
11041104
7. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.
1105+
8. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR.
11051106
(string, required)
11061107
- `owner`: Repository owner (string, required)
11071108
- `page`: Page number for pagination (min 1) (number, optional)

pkg/github/__toolsnaps__/pull_request_read.snap

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,16 @@
77
"inputSchema": {
88
"properties": {
99
"method": {
10-
"description": "Action to specify what pull request data needs to be retrieved from GitHub. \nPossible options: \n 1. get - Get details of a specific pull request.\n 2. get_diff - Get the diff of a pull request.\n 3. get_status - Get status of a head commit in a pull request. This reflects status of builds and checks.\n 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.\n 5. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results.\n 6. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method.\n 7. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.\n",
10+
"description": "Action to specify what pull request data needs to be retrieved from GitHub. \nPossible options: \n 1. get - Get details of a specific pull request.\n 2. get_diff - Get the diff of a pull request.\n 3. get_status - Get combined commit status of a head commit in a pull request.\n 4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.\n 5. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results.\n 6. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method.\n 7. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.\n 8. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR.\n",
1111
"enum": [
1212
"get",
1313
"get_diff",
1414
"get_status",
1515
"get_files",
1616
"get_review_comments",
1717
"get_reviews",
18-
"get_comments"
18+
"get_comments",
19+
"get_check_runs"
1920
],
2021
"type": "string"
2122
},

pkg/github/helper_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const (
5151
PostReposGitTreesByOwnerByRepo = "POST /repos/{owner}/{repo}/git/trees"
5252
GetReposCommitsStatusByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}/status"
5353
GetReposCommitsStatusesByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}/statuses"
54+
GetReposCommitsCheckRunsByOwnerByRepoByRef = "GET /repos/{owner}/{repo}/commits/{ref}/check-runs"
5455

5556
// Issues endpoints
5657
GetReposIssuesByOwnerByRepoByIssueNumber = "GET /repos/{owner}/{repo}/issues/{issue_number}"

pkg/github/minimal_types.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ type MinimalBranch struct {
122122
Protected bool `json:"protected"`
123123
}
124124

125+
// MinimalTag is the trimmed output type for tag objects.
126+
type MinimalTag struct {
127+
Name string `json:"name"`
128+
SHA string `json:"sha"`
129+
}
130+
125131
// MinimalResponse represents a minimal response for all CRUD operations.
126132
// Success is implicit in the HTTP response status, and all other information
127133
// can be derived from the URL or fetched separately if needed.
@@ -702,6 +708,57 @@ func convertToMinimalBranch(branch *github.Branch) MinimalBranch {
702708
}
703709
}
704710

711+
func convertToMinimalTag(tag *github.RepositoryTag) MinimalTag {
712+
m := MinimalTag{
713+
Name: tag.GetName(),
714+
}
715+
716+
if commit := tag.GetCommit(); commit != nil {
717+
m.SHA = commit.GetSHA()
718+
}
719+
720+
return m
721+
}
722+
723+
// MinimalCheckRun is the trimmed output type for check run objects.
724+
type MinimalCheckRun struct {
725+
ID int64 `json:"id"`
726+
Name string `json:"name"`
727+
Status string `json:"status"`
728+
Conclusion string `json:"conclusion,omitempty"`
729+
HTMLURL string `json:"html_url,omitempty"`
730+
DetailsURL string `json:"details_url,omitempty"`
731+
StartedAt string `json:"started_at,omitempty"`
732+
CompletedAt string `json:"completed_at,omitempty"`
733+
}
734+
735+
// MinimalCheckRunsResult is the trimmed output type for check runs list results.
736+
type MinimalCheckRunsResult struct {
737+
TotalCount int `json:"total_count"`
738+
CheckRuns []MinimalCheckRun `json:"check_runs"`
739+
}
740+
741+
// convertToMinimalCheckRun converts a GitHub API CheckRun to MinimalCheckRun
742+
func convertToMinimalCheckRun(checkRun *github.CheckRun) MinimalCheckRun {
743+
minimalCheckRun := MinimalCheckRun{
744+
ID: checkRun.GetID(),
745+
Name: checkRun.GetName(),
746+
Status: checkRun.GetStatus(),
747+
Conclusion: checkRun.GetConclusion(),
748+
HTMLURL: checkRun.GetHTMLURL(),
749+
DetailsURL: checkRun.GetDetailsURL(),
750+
}
751+
752+
if checkRun.StartedAt != nil {
753+
minimalCheckRun.StartedAt = checkRun.StartedAt.Format("2006-01-02T15:04:05Z")
754+
}
755+
if checkRun.CompletedAt != nil {
756+
minimalCheckRun.CompletedAt = checkRun.CompletedAt.Format("2006-01-02T15:04:05Z")
757+
}
758+
759+
return minimalCheckRun
760+
}
761+
705762
func convertToMinimalReviewThreadsResponse(query reviewThreadsQuery) MinimalReviewThreadsResponse {
706763
threads := query.Repository.PullRequest.ReviewThreads
707764

pkg/github/pullrequests.go

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ func PullRequestRead(t translations.TranslationHelperFunc) inventory.ServerTool
3333
Possible options:
3434
1. get - Get details of a specific pull request.
3535
2. get_diff - Get the diff of a pull request.
36-
3. get_status - Get status of a head commit in a pull request. This reflects status of builds and checks.
36+
3. get_status - Get combined commit status of a head commit in a pull request.
3737
4. get_files - Get the list of files changed in a pull request. Use with pagination parameters to control the number of results returned.
3838
5. get_review_comments - Get review threads on a pull request. Each thread contains logically grouped review comments made on the same code location during pull request reviews. Returns threads with metadata (isResolved, isOutdated, isCollapsed) and their associated comments. Use cursor-based pagination (perPage, after) to control results.
3939
6. get_reviews - Get the reviews on a pull request. When asked for review comments, use get_review_comments method.
4040
7. get_comments - Get comments on a pull request. Use this if user doesn't specifically want review comments. Use with pagination parameters to control the number of results returned.
41+
8. get_check_runs - Get check runs for the head commit of a pull request. Check runs are the individual CI/CD jobs and checks that run on the PR.
4142
`,
42-
Enum: []any{"get", "get_diff", "get_status", "get_files", "get_review_comments", "get_reviews", "get_comments"},
43+
Enum: []any{"get", "get_diff", "get_status", "get_files", "get_review_comments", "get_reviews", "get_comments", "get_check_runs"},
4344
},
4445
"owner": {
4546
Type: "string",
@@ -128,6 +129,9 @@ Possible options:
128129
case "get_comments":
129130
result, err := GetIssueComments(ctx, client, deps, owner, repo, pullNumber, pagination)
130131
return result, nil, err
132+
case "get_check_runs":
133+
result, err := GetPullRequestCheckRuns(ctx, client, owner, repo, pullNumber, pagination)
134+
return result, nil, err
131135
default:
132136
return utils.NewToolResultError(fmt.Sprintf("unknown method: %s", method)), nil, nil
133137
}
@@ -267,6 +271,71 @@ func GetPullRequestStatus(ctx context.Context, client *github.Client, owner, rep
267271
return utils.NewToolResultText(string(r)), nil
268272
}
269273

274+
func GetPullRequestCheckRuns(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
275+
// First get the PR to get the head SHA
276+
pr, resp, err := client.PullRequests.Get(ctx, owner, repo, pullNumber)
277+
if err != nil {
278+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
279+
"failed to get pull request",
280+
resp,
281+
err,
282+
), nil
283+
}
284+
defer resp.Body.Close()
285+
286+
if resp.StatusCode != http.StatusOK {
287+
body, err := io.ReadAll(resp.Body)
288+
if err != nil {
289+
return nil, fmt.Errorf("failed to read response body: %w", err)
290+
}
291+
return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get pull request", resp, body), nil
292+
}
293+
294+
// Get check runs for the head SHA
295+
opts := &github.ListCheckRunsOptions{
296+
ListOptions: github.ListOptions{
297+
PerPage: pagination.PerPage,
298+
Page: pagination.Page,
299+
},
300+
}
301+
302+
checkRuns, resp, err := client.Checks.ListCheckRunsForRef(ctx, owner, repo, *pr.Head.SHA, opts)
303+
if err != nil {
304+
return ghErrors.NewGitHubAPIErrorResponse(ctx,
305+
"failed to get check runs",
306+
resp,
307+
err,
308+
), nil
309+
}
310+
defer resp.Body.Close()
311+
312+
if resp.StatusCode != http.StatusOK {
313+
body, err := io.ReadAll(resp.Body)
314+
if err != nil {
315+
return nil, fmt.Errorf("failed to read response body: %w", err)
316+
}
317+
return ghErrors.NewGitHubAPIStatusErrorResponse(ctx, "failed to get check runs", resp, body), nil
318+
}
319+
320+
// Convert to minimal check runs to reduce context usage
321+
minimalCheckRuns := make([]MinimalCheckRun, 0, len(checkRuns.CheckRuns))
322+
for _, checkRun := range checkRuns.CheckRuns {
323+
minimalCheckRuns = append(minimalCheckRuns, convertToMinimalCheckRun(checkRun))
324+
}
325+
326+
minimalResult := MinimalCheckRunsResult{
327+
TotalCount: checkRuns.GetTotal(),
328+
CheckRuns: minimalCheckRuns,
329+
}
330+
331+
r, err := json.Marshal(minimalResult)
332+
if err != nil {
333+
return nil, fmt.Errorf("failed to marshal response: %w", err)
334+
}
335+
336+
return utils.NewToolResultText(string(r)), nil
337+
}
338+
270339
func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
271340
opts := &github.ListOptions{
272341
PerPage: pagination.PerPage,
@@ -1148,7 +1217,14 @@ func ListPullRequests(t translations.TranslationHelperFunc) inventory.ServerTool
11481217
}
11491218
}
11501219

1151-
r, err := json.Marshal(prs)
1220+
minimalPRs := make([]MinimalPullRequest, 0, len(prs))
1221+
for _, pr := range prs {
1222+
if pr != nil {
1223+
minimalPRs = append(minimalPRs, convertToMinimalPullRequest(pr))
1224+
}
1225+
}
1226+
1227+
r, err := json.Marshal(minimalPRs)
11521228
if err != nil {
11531229
return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil
11541230
}

0 commit comments

Comments
 (0)