@@ -913,3 +913,148 @@ func TestPullRequestReviewDeletion(t *testing.T) {
913
913
require .Len (t ,noReviews ,0 ,"expected to find no reviews" )
914
914
915
915
}
916
+
917
+ func TestRequestCopilotReview (t * testing.T ) {
918
+ t .Parallel ()
919
+
920
+ mcpClient := setupMCPClient (t )
921
+
922
+ ctx := context .Background ()
923
+
924
+ // First, who am I
925
+ getMeRequest := mcp.CallToolRequest {}
926
+ getMeRequest .Params .Name = "get_me"
927
+
928
+ t .Log ("Getting current user..." )
929
+ resp ,err := mcpClient .CallTool (ctx ,getMeRequest )
930
+ require .NoError (t ,err ,"expected to call 'get_me' tool successfully" )
931
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
932
+
933
+ require .False (t ,resp .IsError ,"expected result not to be an error" )
934
+ require .Len (t ,resp .Content ,1 ,"expected content to have one item" )
935
+
936
+ textContent ,ok := resp .Content [0 ].(mcp.TextContent )
937
+ require .True (t ,ok ,"expected content to be of type TextContent" )
938
+
939
+ var trimmedGetMeText struct {
940
+ Login string `json:"login"`
941
+ }
942
+ err = json .Unmarshal ([]byte (textContent .Text ),& trimmedGetMeText )
943
+ require .NoError (t ,err ,"expected to unmarshal text content successfully" )
944
+
945
+ currentOwner := trimmedGetMeText .Login
946
+
947
+ // Then create a repository with a README (via autoInit)
948
+ repoName := fmt .Sprintf ("github-mcp-server-e2e-%s-%d" ,t .Name (),time .Now ().UnixMilli ())
949
+ createRepoRequest := mcp.CallToolRequest {}
950
+ createRepoRequest .Params .Name = "create_repository"
951
+ createRepoRequest .Params .Arguments = map [string ]any {
952
+ "name" :repoName ,
953
+ "private" :true ,
954
+ "autoInit" :true ,
955
+ }
956
+
957
+ t .Logf ("Creating repository %s/%s..." ,currentOwner ,repoName )
958
+ _ ,err = mcpClient .CallTool (ctx ,createRepoRequest )
959
+ require .NoError (t ,err ,"expected to call 'get_me' tool successfully" )
960
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
961
+
962
+ // Cleanup the repository after the test
963
+ t .Cleanup (func () {
964
+ // MCP Server doesn't support deletions, but we can use the GitHub Client
965
+ ghClient := gogithub .NewClient (nil ).WithAuthToken (getE2EToken (t ))
966
+ t .Logf ("Deleting repository %s/%s..." ,currentOwner ,repoName )
967
+ _ ,err := ghClient .Repositories .Delete (context .Background (),currentOwner ,repoName )
968
+ require .NoError (t ,err ,"expected to delete repository successfully" )
969
+ })
970
+
971
+ // Create a branch on which to create a new commit
972
+ createBranchRequest := mcp.CallToolRequest {}
973
+ createBranchRequest .Params .Name = "create_branch"
974
+ createBranchRequest .Params .Arguments = map [string ]any {
975
+ "owner" :currentOwner ,
976
+ "repo" :repoName ,
977
+ "branch" :"test-branch" ,
978
+ "from_branch" :"main" ,
979
+ }
980
+
981
+ t .Logf ("Creating branch in %s/%s..." ,currentOwner ,repoName )
982
+ resp ,err = mcpClient .CallTool (ctx ,createBranchRequest )
983
+ require .NoError (t ,err ,"expected to call 'create_branch' tool successfully" )
984
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
985
+
986
+ // Create a commit with a new file
987
+ commitRequest := mcp.CallToolRequest {}
988
+ commitRequest .Params .Name = "create_or_update_file"
989
+ commitRequest .Params .Arguments = map [string ]any {
990
+ "owner" :currentOwner ,
991
+ "repo" :repoName ,
992
+ "path" :"test-file.txt" ,
993
+ "content" :fmt .Sprintf ("Created by e2e test %s" ,t .Name ()),
994
+ "message" :"Add test file" ,
995
+ "branch" :"test-branch" ,
996
+ }
997
+
998
+ t .Logf ("Creating commit with new file in %s/%s..." ,currentOwner ,repoName )
999
+ resp ,err = mcpClient .CallTool (ctx ,commitRequest )
1000
+ require .NoError (t ,err ,"expected to call 'create_or_update_file' tool successfully" )
1001
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
1002
+
1003
+ textContent ,ok = resp .Content [0 ].(mcp.TextContent )
1004
+ require .True (t ,ok ,"expected content to be of type TextContent" )
1005
+
1006
+ var trimmedCommitText struct {
1007
+ SHA string `json:"sha"`
1008
+ }
1009
+ err = json .Unmarshal ([]byte (textContent .Text ),& trimmedCommitText )
1010
+ require .NoError (t ,err ,"expected to unmarshal text content successfully" )
1011
+ commitId := trimmedCommitText .SHA
1012
+
1013
+ // Create a pull request
1014
+ prRequest := mcp.CallToolRequest {}
1015
+ prRequest .Params .Name = "create_pull_request"
1016
+ prRequest .Params .Arguments = map [string ]any {
1017
+ "owner" :currentOwner ,
1018
+ "repo" :repoName ,
1019
+ "title" :"Test PR" ,
1020
+ "body" :"This is a test PR" ,
1021
+ "head" :"test-branch" ,
1022
+ "base" :"main" ,
1023
+ "commitId" :commitId ,
1024
+ }
1025
+
1026
+ t .Logf ("Creating pull request in %s/%s..." ,currentOwner ,repoName )
1027
+ resp ,err = mcpClient .CallTool (ctx ,prRequest )
1028
+ require .NoError (t ,err ,"expected to call 'create_pull_request' tool successfully" )
1029
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
1030
+
1031
+ // Request a copilot review
1032
+ requestCopilotReviewRequest := mcp.CallToolRequest {}
1033
+ requestCopilotReviewRequest .Params .Name = "request_copilot_review"
1034
+ requestCopilotReviewRequest .Params .Arguments = map [string ]any {
1035
+ "owner" :currentOwner ,
1036
+ "repo" :repoName ,
1037
+ "pullNumber" :1 ,
1038
+ }
1039
+
1040
+ t .Logf ("Requesting Copilot review for pull request in %s/%s..." ,currentOwner ,repoName )
1041
+ resp ,err = mcpClient .CallTool (ctx ,requestCopilotReviewRequest )
1042
+ require .NoError (t ,err ,"expected to call 'request_copilot_review' tool successfully" )
1043
+ require .False (t ,resp .IsError ,fmt .Sprintf ("expected result not to be an error: %+v" ,resp ))
1044
+
1045
+ textContent ,ok = resp .Content [0 ].(mcp.TextContent )
1046
+ require .True (t ,ok ,"expected content to be of type TextContent" )
1047
+ require .Equal (t ,"" ,textContent .Text ,"expected content to be empty" )
1048
+
1049
+ // Finally, get requested reviews and see copilot is in there
1050
+ // MCP Server doesn't support requesting reviews yet, but we can use the GitHub Client
1051
+ ghClient := gogithub .NewClient (nil ).WithAuthToken (getE2EToken (t ))
1052
+ t .Logf ("Getting reviews for pull request in %s/%s..." ,currentOwner ,repoName )
1053
+ reviewRequests ,_ ,err := ghClient .PullRequests .ListReviewers (context .Background (),currentOwner ,repoName ,1 ,nil )
1054
+ require .NoError (t ,err ,"expected to get review requests successfully" )
1055
+
1056
+ // Check that there is one review request from copilot
1057
+ require .Len (t ,reviewRequests .Users ,1 ,"expected to find one review request" )
1058
+ require .Equal (t ,"Copilot" ,* reviewRequests .Users [0 ].Login ,"expected review request to be for Copilot" )
1059
+ require .Equal (t ,"Bot" ,* reviewRequests .Users [0 ].Type ,"expected review request to be for Bot" )
1060
+ }