#
tokens: 2126/50000 4/4 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── package.json
├── README.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # GitHub Integration
 2 | 
 3 | The GitHub MCP server provides functionality to extract diffs from Pull Requests.
 4 | 
 5 | ## Available Tools
 6 | 
 7 | ### get_diff_pr
 8 | Retrieves the diff content from a GitHub Pull Request.
 9 | 
10 | **Parameters**:
11 | - `owner`: Repository owner/organization name
12 | - `repo`: Repository name
13 | - `pr_number`: Pull Request number
14 | 
15 | **Returns**: Object containing:
16 | - `content`: String containing the PR diff
17 | 
18 | ## Authentication
19 | 
20 | **Required**: Set the GitHub Personal Access Token as an environment variable:
21 | ```bash
22 | export GITHUB_TOKEN=<your-github-token>
23 | ```
24 | 
25 | The token needs at least `repo` scope permissions to access private repositories. For public repositories, a token with `public_repo` scope is sufficient.
26 | 
27 | ## Error Handling
28 | 
29 | The server implements standard error handling:
30 | - Missing/invalid token returns `ErrorCode.AuthenticationError`
31 | - Invalid repository details return `ErrorCode.InvalidParams`
32 | - Non-existent PR returns `ErrorCode.NotFound`
33 | - Failed diff fetches return formatted error messages
34 | - Graceful shutdown on SIGINT
35 | 
36 | ## Technical Details
37 | 
38 | - Built using the Highlight AI MCP SDK
39 | - Uses GitHub REST API v3
40 | - Input validation via Zod
41 | - Runs as a stdio-based MCP server
42 | - Supports Node.js >=18.0.0
43 | 
44 | ## Limitations
45 | 
46 | - Rate limits apply based on GitHub API restrictions
47 | - Large diffs may be truncated according to GitHub API limits
48 | - Token requires appropriate repository access permissions
49 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "compilerOptions": {
 3 |         "target": "ES2022",
 4 |         // "module": "Node16",
 5 |         // "moduleResolution": "Node16",
 6 |         "strict": true,
 7 |         "esModuleInterop": true,
 8 |         "skipLibCheck": true,
 9 |         "forceConsistentCasingInFileNames": true,
10 |         "resolveJsonModule": true,
11 |         "outDir": ".",
12 |         "rootDir": ".",
13 |         "moduleResolution": "Node",
14 |         "module": "CommonJS"
15 |     },
16 |     "include": [
17 |         "**/*.ts"
18 |     ],
19 |     "exclude": [
20 |         "node_modules"
21 |     ]
22 | }
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "name": "github-mcp-server",
 3 |     "version": "0.0.1",
 4 |     "type": "module",
 5 |     "scripts": {
 6 |         "build": "tsc",
 7 |         "test": "jest",
 8 |         "start": "node dist/index.js"
 9 |     },
