7
7
} from "@modelcontextprotocol/sdk/types.js" ;
8
8
import { z } from 'zod' ;
9
9
import { zodToJsonSchema } from 'zod-to-json-schema' ;
10
+ import fetch , { Request , Response } from 'node-fetch' ;
10
11
11
12
import * as repository from './operations/repository.js' ;
12
13
import * as files from './operations/files.js' ;
@@ -27,6 +28,11 @@ import {
27
28
} from './common/errors.js' ;
28
29
import { VERSION } from "./common/version.js" ;
29
30
31
+ // If fetch doesn't exist in global scope, add it
32
+ if ( ! globalThis . fetch ) {
33
+ globalThis . fetch = fetch as unknown as typeof global . fetch ;
34
+ }
35
+
30
36
const server = new Server (
31
37
{
32
38
name : "github-mcp-server" ,
@@ -149,6 +155,51 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
149
155
name : "get_issue" ,
150
156
description : "Get details of a specific issue in a GitHub repository." ,
151
157
inputSchema : zodToJsonSchema ( issues . GetIssueSchema )
158
+ } ,
159
+ {
160
+ name : "get_pull_request" ,
161
+ description : "Get details of a specific pull request" ,
162
+ inputSchema : zodToJsonSchema ( pulls . GetPullRequestSchema )
163
+ } ,
164
+ {
165
+ name : "list_pull_requests" ,
166
+ description : "List and filter repository pull requests" ,
167
+ inputSchema : zodToJsonSchema ( pulls . ListPullRequestsSchema )
168
+ } ,
169
+ {
170
+ name : "create_pull_request_review" ,
171
+ description : "Create a review on a pull request" ,
172
+ inputSchema : zodToJsonSchema ( pulls . CreatePullRequestReviewSchema )
173
+ } ,
174
+ {
175
+ name : "merge_pull_request" ,
176
+ description : "Merge a pull request" ,
177
+ inputSchema : zodToJsonSchema ( pulls . MergePullRequestSchema )
178
+ } ,
179
+ {
180
+ name : "get_pull_request_files" ,
181
+ description : "Get the list of files changed in a pull request" ,
182
+ inputSchema : zodToJsonSchema ( pulls . GetPullRequestFilesSchema )
183
+ } ,
184
+ {
185
+ name : "get_pull_request_status" ,
186
+ description : "Get the combined status of all status checks for a pull request" ,
187
+ inputSchema : zodToJsonSchema ( pulls . GetPullRequestStatusSchema )
188
+ } ,
189
+ {
190
+ name : "update_pull_request_branch" ,
191
+ description : "Update a pull request branch with the latest changes from the base branch" ,
192
+ inputSchema : zodToJsonSchema ( pulls . UpdatePullRequestBranchSchema )
193
+ } ,
194
+ {
195
+ name : "get_pull_request_comments" ,
196
+ description : "Get the review comments on a pull request" ,
197
+ inputSchema : zodToJsonSchema ( pulls . GetPullRequestCommentsSchema )
198
+ } ,
199
+ {
200
+ name : "get_pull_request_reviews" ,
201
+ description : "Get the reviews on a pull request" ,
202
+ inputSchema : zodToJsonSchema ( pulls . GetPullRequestReviewsSchema )
152
203
}
153
204
] ,
154
205
} ;
@@ -248,10 +299,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
248
299
case "create_issue" : {
249
300
const args = issues . CreateIssueSchema . parse ( request . params . arguments ) ;
250
301
const { owner, repo, ...options } = args ;
251
- const issue = await issues . createIssue ( owner , repo , options ) ;
252
- return {
253
- content : [ { type : "text" , text : JSON . stringify ( issue , null , 2 ) } ] ,
254
- } ;
302
+
303
+ try {
304
+ console . error ( `[DEBUG] Attempting to create issue in ${ owner } /${ repo } ` ) ;
305
+ console . error ( `[DEBUG] Issue options:` , JSON . stringify ( options , null , 2 ) ) ;
306
+
307
+ const issue = await issues . createIssue ( owner , repo , options ) ;
308
+
309
+ console . error ( `[DEBUG] Issue created successfully` ) ;
310
+ return {
311
+ content : [ { type : "text" , text : JSON . stringify ( issue , null , 2 ) } ] ,
312
+ } ;
313
+ } catch ( err ) {
314
+ // Type guard for Error objects
315
+ const error = err instanceof Error ? err : new Error ( String ( err ) ) ;
316
+
317
+ console . error ( `[ERROR] Failed to create issue:` , error ) ;
318
+
319
+ if ( error instanceof GitHubResourceNotFoundError ) {
320
+ throw new Error (
321
+ `Repository '${ owner } /${ repo } ' not found. Please verify:\n` +
322
+ `1. The repository exists\n` +
323
+ `2. You have correct access permissions\n` +
324
+ `3. The owner and repository names are spelled correctly`
325
+ ) ;
326
+ }
327
+
328
+ // Safely access error properties
329
+ throw new Error (
330
+ `Failed to create issue: ${ error . message } ${
331
+ error . stack ? `\nStack: ${ error . stack } ` : ''
332
+ } `
333
+ ) ;
334
+ }
255
335
}
256
336
257
337
case "create_pull_request" : {
@@ -335,6 +415,82 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
335
415
} ;
336
416
}
337
417
418
+ case "get_pull_request" : {
419
+ const args = pulls . GetPullRequestSchema . parse ( request . params . arguments ) ;
420
+ const pullRequest = await pulls . getPullRequest ( args . owner , args . repo , args . pull_number ) ;
421
+ return {
422
+ content : [ { type : "text" , text : JSON . stringify ( pullRequest , null , 2 ) } ] ,
423
+ } ;
424
+ }
425
+
426
+ case "list_pull_requests" : {
427
+ const args = pulls . ListPullRequestsSchema . parse ( request . params . arguments ) ;
428
+ const { owner, repo, ...options } = args ;
429
+ const pullRequests = await pulls . listPullRequests ( owner , repo , options ) ;
430
+ return {
431
+ content : [ { type : "text" , text : JSON . stringify ( pullRequests , null , 2 ) } ] ,
432
+ } ;
433
+ }
434
+
435
+ case "create_pull_request_review" : {
436
+ const args = pulls . CreatePullRequestReviewSchema . parse ( request . params . arguments ) ;
437
+ const { owner, repo, pull_number, ...options } = args ;
438
+ const review = await pulls . createPullRequestReview ( owner , repo , pull_number , options ) ;
439
+ return {
440
+ content : [ { type : "text" , text : JSON . stringify ( review , null , 2 ) } ] ,
441
+ } ;
442
+ }
443
+
444
+ case "merge_pull_request" : {
445
+ const args = pulls . MergePullRequestSchema . parse ( request . params . arguments ) ;
446
+ const { owner, repo, pull_number, ...options } = args ;
447
+ const result = await pulls . mergePullRequest ( owner , repo , pull_number , options ) ;
448
+ return {
449
+ content : [ { type : "text" , text : JSON . stringify ( result , null , 2 ) } ] ,
450
+ } ;
451
+ }
452
+
453
+ case "get_pull_request_files" : {
454
+ const args = pulls . GetPullRequestFilesSchema . parse ( request . params . arguments ) ;
455
+ const files = await pulls . getPullRequestFiles ( args . owner , args . repo , args . pull_number ) ;
456
+ return {
457
+ content : [ { type : "text" , text : JSON . stringify ( files , null , 2 ) } ] ,
458
+ } ;
459
+ }
460
+
461
+ case "get_pull_request_status" : {
462
+ const args = pulls . GetPullRequestStatusSchema . parse ( request . params . arguments ) ;
463
+ const status = await pulls . getPullRequestStatus ( args . owner , args . repo , args . pull_number ) ;
464
+ return {
465
+ content : [ { type : "text" , text : JSON . stringify ( status , null , 2 ) } ] ,
466
+ } ;
467
+ }
468
+
469
+ case "update_pull_request_branch" : {
470
+ const args = pulls . UpdatePullRequestBranchSchema . parse ( request . params . arguments ) ;
471
+ const { owner, repo, pull_number, expected_head_sha } = args ;
472
+ await pulls . updatePullRequestBranch ( owner , repo , pull_number , expected_head_sha ) ;
473
+ return {
474
+ content : [ { type : "text" , text : JSON . stringify ( { success : true } , null , 2 ) } ] ,
475
+ } ;
476
+ }
477
+
478
+ case "get_pull_request_comments" : {
479
+ const args = pulls . GetPullRequestCommentsSchema . parse ( request . params . arguments ) ;
480
+ const comments = await pulls . getPullRequestComments ( args . owner , args . repo , args . pull_number ) ;
481
+ return {
482
+ content : [ { type : "text" , text : JSON . stringify ( comments , null , 2 ) } ] ,
483
+ } ;
484
+ }
485
+
486
+ case "get_pull_request_reviews" : {
487
+ const args = pulls . GetPullRequestReviewsSchema . parse ( request . params . arguments ) ;
488
+ const reviews = await pulls . getPullRequestReviews ( args . owner , args . repo , args . pull_number ) ;
489
+ return {
490
+ content : [ { type : "text" , text : JSON . stringify ( reviews , null , 2 ) } ] ,
491
+ } ;
492
+ }
493
+
338
494
default :
339
495
throw new Error ( `Unknown tool: ${ request . params . name } ` ) ;
340
496
}
0 commit comments