Skip to content

Commit 110eba7

Browse files
Update pull requests and issues tools to use cursor-based pagination
Co-authored-by: SamMorrowDrums <[email protected]>
1 parent 6c1833a commit 110eba7

File tree

3 files changed

+77
-53
lines changed

3 files changed

+77
-53
lines changed

pkg/github/issues.go

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ Options are:
279279
return mcp.NewToolResultError(err.Error()), nil
280280
}
281281

282-
pagination, err := OptionalPaginationParams(request)
282+
cursorParams, err := GetCursorBasedParams(request)
283283
if err != nil {
284284
return mcp.NewToolResultError(err.Error()), nil
285285
}
@@ -298,9 +298,9 @@ Options are:
298298
case "get":
299299
return GetIssue(ctx, client, owner, repo, issueNumber)
300300
case "get_comments":
301-
return GetIssueComments(ctx, client, owner, repo, issueNumber, pagination)
301+
return GetIssueComments(ctx, client, owner, repo, issueNumber, cursorParams)
302302
case "get_sub_issues":
303-
return GetSubIssues(ctx, client, owner, repo, issueNumber, pagination)
303+
return GetSubIssues(ctx, client, owner, repo, issueNumber, cursorParams)
304304
case "get_labels":
305305
return GetIssueLabels(ctx, gqlClient, owner, repo, issueNumber)
306306
default:
@@ -342,11 +342,11 @@ func GetIssue(ctx context.Context, client *github.Client, owner string, repo str
342342
return mcp.NewToolResultText(string(r)), nil
343343
}
344344