10 |     "dependencies": {
11 |         "@highlight-ai/mcp-sdk": "^0.0.7",
12 |         "@octokit/rest": "^21.1.0",
13 |         "zod-to-json-schema": "^3.23.5"
14 |     },
15 |     "devDependencies": {
16 |         "@types/jest": "^29.5.11",
17 |         "@types/node": "^20.10.5",
18 |         "jest": "^29.7.0",
19 |         "ts-jest": "^29.1.1",
20 |         "typescript": "^5.3.3"
21 |     }
22 | }
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from '@highlight-ai/mcp-sdk/server/index.js'
  3 | import { StdioServerTransport } from '@highlight-ai/mcp-sdk/server/stdio.js'
  4 | import {
  5 |     ListToolsRequestSchema,
  6 |     GetAuthTokenRequestSchema,
  7 |     CallToolRequestSchema,
  8 |     ErrorCode,
  9 |     McpError,
 10 | } from '@highlight-ai/mcp-sdk/types.js'
 11 | import { z } from 'zod'
 12 | import { Octokit } from '@octokit/rest'
 13 | 
 14 | async function getPRDiff(owner: string, repo: string, pullNumber: number, token: string): Promise<string> {
 15 |     const octokit = new Octokit({
 16 |         auth: token,
 17 |     })
 18 | 
 19 |     const response = await octokit.pulls.get({
 20 |         owner,
 21 |         repo,
 22 |         pull_number: pullNumber,
 23 |         mediaType: {
 24 |             format: 'diff',
 25 |         },
 26 |     })
 27 | 
 28 |     return response.data as unknown as string
 29 | }
 30 | 
 31 | class GithubServer {
 32 |     private server: Server
 33 |     private githubToken: string
 34 | 
 35 |     constructor() {
 36 |         const token = process.env.GITHUB_TOKEN
 37 |         if (!token) {
 38 |             throw new Error('GITHUB_TOKEN environment variable is required')
 39 |         }
 40 |         this.githubToken = token
 41 | 
 42 |         this.server = new Server(
 43 |             {
 44 |                 name: 'github-server',
 45 |                 version: '0.0.1',
 46 |             },
 47 |             {
 48 |                 capabilities: {
 49 |                     resources: {},
 50 |                     tools: {},
 51 |                 },
 52 |             },
 53 |         )
 54 | 
 55 |         this.setupHandlers()
 56 |         this.setupErrorHandling()
 57 |     }
 58 | 
 59 |     private setupErrorHandling(): void {
 60 |         this.server.onerror = (error) => {
 61 |             console.error('[MCP Error]', error)
 62 |         }
 63 | 
 64 |         process.on('SIGINT', async () => {
 65 |             await this.server.close()
 66 |             process.exit(0)
 67 |         })
 68 |     }
 69 | 
 70 |     private setupHandlers(): void {
 71 |         this.setupToolHandlers()
 72 |     }
 73 | 
 74 |     private setupToolHandlers(): void {
 75 |         // List available tools
 76 |         this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
 77 |             tools: [
 78 |                 {
 79 |                     name: 'get_pr_diff',
 80 |                     description: 'Get the diff of a pull request',
 81 |                     inputSchema: {
 82 |                         type: 'object',
 83 |                         properties: {
 84 |                             owner: {
 85 |                                 type: 'string',
 86 |                                 description: 'The owner of the repository',
 87 |                             },
 88 |                             repo: {
 89 |                                 type: 'string',
 90 |                                 description: 'The repository name',
 91 |                             },
 92 |                             pullNumber: {
 93 |                                 type: 'number',
 94 |                                 description: 'The pull request number',
 95 |                             },
 96 |                         },
 97 |                         required: ['owner', 'repo', 'pullNumber'],
 98 |                     },
 99 |                 },
100 |             ],
101 |         }))
102 | 
103 |         // Handle tool calls
104 |         this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
105 |             if (request.params.name !== 'get_pr_diff') {
106 |                 throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`)
107 |             }
108 | 
109 |             const pullRequestParamsSchema = z.object({
110 |                 owner: z.string(),
111 |                 repo: z.string(),
112 |                 pullNumber: z.number(),
113 |             })
114 | 
115 |             const parsedParams = pullRequestParamsSchema.safeParse(request.params.arguments)
116 |             if (!parsedParams.success) {
117 |                 throw new Error('Invalid arguments')
118 |             }
119 | 
120 |             const diff = await getPRDiff(
121 |                 parsedParams.data.owner,
122 |                 parsedParams.data.repo,
123 |                 parsedParams.data.pullNumber,
124 |                 this.githubToken
125 |             )
126 | 
127 |             return {
128 |                 content: [
129 |                     {
130 |                         type: 'text',
131 |                         text: diff,
132 |                     },
133 |                 ],
134 |             }
135 |         })
136 |     }
137 | 
138 |     async run(): Promise<void> {
139 |         const transport = new StdioServerTransport()
140 |         await this.server.connect(transport)
141 |         console.log('Github MCP server running on stdio')
142 |     }
143 | }
144 | 
145 | const server = new GithubServer()
146 | server.run().catch(console.error)
147 | 
```