#
tokens: 1480/50000 4/4 files
lines: off (toggle) GitHub
raw markdown copy
# Directory Structure

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

# Files

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

```markdown
# GitHub Integration

The GitHub MCP server provides functionality to extract diffs from Pull Requests.

## Available Tools

### get_diff_pr
Retrieves the diff content from a GitHub Pull Request.

**Parameters**:
- `owner`: Repository owner/organization name
- `repo`: Repository name
- `pr_number`: Pull Request number

**Returns**: Object containing:
- `content`: String containing the PR diff

## Authentication

**Required**: Set the GitHub Personal Access Token as an environment variable:
```bash
export GITHUB_TOKEN=<your-github-token>
```

The token needs at least `repo` scope permissions to access private repositories. For public repositories, a token with `public_repo` scope is sufficient.

## Error Handling

The server implements standard error handling:
- Missing/invalid token returns `ErrorCode.AuthenticationError`
- Invalid repository details return `ErrorCode.InvalidParams`
- Non-existent PR returns `ErrorCode.NotFound`
- Failed diff fetches return formatted error messages
- Graceful shutdown on SIGINT

## Technical Details

- Built using the Highlight AI MCP SDK
- Uses GitHub REST API v3
- Input validation via Zod
- Runs as a stdio-based MCP server
- Supports Node.js >=18.0.0

## Limitations

- Rate limits apply based on GitHub API restrictions
- Large diffs may be truncated according to GitHub API limits
- Token requires appropriate repository access permissions

```

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

```json
{
    "compilerOptions": {
        "target": "ES2022",
        // "module": "Node16",
        // "moduleResolution": "Node16",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true,
        "resolveJsonModule": true,
        "outDir": ".",
        "rootDir": ".",
        "moduleResolution": "Node",
        "module": "CommonJS"
    },
    "include": [
        "**/*.ts"
    ],
    "exclude": [
        "node_modules"
    ]
}
```

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

```json
{
    "name": "github-mcp-server",
    "version": "0.0.1",
    "type": "module",
    "scripts": {
        "build": "tsc",
        "test": "jest",
        "start": "node dist/index.js"
    },
    "dependencies": {
        "@highlight-ai/mcp-sdk": "^0.0.7",
        "@octokit/rest": "^21.1.0",
        "zod-to-json-schema": "^3.23.5"
    },
    "devDependencies": {
        "@types/jest": "^29.5.11",
        "@types/node": "^20.10.5",
        "jest": "^29.7.0",
        "ts-jest": "^29.1.1",
        "typescript": "^5.3.3"
    }
}
```

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

```typescript
#!/usr/bin/env node
import { Server } from '@highlight-ai/mcp-sdk/server/index.js'
import { StdioServerTransport } from '@highlight-ai/mcp-sdk/server/stdio.js'
import {
    ListToolsRequestSchema,
    GetAuthTokenRequestSchema,
    CallToolRequestSchema,
    ErrorCode,
    McpError,
} from '@highlight-ai/mcp-sdk/types.js'
import { z } from 'zod'
import { Octokit } from '@octokit/rest'

async function getPRDiff(owner: string, repo: string, pullNumber: number, token: string): Promise<string> {
    const octokit = new Octokit({
        auth: token,
    })

    const response = await octokit.pulls.get({
        owner,
        repo,
        pull_number: pullNumber,
        mediaType: {
            format: 'diff',
        },
    })

    return response.data as unknown as string
}

class GithubServer {
    private server: Server
    private githubToken: string

    constructor() {
        const token = process.env.GITHUB_TOKEN
        if (!token) {
            throw new Error('GITHUB_TOKEN environment variable is required')
        }
        this.githubToken = token

        this.server = new Server(
            {
                name: 'github-server',
                version: '0.0.1',
            },
            {
                capabilities: {
                    resources: {},
                    tools: {},
                },
            },
        )

        this.setupHandlers()
        this.setupErrorHandling()
    }

    private setupErrorHandling(): void {
        this.server.onerror = (error) => {
            console.error('[MCP Error]', error)
        }

        process.on('SIGINT', async () => {
            await this.server.close()
            process.exit(0)
        })
    }

    private setupHandlers(): void {
        this.setupToolHandlers()
    }

    private setupToolHandlers(): void {
        // List available tools
        this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
            tools: [
                {
                    name: 'get_pr_diff',
                    description: 'Get the diff of a pull request',
                    inputSchema: {
                        type: 'object',
                        properties: {
                            owner: {
                                type: 'string',
                                description: 'The owner of the repository',
                            },
                            repo: {
                                type: 'string',
                                description: 'The repository name',
                            },
                            pullNumber: {
                                type: 'number',
                                description: 'The pull request number',
                            },
                        },
                        required: ['owner', 'repo', 'pullNumber'],
                    },
                },
            ],
        }))

        // Handle tool calls
        this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
            if (request.params.name !== 'get_pr_diff') {
                throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}`)
            }

            const pullRequestParamsSchema = z.object({
                owner: z.string(),
                repo: z.string(),
                pullNumber: z.number(),
            })

            const parsedParams = pullRequestParamsSchema.safeParse(request.params.arguments)
            if (!parsedParams.success) {
                throw new Error('Invalid arguments')
            }

            const diff = await getPRDiff(
                parsedParams.data.owner,
                parsedParams.data.repo,
                parsedParams.data.pullNumber,
                this.githubToken
            )

            return {
                content: [
                    {
                        type: 'text',
                        text: diff,
                    },
                ],
            }
        })
    }

    async run(): Promise<void> {
        const transport = new StdioServerTransport()
        await this.server.connect(transport)
        console.log('Github MCP server running on stdio')
    }
}

const server = new GithubServer()
server.run().catch(console.error)

```