345-
func GetIssueComments(ctx context.Context, client *github.Client, owner string, repo string, issueNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
345+
func GetIssueComments(ctx context.Context, client *github.Client, owner string, repo string, issueNumber int, cursorParams *DecodedCursor) (*mcp.CallToolResult, error) {
346346
opts := &github.IssueListCommentsOptions{
347347
ListOptions: github.ListOptions{
348-
Page: pagination.Page,
349-
PerPage: pagination.PerPage,
348+
Page: cursorParams.Page,
349+
PerPage: cursorParams.PerPage + 1, // Request one extra
350350
},
351351
}
352352

@@ -364,19 +364,23 @@ func GetIssueComments(ctx context.Context, client *github.Client, owner string,
364364
return mcp.NewToolResultError(fmt.Sprintf("failed to get issue comments: %s", string(body))), nil
365365
}
366366

367-
r, err := json.Marshal(comments)
368-
if err != nil {
369-
return nil, fmt.Errorf("failed to marshal response: %w", err)
367+
// Check if there are more results
368+
hasMore := len(comments) > cursorParams.PerPage
369+
if hasMore {
370+
// Remove the extra item
371+
comments = comments[:cursorParams.PerPage]
370372
}
371373

372-
return mcp.NewToolResultText(string(r)), nil
374+
// Create paginated response
375+
paginatedResp := NewPaginatedRESTResponse(comments, cursorParams.Page, cursorParams.PerPage, hasMore)
376+
return MarshalPaginatedResponse(paginatedResp), nil
373377
}
374378

375-
func GetSubIssues(ctx context.Context, client *github.Client, owner string, repo string, issueNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
379+
func GetSubIssues(ctx context.Context, client *github.Client, owner string, repo string, issueNumber int, cursorParams *DecodedCursor) (*mcp.CallToolResult, error) {
376380
opts := &github.IssueListOptions{
377381
ListOptions: github.ListOptions{
378-
Page: pagination.Page,
379-
PerPage: pagination.PerPage,
382+
Page: cursorParams.Page,
383+
PerPage: cursorParams.PerPage + 1, // Request one extra
380384
},
381385
}
382386

@@ -399,12 +403,16 @@ func GetSubIssues(ctx context.Context, client *github.Client, owner string, repo
399403
return mcp.NewToolResultError(fmt.Sprintf("failed to list sub-issues: %s", string(body))), nil
400404
}
401405

402-
r, err := json.Marshal(subIssues)
403-
if err != nil {
404-
return nil, fmt.Errorf("failed to marshal response: %w", err)
406+
// Check if there are more results
407+
hasMore := len(subIssues) > cursorParams.PerPage
408+
if hasMore {
409+
// Remove the extra item
410+
subIssues = subIssues[:cursorParams.PerPage]
405411
}
406412

407-
return mcp.NewToolResultText(string(r)), nil
413+
// Create paginated response
414+
paginatedResp := NewPaginatedRESTResponse(subIssues, cursorParams.Page, cursorParams.PerPage, hasMore)
415+
return MarshalPaginatedResponse(paginatedResp), nil
408416
}
409417

410418
func GetIssueLabels(ctx context.Context, client *githubv4.Client, owner string, repo string, issueNumber int) (*mcp.CallToolResult, error) {

pkg/github/pullrequests.go

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ Possible options:
7373
if err != nil {
7474
return mcp.NewToolResultError(err.Error()), nil
7575
}
76-
pagination, err := OptionalPaginationParams(request)
76+
cursorParams, err := GetCursorBasedParams(request)
7777
if err != nil {
7878
return mcp.NewToolResultError(err.Error()), nil
7979
}
@@ -92,13 +92,13 @@ Possible options:
9292
case "get_status":
9393
return GetPullRequestStatus(ctx, client, owner, repo, pullNumber)
9494
case "get_files":
95-
return GetPullRequestFiles(ctx, client, owner, repo, pullNumber, pagination)
95+
return GetPullRequestFiles(ctx, client, owner, repo, pullNumber, cursorParams)
9696
case "get_review_comments":
97-
return GetPullRequestReviewComments(ctx, client, owner, repo, pullNumber, pagination)
97+
return GetPullRequestReviewComments(ctx, client, owner, repo, pullNumber, cursorParams)
9898
case "get_reviews":
9999
return GetPullRequestReviews(ctx, client, owner, repo, pullNumber)
100100
case "get_comments":
101-
return GetIssueComments(ctx, client, owner, repo, pullNumber, pagination)
101+
return GetIssueComments(ctx, client, owner, repo, pullNumber, cursorParams)
102102
default:
103103
return nil, fmt.Errorf("unknown method: %s", method)
104104
}
@@ -218,10 +218,10 @@ func GetPullRequestStatus(ctx context.Context, client *github.Client, owner, rep
218218
return mcp.NewToolResultText(string(r)), nil
219219
}
220220

221-
func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
221+
func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, cursorParams *DecodedCursor) (*mcp.CallToolResult, error) {
222222
opts := &github.ListOptions{
223-
PerPage: pagination.PerPage,
224-
Page: pagination.Page,
223+
PerPage: cursorParams.PerPage + 1, // Request one extra
224+
Page: cursorParams.Page,
225225
}
226226
files, resp, err := client.PullRequests.ListFiles(ctx, owner, repo, pullNumber, opts)
227227
if err != nil {
@@ -241,19 +241,23 @@ func GetPullRequestFiles(ctx context.Context, client *github.Client, owner, repo
241241
return mcp.NewToolResultError(fmt.Sprintf("failed to get pull request files: %s", string(body))), nil
242242
}
243243

244-
r, err := json.Marshal(files)
245-
if err != nil {
246-
return nil, fmt.Errorf("failed to marshal response: %w", err)
244+
// Check if there are more results
245+
hasMore := len(files) > cursorParams.PerPage
246+
if hasMore {
247+
// Remove the extra item
248+
files = files[:cursorParams.PerPage]
247249
}
248250

249-
return mcp.NewToolResultText(string(r)), nil
251+
// Create paginated response
252+
paginatedResp := NewPaginatedRESTResponse(files, cursorParams.Page, cursorParams.PerPage, hasMore)
253+
return MarshalPaginatedResponse(paginatedResp), nil
250254
}
251255

252-
func GetPullRequestReviewComments(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, pagination PaginationParams) (*mcp.CallToolResult, error) {
256+
func GetPullRequestReviewComments(ctx context.Context, client *github.Client, owner, repo string, pullNumber int, cursorParams *DecodedCursor) (*mcp.CallToolResult, error) {
253257
opts := &github.PullRequestListCommentsOptions{
254258
ListOptions: github.ListOptions{
255-
PerPage: pagination.PerPage,
256-
Page: pagination.Page,
259+
PerPage: cursorParams.PerPage + 1, // Request one extra
260+
Page: cursorParams.Page,
257261
},
258262
}
259263

@@ -275,12 +279,16 @@ func GetPullRequestReviewComments(ctx context.Context, client *github.Client, ow
275279
return mcp.NewToolResultError(fmt.Sprintf("failed to get pull request review comments: %s", string(body))), nil
276280
}
277281

278-
r, err := json.Marshal(comments)
279-
if err != nil {
280-
return nil, fmt.Errorf("failed to marshal response: %w", err)
282+
// Check if there are more results
283+
hasMore := len(comments) > cursorParams.PerPage
284+
if hasMore {
285+
// Remove the extra item
286+
comments = comments[:cursorParams.PerPage]
281287
}
282288

283-
return mcp.NewToolResultText(string(r)), nil
289+
// Create paginated response
290+
paginatedResp := NewPaginatedRESTResponse(comments, cursorParams.Page, cursorParams.PerPage, hasMore)
291+
return MarshalPaginatedResponse(paginatedResp), nil
284292
}
285293

286294
func GetPullRequestReviews(ctx context.Context, client *github.Client, owner, repo string, pullNumber int) (*mcp.CallToolResult, error) {
@@ -777,7 +785,7 @@ func ListPullRequests(getClient GetClientFn, t translations.TranslationHelperFun
777785
if err != nil {
778786
return mcp.NewToolResultError(err.Error()), nil
779787
}
780-
pagination, err := OptionalPaginationParams(request)
788+
cursorParams, err := GetCursorBasedParams(request)
781789
if err != nil {
782790
return mcp.NewToolResultError(err.Error()), nil
783791
}
@@ -788,8 +796,8 @@ func ListPullRequests(getClient GetClientFn, t translations.TranslationHelperFun
788796
Sort: sort,
789797
Direction: direction,
790798
ListOptions: github.ListOptions{
791-
PerPage: pagination.PerPage,
792-
Page: pagination.Page,
799+
PerPage: cursorParams.PerPage + 1, // Request one extra
800+
Page: cursorParams.Page,
793801
},
794802
}
795803

@@ -815,6 +823,13 @@ func ListPullRequests(getClient GetClientFn, t translations.TranslationHelperFun
815823
return mcp.NewToolResultError(fmt.Sprintf("failed to list pull requests: %s", string(body))), nil
816824
}
817825

826+
// Check if there are more results
827+
hasMore := len(prs) > cursorParams.PerPage
828+
if hasMore {
829+
// Remove the extra item
830+
prs = prs[:cursorParams.PerPage]
831+
}
832+
818833
// sanitize title/body on each PR
819834
for _, pr := range prs {
820835
if pr == nil {
@@ -828,12 +843,9 @@ func ListPullRequests(getClient GetClientFn, t translations.TranslationHelperFun
828843
}
829844
}
830845

831-
r, err := json.Marshal(prs)
832-
if err != nil {
833-
return nil, fmt.Errorf("failed to marshal response: %w", err)
834-
}
835-
836-
return mcp.NewToolResultText(string(r)), nil
846+
// Create paginated response
847+
paginatedResp := NewPaginatedRESTResponse(prs, cursorParams.Page, cursorParams.PerPage, hasMore)
848+
return MarshalPaginatedResponse(paginatedResp), nil
837849
}
838850
}
839851

pkg/github/repositories.go

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ func GetCommit(getClient GetClientFn, t translations.TranslationHelperFunc) (too
6060
if err != nil {
6161
return mcp.NewToolResultError(err.Error()), nil
6262
}
63-
pagination, err := OptionalPaginationParams(request)
63+
cursorParams, err := GetCursorBasedParams(request)
6464
if err != nil {
6565
return mcp.NewToolResultError(err.Error()), nil
6666
}
6767

6868
opts := &github.ListOptions{
69-
Page: pagination.Page,
70-
PerPage: pagination.PerPage,
69+
Page: cursorParams.Page,
70+
PerPage: cursorParams.PerPage + 1, // Request one extra
7171
}
7272

7373
client, err := getClient(ctx)
@@ -92,15 +92,19 @@ func GetCommit(getClient GetClientFn, t translations.TranslationHelperFunc) (too
9292
return mcp.NewToolResultError(fmt.Sprintf("failed to get commit: %s", string(body))), nil
9393
}
9494

95+
// Check if there are more files in the commit
96+
hasMore := len(commit.Files) > cursorParams.PerPage
97+
if hasMore {
98+
// Remove the extra item
99+
commit.Files = commit.Files[:cursorParams.PerPage]
100+
}
101+
95102
// Convert to minimal commit
96103
minimalCommit := convertToMinimalCommit(commit, includeDiff)
97104

98-
r, err := json.Marshal(minimalCommit)
99-
if err != nil {
100-
return nil, fmt.Errorf("failed to marshal response: %w", err)
101-
}
102-
103-
return mcp.NewToolResultText(string(r)), nil
105+
// Create paginated response
106+
paginatedResp := NewPaginatedRESTResponse(minimalCommit, cursorParams.Page, cursorParams.PerPage, hasMore)
107+
return MarshalPaginatedResponse(paginatedResp), nil
104108
}
105109
}
106110

0 commit comments

Comments
 (0)