@@ -369,3 +369,196 @@ func TestTags(t *testing.T) {
369
369
require .Equal (t , "v0.0.1" , trimmedTag [0 ].Name , "expected tag name to match" )
370
370
require .Equal (t , * ref .Object .SHA , trimmedTag [0 ].Commit .SHA , "expected tag SHA to match" )
371
371
}
372
+
373
+ func TestPullRequestReview (t * testing.T ) {
374
+ t .Parallel ()
375
+
376
+ mcpClient := setupMCPClient (t )
377
+
378
+ ctx := context .Background ()
379
+
380
+ // First, who am I
381
+ getMeRequest := mcp.CallToolRequest {}
382
+ getMeRequest .Params .Name = "get_me"
383
+
384
+ t .Log ("Getting current user..." )
385
+ resp , err := mcpClient .CallTool (ctx , getMeRequest )
386
+ require .NoError (t , err , "expected to call 'get_me' tool successfully" )
387
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
388
+
389
+ require .False (t , resp .IsError , "expected result not to be an error" )
390
+ require .Len (t , resp .Content , 1 , "expected content to have one item" )
391
+
392
+ textContent , ok := resp .Content [0 ].(mcp.TextContent )
393
+ require .True (t , ok , "expected content to be of type TextContent" )
394
+
395
+ var trimmedGetMeText struct {
396
+ Login string `json:"login"`
397
+ }
398
+ err = json .Unmarshal ([]byte (textContent .Text ), & trimmedGetMeText )
399
+ require .NoError (t , err , "expected to unmarshal text content successfully" )
400
+
401
+ currentOwner := trimmedGetMeText .Login
402
+
403
+ // Then create a repository with a README (via autoInit)
404
+ repoName := fmt .Sprintf ("github-mcp-server-e2e-%s-%d" , t .Name (), time .Now ().UnixMilli ())
405
+ createRepoRequest := mcp.CallToolRequest {}
406
+ createRepoRequest .Params .Name = "create_repository"
407
+ createRepoRequest .Params .Arguments = map [string ]any {
408
+ "name" : repoName ,
409
+ "private" : true ,
410
+ "autoInit" : true ,
411
+ }
412
+
413
+ t .Logf ("Creating repository %s/%s..." , currentOwner , repoName )
414
+ _ , err = mcpClient .CallTool (ctx , createRepoRequest )
415
+ require .NoError (t , err , "expected to call 'get_me' tool successfully" )
416
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
417
+
418
+ // Cleanup the repository after the test
419
+ t .Cleanup (func () {
420
+ // MCP Server doesn't support deletions, but we can use the GitHub Client
421
+ ghClient := gogithub .NewClient (nil ).WithAuthToken (getE2EToken (t ))
422
+ t .Logf ("Deleting repository %s/%s..." , currentOwner , repoName )
423
+ _ , err := ghClient .Repositories .Delete (context .Background (), currentOwner , repoName )
424
+ require .NoError (t , err , "expected to delete repository successfully" )
425
+ })
426
+
427
+ // Create a branch on which to create a new commit
428
+ createBranchRequest := mcp.CallToolRequest {}
429
+ createBranchRequest .Params .Name = "create_branch"
430
+ createBranchRequest .Params .Arguments = map [string ]any {
431
+ "owner" : currentOwner ,
432
+ "repo" : repoName ,
433
+ "branch" : "test-branch" ,
434
+ "from_branch" : "main" ,
435
+ }
436
+
437
+ t .Logf ("Creating branch in %s/%s..." , currentOwner , repoName )
438
+ resp , err = mcpClient .CallTool (ctx , createBranchRequest )
439
+ require .NoError (t , err , "expected to call 'create_branch' tool successfully" )
440
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
441
+
442
+ // Create a commit with a new file
443
+ commitRequest := mcp.CallToolRequest {}
444
+ commitRequest .Params .Name = "create_or_update_file"
445
+ commitRequest .Params .Arguments = map [string ]any {
446
+ "owner" : currentOwner ,
447
+ "repo" : repoName ,
448
+ "path" : "test-file.txt" ,
449
+ "content" : fmt .Sprintf ("Created by e2e test %s" , t .Name ()),
450
+ "message" : "Add test file" ,
451
+ "branch" : "test-branch" ,
452
+ }
453
+
454
+ t .Logf ("Creating commit with new file in %s/%s..." , currentOwner , repoName )
455
+ resp , err = mcpClient .CallTool (ctx , commitRequest )
456
+ require .NoError (t , err , "expected to call 'create_or_update_file' tool successfully" )
457
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
458
+
459
+ textContent , ok = resp .Content [0 ].(mcp.TextContent )
460
+ require .True (t , ok , "expected content to be of type TextContent" )
461
+
462
+ var trimmedCommitText struct {
463
+ SHA string `json:"sha"`
464
+ }
465
+ err = json .Unmarshal ([]byte (textContent .Text ), & trimmedCommitText )
466
+ require .NoError (t , err , "expected to unmarshal text content successfully" )
467
+ commitId := trimmedCommitText .SHA
468
+
469
+ // Create a pull request
470
+ prRequest := mcp.CallToolRequest {}
471
+ prRequest .Params .Name = "create_pull_request"
472
+ prRequest .Params .Arguments = map [string ]any {
473
+ "owner" : currentOwner ,
474
+ "repo" : repoName ,
475
+ "title" : "Test PR" ,
476
+ "body" : "This is a test PR" ,
477
+ "head" : "test-branch" ,
478
+ "base" : "main" ,
479
+ "commitId" : commitId ,
480
+ }
481
+
482
+ t .Logf ("Creating pull request in %s/%s..." , currentOwner , repoName )
483
+ resp , err = mcpClient .CallTool (ctx , prRequest )
484
+ require .NoError (t , err , "expected to call 'create_pull_request' tool successfully" )
485
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
486
+
487
+ // Create a review for the pull request, but we can't approve it
488
+ // because the current owner also owns the PR.
489
+ createPendingPullRequestReviewRequest := mcp.CallToolRequest {}
490
+ createPendingPullRequestReviewRequest .Params .Name = "mvp_create_pending_pull_request_review"
491
+ createPendingPullRequestReviewRequest .Params .Arguments = map [string ]any {
492
+ "owner" : currentOwner ,
493
+ "repo" : repoName ,
494
+ "pullNumber" : 1 ,
495
+ }
496
+
497
+ t .Logf ("Creating pending review for pull request in %s/%s..." , currentOwner , repoName )
498
+ resp , err = mcpClient .CallTool (ctx , createPendingPullRequestReviewRequest )
499
+ require .NoError (t , err , "expected to call 'mvp_create_pending_pull_request_review' tool successfully" )
500
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
501
+
502
+ textContent , ok = resp .Content [0 ].(mcp.TextContent )
503
+ require .True (t , ok , "expected content to be of type TextContent" )
504
+ require .Equal (t , "" , textContent .Text , "expected content to be empty" )
505
+
506
+ // Add a review comment
507
+ addReviewCommentRequest := mcp.CallToolRequest {}
508
+ addReviewCommentRequest .Params .Name = "mvp_add_pull_request_review_comment_to_pending_review"
509
+ addReviewCommentRequest .Params .Arguments = map [string ]any {
510
+ "owner" : currentOwner ,
511
+ "repo" : repoName ,
512
+ "pullNumber" : 1 ,
513
+ "path" : "test-file.txt" ,
514
+ "body" : "Very nice!" ,
515
+ "line" : 1 ,
516
+ }
517
+
518
+ t .Logf ("Adding review comment to pull request in %s/%s..." , currentOwner , repoName )
519
+ resp , err = mcpClient .CallTool (ctx , addReviewCommentRequest )
520
+ require .NoError (t , err , "expected to call 'mvp_add_pull_request_review_comment_to_pending_review' tool successfully" )
521
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
522
+
523
+ // Submit the review
524
+ submitReviewRequest := mcp.CallToolRequest {}
525
+ submitReviewRequest .Params .Name = "mvp_submit_pull_request_review"
526
+ submitReviewRequest .Params .Arguments = map [string ]any {
527
+ "owner" : currentOwner ,
528
+ "repo" : repoName ,
529
+ "pullNumber" : 1 ,
530
+ "event" : "COMMENT" , // the only event we can use as the creator of the PR
531
+ "body" : "Looks good if you like bad code I guess!" ,
532
+ }
533
+
534
+ t .Logf ("Submitting review for pull request in %s/%s..." , currentOwner , repoName )
535
+ resp , err = mcpClient .CallTool (ctx , submitReviewRequest )
536
+ require .NoError (t , err , "expected to call 'mvp_submit_pull_request_review' tool successfully" )
537
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
538
+
539
+ // Finally, get the review and see that it has been created
540
+ getPullRequestsReview := mcp.CallToolRequest {}
541
+ getPullRequestsReview .Params .Name = "get_pull_request_reviews"
542
+ getPullRequestsReview .Params .Arguments = map [string ]any {
543
+ "owner" : currentOwner ,
544
+ "repo" : repoName ,
545
+ "pullNumber" : 1 ,
546
+ }
547
+
548
+ t .Logf ("Getting reviews for pull request in %s/%s..." , currentOwner , repoName )
549
+ resp , err = mcpClient .CallTool (ctx , getPullRequestsReview )
550
+ require .NoError (t , err , "expected to call 'get_pull_request_reviews' tool successfully" )
551
+ require .False (t , resp .IsError , fmt .Sprintf ("expected result not to be an error: %+v" , resp ))
552
+
553
+ textContent , ok = resp .Content [0 ].(mcp.TextContent )
554
+ require .True (t , ok , "expected content to be of type TextContent" )
555
+
556
+ var reviews []struct {
557
+ NodeID string `json:"node_id"`
558
+ }
559
+ err = json .Unmarshal ([]byte (textContent .Text ), & reviews )
560
+ require .NoError (t , err , "expected to unmarshal text content successfully" )
561
+
562
+ // Check that there is one review
563
+ require .Len (t , reviews , 1 , "expected to find one review" )
564
+ }
0 commit comments