77} from "@modelcontextprotocol/sdk/types.js" ;
88import { z } from 'zod' ;
99import { zodToJsonSchema } from 'zod-to-json-schema' ;
10+ import fetch , { Request , Response } from 'node-fetch' ;
1011
1112import * as repository from './operations/repository.js' ;
1213import * as files from './operations/files.js' ;
@@ -27,6 +28,11 @@ import {
2728} from './common/errors.js' ;
2829import { VERSION } from "./common/version.js" ;
2930
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+
3036const server = new Server (
3137 {
3238 name : "github-mcp-server" ,
@@ -149,6 +155,51 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
149155 name : "get_issue" ,
150156 description : "Get details of a specific issue in a GitHub repository." ,
151157 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 )
152203 }
153204 ] ,
154205 } ;
@@ -248,10 +299,39 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
248299 case "create_issue" : {
249300 const args = issues . CreateIssueSchema . parse ( request . params . arguments ) ;
250301 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+ }
255335 }
256336
257337 case "create_pull_request" : {
@@ -335,6 +415,82 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
335415 } ;
336416 }
337417
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+
338494 default :
339495 throw new Error ( `Unknown tool: ${ request . params . name } ` ) ;
340496 }
0 commit comments