@@ -22,6 +22,9 @@ import {
22
22
GetFileContentsSchema ,
23
23
GetIssueSchema ,
24
24
GetPullRequestSchema ,
25
+ GetPullRequestFilesSchema ,
26
+ GetPullRequestStatusSchema ,
27
+ MergePullRequestSchema ,
25
28
GitHubCommitSchema ,
26
29
GitHubContentSchema ,
27
30
GitHubCreateUpdateFileResponseSchema ,
@@ -40,6 +43,8 @@ import {
40
43
ListPullRequestsSchema ,
41
44
CreatePullRequestReviewSchema ,
42
45
PushFilesSchema ,
46
+ PullRequestFileSchema ,
47
+ CombinedStatusSchema ,
43
48
SearchCodeResponseSchema ,
44
49
SearchCodeSchema ,
45
50
SearchIssuesResponseSchema ,
@@ -798,6 +803,99 @@ async function createPullRequestReview(
798
803
return await response . json ( ) ;
799
804
}
800
805
806
+ async function mergePullRequest (
807
+ owner : string ,
808
+ repo : string ,
809
+ pullNumber : number ,
810
+ options : Omit < z . infer < typeof MergePullRequestSchema > , 'owner' | 'repo' | 'pull_number' >
811
+ ) : Promise < any > {
812
+ const response = await fetch (
813
+ `https://api.github.com/repos/${ owner } /${ repo } /pulls/${ pullNumber } /merge` ,
814
+ {
815
+ method : 'PUT' ,
816
+ headers : {
817
+ Authorization : `token ${ GITHUB_PERSONAL_ACCESS_TOKEN } ` ,
818
+ Accept : "application/vnd.github.v3+json" ,
819
+ "User-Agent" : "github-mcp-server" ,
820
+ "Content-Type" : "application/json" ,
821
+ } ,
822
+ body : JSON . stringify ( options ) ,
823
+ }
824
+ ) ;
825
+
826
+ if ( ! response . ok ) {
827
+ throw new Error ( `GitHub API error: ${ response . statusText } ` ) ;
828
+ }
829
+
830
+ return await response . json ( ) ;
831
+ }
832
+
833
+ async function getPullRequestFiles (
834
+ owner : string ,
835
+ repo : string ,
836
+ pullNumber : number
837
+ ) : Promise < z . infer < typeof PullRequestFileSchema > [ ] > {
838
+ const response = await fetch (
839
+ `https://api.github.com/repos/${ owner } /${ repo } /pulls/${ pullNumber } /files` ,
840
+ {
841
+ headers : {
842
+ Authorization : `token ${ GITHUB_PERSONAL_ACCESS_TOKEN } ` ,
843
+ Accept : "application/vnd.github.v3+json" ,
844
+ "User-Agent" : "github-mcp-server" ,
845
+ } ,
846
+ }
847
+ ) ;
848
+
849
+ if ( ! response . ok ) {
850
+ throw new Error ( `GitHub API error: ${ response . statusText } ` ) ;
851
+ }
852
+
853
+ return z . array ( PullRequestFileSchema ) . parse ( await response . json ( ) ) ;
854
+ }
855
+
856
+ async function getPullRequestStatus (
857
+ owner : string ,
858
+ repo : string ,
859
+ pullNumber : number
860
+ ) : Promise < z . infer < typeof CombinedStatusSchema >> {
861
+ // First get the PR to get the head SHA
862
+ const prResponse = await fetch (
863
+ `https://api.github.com/repos/${ owner } /${ repo } /pulls/${ pullNumber } ` ,
864
+ {
865
+ headers : {
866
+ Authorization : `token ${ GITHUB_PERSONAL_ACCESS_TOKEN } ` ,
867
+ Accept : "application/vnd.github.v3+json" ,
868
+ "User-Agent" : "github-mcp-server" ,
869
+ } ,
870
+ }
871
+ ) ;
872
+
873
+ if ( ! prResponse . ok ) {
874
+ throw new Error ( `GitHub API error: ${ prResponse . statusText } ` ) ;
875
+ }
876
+
877
+ const pr = GitHubPullRequestSchema . parse ( await prResponse . json ( ) ) ;
878
+ const sha = pr . head . sha ;
879
+
880
+ // Then get the combined status for that SHA
881
+ const statusResponse = await fetch (
882
+ `https://api.github.com/repos/${ owner } /${ repo } /commits/${ sha } /status` ,
883
+ {
884
+ headers : {
885
+ Authorization : `token ${ GITHUB_PERSONAL_ACCESS_TOKEN } ` ,
886
+ Accept : "application/vnd.github.v3+json" ,
887
+ "User-Agent" : "github-mcp-server" ,
888
+ } ,
889
+ }
890
+ ) ;
891
+
892
+ if ( ! statusResponse . ok ) {
893
+ throw new Error ( `GitHub API error: ${ statusResponse . statusText } ` ) ;
894
+ }
895
+
896
+ return CombinedStatusSchema . parse ( await statusResponse . json ( ) ) ;
897
+ }
898
+
801
899
server . setRequestHandler ( ListToolsRequestSchema , async ( ) => {
802
900
return {
803
901
tools : [
@@ -904,6 +1002,21 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
904
1002
name : "create_pull_request_review" ,
905
1003
description : "Create a review on a pull request" ,
906
1004
inputSchema : zodToJsonSchema ( CreatePullRequestReviewSchema )
1005
+ } ,
1006
+ {
1007
+ name : "merge_pull_request" ,
1008
+ description : "Merge a pull request" ,
1009
+ inputSchema : zodToJsonSchema ( MergePullRequestSchema )
1010
+ } ,
1011
+ {
1012
+ name : "get_pull_request_files" ,
1013
+ description : "Get the list of files changed in a pull request" ,
1014
+ inputSchema : zodToJsonSchema ( GetPullRequestFilesSchema )
1015
+ } ,
1016
+ {
1017
+ name : "get_pull_request_status" ,
1018
+ description : "Get the combined status of all status checks for a pull request" ,
1019
+ inputSchema : zodToJsonSchema ( GetPullRequestStatusSchema )
907
1020
}
908
1021
] ,
909
1022
} ;
@@ -1129,6 +1242,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
1129
1242
return { toolResult : review } ;
1130
1243
}
1131
1244
1245
+ case "merge_pull_request" : {
1246
+ const args = MergePullRequestSchema . parse ( request . params . arguments ) ;
1247
+ const { owner, repo, pull_number, ...options } = args ;
1248
+ const result = await mergePullRequest ( owner , repo , pull_number , options ) ;
1249
+ return { toolResult : result } ;
1250
+ }
1251
+
1252
+ case "get_pull_request_files" : {
1253
+ const args = GetPullRequestFilesSchema . parse ( request . params . arguments ) ;
1254
+ const files = await getPullRequestFiles ( args . owner , args . repo , args . pull_number ) ;
1255
+ return { toolResult : files } ;
1256
+ }
1257
+
1258
+ case "get_pull_request_status" : {
1259
+ const args = GetPullRequestStatusSchema . parse ( request . params . arguments ) ;
1260
+ const status = await getPullRequestStatus ( args . owner , args . repo , args . pull_number ) ;
1261
+ return { toolResult : status } ;
1262
+ }
1263
+
1132
1264
default :
1133
1265
throw new Error ( `Unknown tool: ${ request . params . name } ` ) ;
1134
1266
}
0 commit comments