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

```
├── .gitignore
├── CLINE_INSTALL_SCRIPT.md
├── CLINE_INSTALLATION.md
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── index.ts
│   ├── mcp-sdk
│   │   ├── index.js
│   │   ├── stdio.js
│   │   └── types.js
│   ├── server.ts
│   ├── tools
│   │   ├── files.ts
│   │   ├── issues.ts
│   │   ├── pull-requests.ts
│   │   ├── repository.ts
│   │   └── search.ts
│   ├── types
│   │   └── mcp-sdk.d.ts
│   └── utils
│       ├── error-handling.ts
│       ├── github-api.ts
│       └── validation.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependency directories
node_modules/
jspm_packages/

# Build outputs
dist/
build/
out/
*.tsbuildinfo

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# IDE and editor files
.idea/
.vscode/
*.swp
*.swo
.DS_Store
.project
.classpath
.settings/
*.sublime-workspace
*.sublime-project

# Coverage directory used by tools like istanbul
coverage/
*.lcov

# nyc test coverage
.nyc_output

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.test
.env.local

# parcel-bundler cache
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

```

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

```markdown
# GitHub Enterprise MCP Server

MCP Server for the GitHub API, enabling file operations, repository management, search functionality, and more.

## Features

- **Automatic Branch Creation**: When creating/updating files or pushing changes, branches are automatically created if they don't exist
- **Comprehensive Error Handling**: Clear error messages for common issues
- **Git History Preservation**: Operations maintain proper Git history without force pushing
- **Batch Operations**: Support for both single-file and multi-file operations
- **Advanced Search**: Support for searching code, issues/PRs, and users

## Cline Installation Guide

This guide will help you install and configure the GitHub Enterprise MCP server in Cline, enabling you to use GitHub API functionality directly through Cline.

### Prerequisites

1. Node.js installed on your system
2. A GitHub Personal Access Token with appropriate permissions
3. Cline installed on your system

### Installation Steps

#### 1. Clone the Repository

```bash
git clone https://github.com/yourusername/github-enterprise-mcp.git
cd github-enterprise-mcp
```

#### 2. Install Dependencies and Build

```bash
npm install
npm run build
```

This will create a `dist` directory with the compiled JavaScript files.

#### 3. Create a GitHub Personal Access Token

1. Go to [GitHub Personal Access Tokens](https://github.com/settings/tokens) (in GitHub Settings > Developer settings)
2. Click "Generate new token"
3. Select which repositories you'd like this token to have access to (Public, All, or Select)
4. Create a token with the `repo` scope ("Full control of private repositories")
   - Alternatively, if working only with public repositories, select only the `public_repo` scope
5. Copy the generated token

#### 4. Configure Cline MCP Settings

##### For Cline VS Code Extension

1. Open VS Code
2. Locate the Cline MCP settings file at:
   - Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
   - macOS: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
   - Linux: `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`

3. Add the GitHub Enterprise MCP server configuration to the `mcpServers` object:

```json
{
  "mcpServers": {
    "github-enterprise": {
      "command": "node",
      "args": [
        "/absolute/path/to/github-enterprise-mcp/dist/index.js"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
        "GITHUB_API_URL": "https://api.github.com" // For GitHub.com
        // For GitHub Enterprise, use your instance URL, e.g., "https://github.yourdomain.com/api/v3"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

Replace `/absolute/path/to/github-enterprise-mcp/dist/index.js` with the absolute path to the built index.js file.

##### For Claude Desktop App

1. Locate the Claude Desktop configuration file at:
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Linux: `~/.config/Claude/claude_desktop_config.json`

2. Add the GitHub Enterprise MCP server configuration to the `mcpServers` object:

```json
{
  "mcpServers": {
    "github-enterprise": {
      "command": "node",
      "args": [
        "/absolute/path/to/github-enterprise-mcp/dist/index.js"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
        "GITHUB_API_URL": "https://api.github.com" // For GitHub.com
        // For GitHub Enterprise, use your instance URL, e.g., "https://github.yourdomain.com/api/v3"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

#### 5. Restart Cline

After configuring the MCP settings, restart Cline (VS Code or Claude Desktop) to apply the changes.

### Verification

To verify that the GitHub Enterprise MCP server is properly installed and configured, you can ask Cline to use one of the GitHub tools:

```
Can you search for repositories with the keyword "react" using the GitHub Enterprise MCP server?
```

Cline should be able to use the `search_repositories` tool to search for repositories with the keyword "react".

### Interactive Installation with Cline

For an interactive installation experience, copy and paste the following text into Cline, and it will guide you through the installation process:

```
I want you to help me install the GitHub Enterprise MCP server. Here's what I need you to do:

1. First, explain what the GitHub Enterprise MCP server is and what capabilities it will give you.

2. Guide me through the installation process:
   - Help me clone the repository (if I haven't already)
   - Help me install dependencies and build the project
   - Guide me through creating a GitHub Personal Access Token if I don't have one
   - Help me configure the MCP settings in either VS Code or Claude Desktop
   - Verify the installation is working

3. Show me some examples of how I can use the GitHub Enterprise MCP server once it's installed.

Please start by explaining what the GitHub Enterprise MCP server is and what it will allow you to do for me.
```

### Example Usage

After installation, you can ask Cline to perform GitHub operations directly, such as:

- "Create a new repository called 'my-project'"
- "Search for repositories related to machine learning"
- "Create a pull request from my feature branch to main"
- "Get the contents of the README.md file in repository X"
- "List open issues in my repository"

### Troubleshooting

If you encounter issues with the GitHub Enterprise MCP server:

1. Check that the path to the index.js file is correct in your MCP settings
2. Verify that your GitHub Personal Access Token has the necessary permissions
3. Ensure that the GitHub API URL is correct for your GitHub instance
4. Check the logs for any error messages

### Additional Configuration Options

#### GitHub API Version

You can specify a GitHub API version by adding the `GITHUB_API_VERSION` environment variable:

```json
"env": {
  "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
  "GITHUB_API_URL": "https://api.github.com",
  "GITHUB_API_VERSION": "2022-11-28"
}
```

#### Enterprise Authentication

For GitHub Enterprise instances that use different authentication methods, you may need to provide additional configuration. Refer to the [Octokit documentation](https://github.com/octokit/rest.js) for more information.

## Tools

1. `create_or_update_file`
   - Create or update a single file in a repository
   - Inputs:
     - `owner` (string): Repository owner (username or organization)
     - `repo` (string): Repository name
     - `path` (string): Path where to create/update the file
     - `content` (string): Content of the file
     - `message` (string): Commit message
     - `branch` (string): Branch to create/update the file in
     - `sha` (optional string): SHA of file being replaced (for updates)
   - Returns: File content and commit details

2. `push_files`
   - Push multiple files in a single commit
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `branch` (string): Branch to push to
     - `files` (array): Files to push, each with `path` and `content`
     - `message` (string): Commit message
   - Returns: Updated branch reference

3. `search_repositories`
   - Search for GitHub repositories
   - Inputs:
     - `query` (string): Search query
     - `page` (optional number): Page number for pagination
     - `perPage` (optional number): Results per page (max 100)
   - Returns: Repository search results

4. `create_repository`
   - Create a new GitHub repository
   - Inputs:
     - `name` (string): Repository name
     - `description` (optional string): Repository description
     - `private` (optional boolean): Whether repo should be private
     - `autoInit` (optional boolean): Initialize with README
   - Returns: Created repository details

5. `get_file_contents`
   - Get contents of a file or directory
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `path` (string): Path to file/directory
     - `branch` (optional string): Branch to get contents from
   - Returns: File/directory contents

6. `create_issue`
   - Create a new issue
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `title` (string): Issue title
     - `body` (optional string): Issue description
     - `assignees` (optional string[]): Usernames to assign
     - `labels` (optional string[]): Labels to add
     - `milestone` (optional number): Milestone number
   - Returns: Created issue details

7. `create_pull_request`
   - Create a new pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `title` (string): PR title
     - `body` (optional string): PR description
     - `head` (string): Branch containing changes
     - `base` (string): Branch to merge into
     - `draft` (optional boolean): Create as draft PR
     - `maintainer_can_modify` (optional boolean): Allow maintainer edits
   - Returns: Created pull request details

8. `fork_repository`
   - Fork a repository
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `organization` (optional string): Organization to fork to
   - Returns: Forked repository details

9. `create_branch`
   - Create a new branch
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `branch` (string): Name for new branch
     - `from_branch` (optional string): Source branch (defaults to repo default)
   - Returns: Created branch reference

10. `list_issues`
    - List and filter repository issues
    - Inputs:
      - `owner` (string): Repository owner
      - `repo` (string): Repository name
      - `state` (optional string): Filter by state ('open', 'closed', 'all')
      - `labels` (optional string[]): Filter by labels
      - `sort` (optional string): Sort by ('created', 'updated', 'comments')
      - `direction` (optional string): Sort direction ('asc', 'desc')
      - `since` (optional string): Filter by date (ISO 8601 timestamp)
      - `page` (optional number): Page number
      - `per_page` (optional number): Results per page
    - Returns: Array of issue details

11. `update_issue`
    - Update an existing issue
    - Inputs:
      - `owner` (string): Repository owner
      - `repo` (string): Repository name
      - `issue_number` (number): Issue number to update
      - `title` (optional string): New title
      - `body` (optional string): New description
      - `state` (optional string): New state ('open' or 'closed')
      - `labels` (optional string[]): New labels
      - `assignees` (optional string[]): New assignees
      - `milestone` (optional number): New milestone number
    - Returns: Updated issue details

12. `add_issue_comment`
    - Add a comment to an issue
    - Inputs:
      - `owner` (string): Repository owner
      - `repo` (string): Repository name
      - `issue_number` (number): Issue number to comment on
      - `body` (string): Comment text
    - Returns: Created comment details

13. `search_code`
    - Search for code across GitHub repositories
    - Inputs:
      - `q` (string): Search query using GitHub code search syntax
      - `sort` (optional string): Sort field ('indexed' only)
      - `order` (optional string): Sort order ('asc' or 'desc')
      - `per_page` (optional number): Results per page (max 100)
      - `page` (optional number): Page number
    - Returns: Code search results with repository context

14. `search_issues`
    - Search for issues and pull requests
    - Inputs:
      - `q` (string): Search query using GitHub issues search syntax
      - `sort` (optional string): Sort field (comments, reactions, created, etc.)
      - `order` (optional string): Sort order ('asc' or 'desc')
      - `per_page` (optional number): Results per page (max 100)
      - `page` (optional number): Page number
    - Returns: Issue and pull request search results

15. `search_users`
    - Search for GitHub users
    - Inputs:
      - `q` (string): Search query using GitHub users search syntax
      - `sort` (optional string): Sort field (followers, repositories, joined)
      - `order` (optional string): Sort order ('asc' or 'desc')
      - `per_page` (optional number): Results per page (max 100)
      - `page` (optional number): Page number
    - Returns: User search results

16. `list_commits`
   - Gets commits of a branch in a repository
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `page` (optional string): page number
     - `per_page` (optional string): number of record per page
     - `sha` (optional string): branch name
   - Returns: List of commits

17. `get_issue`
   - Gets the contents of an issue within a repository
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `issue_number` (number): Issue number to retrieve
   - Returns: Github Issue object & details

18. `get_pull_request`
   - Get details of a specific pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
   - Returns: Pull request details including diff and review status

19. `list_pull_requests`
   - List and filter repository pull requests
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `state` (optional string): Filter by state ('open', 'closed', 'all')
     - `head` (optional string): Filter by head user/org and branch
     - `base` (optional string): Filter by base branch
     - `sort` (optional string): Sort by ('created', 'updated', 'popularity', 'long-running')
     - `direction` (optional string): Sort direction ('asc', 'desc')
     - `per_page` (optional number): Results per page (max 100)
     - `page` (optional number): Page number
   - Returns: Array of pull request details

20. `create_pull_request_review`
   - Create a review on a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
     - `body` (string): Review comment text
     - `event` (string): Review action ('APPROVE', 'REQUEST_CHANGES', 'COMMENT')
     - `commit_id` (optional string): SHA of commit to review
     - `comments` (optional array): Line-specific comments, each with:
       - `path` (string): File path
       - `position` (number): Line position in diff
       - `body` (string): Comment text
   - Returns: Created review details

21. `merge_pull_request`
   - Merge a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
     - `commit_title` (optional string): Title for merge commit
     - `commit_message` (optional string): Extra detail for merge commit
     - `merge_method` (optional string): Merge method ('merge', 'squash', 'rebase')
   - Returns: Merge result details

22. `get_pull_request_files`
   - Get the list of files changed in a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
   - Returns: Array of changed files with patch and status details

23. `get_pull_request_status`
   - Get the combined status of all status checks for a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
   - Returns: Combined status check results and individual check details

24. `update_pull_request_branch`
   - Update a pull request branch with the latest changes from the base branch (equivalent to GitHub's "Update branch" button)
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
     - `expected_head_sha` (optional string): The expected SHA of the pull request's HEAD ref
   - Returns: Success message when branch is updated

25. `get_pull_request_comments`
   - Get the review comments on a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
   - Returns: Array of pull request review comments with details like the comment text, author, and location in the diff

26. `get_pull_request_reviews`
   - Get the reviews on a pull request
   - Inputs:
     - `owner` (string): Repository owner
     - `repo` (string): Repository name
     - `pull_number` (number): Pull request number
   - Returns: Array of pull request reviews with details like the review state (APPROVED, CHANGES_REQUESTED, etc.), reviewer, and review body

## Search Query Syntax

### Code Search
- `language:javascript`: Search by programming language
- `repo:owner/name`: Search in specific repository
- `path:app/src`: Search in specific path
- `extension:js`: Search by file extension
- Example: `q: "import express" language:typescript path:src/`

### Issues Search
- `is:issue` or `is:pr`: Filter by type
- `is:open` or `is:closed`: Filter by state
- `label:bug`: Search by label
- `author:username`: Search by author
- Example: `q: "memory leak" is:issue is:open label:bug`

### Users Search
- `type:user` or `type:org`: Filter by account type
- `followers:>1000`: Filter by followers
- `location:London`: Search by location
- Example: `q: "fullstack developer" location:London followers:>100`

For detailed search syntax, see [GitHub's searching documentation](https://docs.github.com/en/search-github/searching-on-github).

## Setup

### Personal Access Token
[Create a GitHub Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) with appropriate permissions:
   - Go to [Personal access tokens](https://github.com/settings/tokens) (in GitHub Settings > Developer settings)
   - Select which repositories you'd like this token to have access to (Public, All, or Select)
   - Create a token with the `repo` scope ("Full control of private repositories")
     - Alternatively, if working only with public repositories, select only the `public_repo` scope
   - Copy the generated token

### Usage with Claude Desktop
To use this with Claude Desktop, add the following to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "github": {
      "command": "node",
      "args": [
        "/path/to/github-enterprise-mcp/dist/index.js"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
      }
    }
  }
}
```

## Build

```bash
# Install dependencies
npm install

# Build the project
npm run build

# Start the server
npm start
```

## License

This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.

```

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

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "esModuleInterop": true,
    "strict": true,
    "outDir": "dist",
    "sourceMap": true,
    "declaration": true,
    "resolveJsonModule": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "**/*.test.ts"]
}

```

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

```typescript
#!/usr/bin/env node

import { GitHubEnterpriseServer } from './server.js';

/**
 * Main entry point for the GitHub Enterprise MCP server
 */
async function main(): Promise<void> {
  try {
    const server = new GitHubEnterpriseServer();
    await server.run();
  } catch (error) {
    console.error('Failed to start GitHub Enterprise MCP server:', error);
    process.exit(1);
  }
}

// Start the server
main().catch((error) => {
  console.error('Unhandled error:', error);
  process.exit(1);
});

```

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

```json
{
  "name": "github-enterprise-mcp",
  "version": "1.0.0",
  "description": "MCP Server for GitHub Enterprise API",
  "main": "dist/index.js",
  "type": "module",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "ts-node-esm src/index.ts",
    "test": "jest"
  },
  "keywords": [
    "mcp",
    "github",
    "github-enterprise",
    "api"
  ],
  "author": "",
  "license": "MIT",
  "dependencies": {
    "@modelcontextprotocol/sdk": "^1.8.0",
    "@octokit/rest": "^20.0.2",
    "axios": "^1.6.2",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@types/jest": "^29.5.10",
    "@types/node": "^20.10.0",
    "jest": "^29.7.0",
    "ts-jest": "^29.1.1",
    "ts-node": "^10.9.1",
    "typescript": "^5.3.2"
  }
}

```

--------------------------------------------------------------------------------
/src/mcp-sdk/types.js:
--------------------------------------------------------------------------------

```javascript
/**
 * This is a minimal implementation of the MCP SDK types for the GitHub Enterprise MCP server.
 * In a real-world scenario, you would use the actual @modelcontextprotocol/sdk package.
 */

export const ErrorCode = {
  ParseError: -32700,
  InvalidRequest: -32600,
  MethodNotFound: -32601,
  InvalidParams: -32602,
  InternalError: -32603,
  ConfigurationError: -32000,
  Unauthorized: -32001,
  Forbidden: -32003,
  NotFound: -32004,
};

export class McpError extends Error {
  constructor(code, message) {
    super(message);
    this.code = code;
    this.name = 'McpError';
  }
}

// Schema constants
export const CallToolRequestSchema = { id: 'call_tool' };
export const ListToolsRequestSchema = { id: 'list_tools' };
export const ListResourcesRequestSchema = { id: 'list_resources' };
export const ListResourceTemplatesRequestSchema = { id: 'list_resource_templates' };
export const ReadResourceRequestSchema = { id: 'read_resource' };

```

--------------------------------------------------------------------------------
/src/types/mcp-sdk.d.ts:
--------------------------------------------------------------------------------

```typescript
declare module '@modelcontextprotocol/sdk/server/index.js' {
  export class Server {
    constructor(
      info: { name: string; version: string },
      options: { capabilities: { tools: Record<string, unknown> } }
    );
    
    onerror: (error: any) => void;
    
    setRequestHandler<T>(schema: any, handler: (request: any) => Promise<T>): void;
    
    connect(transport: any): Promise<void>;
    
    close(): Promise<void>;
  }
}

declare module '@modelcontextprotocol/sdk/server/stdio.js' {
  export class StdioServerTransport {
    constructor();
  }
}

declare module '@modelcontextprotocol/sdk/types.js' {
  export enum ErrorCode {
    ParseError = -32700,
    InvalidRequest = -32600,
    MethodNotFound = -32601,
    InvalidParams = -32602,
    InternalError = -32603,
    ConfigurationError = -32000,
    Unauthorized = -32001,
    Forbidden = -32003,
    NotFound = -32004,
  }
  
  export class McpError extends Error {
    constructor(code: ErrorCode, message: string);
    code: ErrorCode;
  }
  
  export const CallToolRequestSchema: any;
  export const ListToolsRequestSchema: any;
  export const ListResourcesRequestSchema: any;
  export const ListResourceTemplatesRequestSchema: any;
  export const ReadResourceRequestSchema: any;
}

```

--------------------------------------------------------------------------------
/src/mcp-sdk/stdio.js:
--------------------------------------------------------------------------------

```javascript
/**
 * This is a minimal implementation of the MCP SDK stdio transport for the GitHub Enterprise MCP server.
 * In a real-world scenario, you would use the actual @modelcontextprotocol/sdk package.
 */

export class StdioServerTransport {
  constructor() {
    this.onRequest = null;
    
    // Set up stdin/stdout handling
    process.stdin.on('data', (data) => {
      try {
        const request = JSON.parse(data.toString());
        if (this.onRequest) {
          this.onRequest(request)
            .then((result) => {
              const response = {
                jsonrpc: '2.0',
                id: request.id,
                result,
              };
              process.stdout.write(JSON.stringify(response) + '\n');
            })
            .catch((error) => {
              const response = {
                jsonrpc: '2.0',
                id: request.id,
                error: {
                  code: error.code || -32603, // Internal error
                  message: error.message || 'Unknown error',
                },
              };
              process.stdout.write(JSON.stringify(response) + '\n');
            });
        }
      } catch (error) {
        console.error('Error processing request:', error);
      }
    });
  }
}

```

--------------------------------------------------------------------------------
/CLINE_INSTALL_SCRIPT.md:
--------------------------------------------------------------------------------

```markdown
# GitHub Enterprise MCP Installation Script for Cline

Copy and paste the following text into Cline to have it guide you through installing the GitHub Enterprise MCP server:

```
I want you to help me install the GitHub Enterprise MCP server. Here's what I need you to do:

1. First, explain what the GitHub Enterprise MCP server is and what capabilities it will give you.

2. Guide me through the installation process:
   - Help me clone the repository (if I haven't already)
   - Help me install dependencies and build the project
   - Guide me through creating a GitHub Personal Access Token if I don't have one
   - Help me configure the MCP settings in either VS Code or Claude Desktop
   - Verify the installation is working

3. Show me some examples of how I can use the GitHub Enterprise MCP server once it's installed.

Please start by explaining what the GitHub Enterprise MCP server is and what it will allow you to do for me.
```

After Cline helps you install the GitHub Enterprise MCP server, you can ask it to perform GitHub operations directly, such as:

- "Create a new repository called 'my-project'"
- "Search for repositories related to machine learning"
- "Create a pull request from my feature branch to main"
- "Get the contents of the README.md file in repository X"
- "List open issues in my repository"

The GitHub Enterprise MCP server enables Cline to interact with GitHub on your behalf, making it easier to manage your GitHub repositories, issues, pull requests, and more without leaving your Cline environment.

```

--------------------------------------------------------------------------------
/src/utils/error-handling.ts:
--------------------------------------------------------------------------------

```typescript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

/**
 * Safely parse JSON with error handling
 * @param input JSON string to parse
 * @param errorMessage Custom error message
 * @returns Parsed JSON object
 */
export function safeJsonParse(input: string, errorMessage = 'Invalid JSON'): any {
  try {
    return JSON.parse(input);
  } catch (error) {
    throw new McpError(ErrorCode.InvalidParams, `${errorMessage}: ${(error as Error).message}`);
  }
}

/**
 * Safely stringify JSON with error handling
 * @param input Object to stringify
 * @param errorMessage Custom error message
 * @returns JSON string
 */
export function safeJsonStringify(input: any, errorMessage = 'Failed to stringify object'): string {
  try {
    return JSON.stringify(input);
  } catch (error) {
    throw new McpError(ErrorCode.InternalError, `${errorMessage}: ${(error as Error).message}`);
  }
}

/**
 * Wrap async function execution with error handling
 * @param fn Async function to execute
 * @param errorMessage Custom error message
 * @returns Result of the function
 */
export async function tryCatchAsync<T>(
  fn: () => Promise<T>,
  errorMessage = 'Operation failed'
): Promise<T> {
  try {
    return await fn();
  } catch (error) {
    if (error instanceof McpError) {
      throw error;
    }
    throw new McpError(
      ErrorCode.InternalError,
      `${errorMessage}: ${(error as Error).message}`
    );
  }
}

/**
 * Wrap synchronous function execution with error handling
 * @param fn Function to execute
 * @param errorMessage Custom error message
 * @returns Result of the function
 */
export function tryCatch<T>(fn: () => T, errorMessage = 'Operation failed'): T {
  try {
    return fn();
  } catch (error) {
    if (error instanceof McpError) {
      throw error;
    }
    throw new McpError(
      ErrorCode.InternalError,
      `${errorMessage}: ${(error as Error).message}`
    );
  }
}

/**
 * Convert a base64 string to UTF-8
 * @param base64 Base64 string
 * @returns UTF-8 string
 */
export function base64ToUtf8(base64: string): string {
  try {
    return Buffer.from(base64, 'base64').toString('utf-8');
  } catch (error) {
    throw new McpError(
      ErrorCode.InternalError,
      `Failed to decode base64 string: ${(error as Error).message}`
    );
  }
}

/**
 * Convert a UTF-8 string to base64
 * @param utf8 UTF-8 string
 * @returns Base64 string
 */
export function utf8ToBase64(utf8: string): string {
  try {
    return Buffer.from(utf8, 'utf-8').toString('base64');
  } catch (error) {
    throw new McpError(
      ErrorCode.InternalError,
      `Failed to encode string to base64: ${(error as Error).message}`
    );
  }
}

/**
 * Validate required environment variables
 * @param variables Array of required environment variable names
 * @throws McpError if any required variable is missing
 */
export function validateEnvVariables(variables: string[]): void {
  const missing = variables.filter(variable => !process.env[variable]);
  if (missing.length > 0) {
    throw new McpError(
      ErrorCode.ConfigurationError,
      `Missing required environment variables: ${missing.join(', ')}`
    );
  }
}

```

--------------------------------------------------------------------------------
/src/mcp-sdk/index.js:
--------------------------------------------------------------------------------

```javascript
/**
 * This is a minimal implementation of the MCP SDK for the GitHub Enterprise MCP server.
 * In a real-world scenario, you would use the actual @modelcontextprotocol/sdk package.
 */

export class Server {
  constructor(info, options) {
    this.info = info;
    this.options = options;
    this.handlers = new Map();
  }

  onerror = (error) => {
    console.error('Server error:', error);
  };

  setRequestHandler(schema, handler) {
    const schemaId = schema.id || schema.name || 'unknown';
    this.handlers.set(schemaId, handler);
  }

  async connect(transport) {
    this.transport = transport;
    console.error(`MCP Server ${this.info.name} v${this.info.version} connected`);
    
    // Set up transport
    if (this.transport) {
      this.transport.onRequest = async (request) => {
        try {
          // Find handler for method
          const handler = this.handlers.get(request.method) || this.handlers.get('unknown');
          if (!handler) {
            throw new McpError(ErrorCode.MethodNotFound, `Method not found: ${request.method}`);
          }
          
          // Call handler
          const result = await handler({ params: request.params });
          return result;
        } catch (error) {
          this.onerror(error);
          throw error;
        }
      };
    }
  }

  async close() {
    console.error(`MCP Server ${this.info.name} v${this.info.version} closed`);
  }
}

export class StdioServerTransport {
  constructor() {
    this.onRequest = null;
    
    // Set up stdin/stdout handling
    process.stdin.on('data', (data) => {
      try {
        const request = JSON.parse(data.toString());
        if (this.onRequest) {
          this.onRequest(request)
            .then((result) => {
              const response = {
                jsonrpc: '2.0',
                id: request.id,
                result,
              };
              process.stdout.write(JSON.stringify(response) + '\n');
            })
            .catch((error) => {
              const response = {
                jsonrpc: '2.0',
                id: request.id,
                error: {
                  code: error.code || ErrorCode.InternalError,
                  message: error.message || 'Unknown error',
                },
              };
              process.stdout.write(JSON.stringify(response) + '\n');
            });
        }
      } catch (error) {
        console.error('Error processing request:', error);
      }
    });
  }
}

export const ErrorCode = {
  ParseError: -32700,
  InvalidRequest: -32600,
  MethodNotFound: -32601,
  InvalidParams: -32602,
  InternalError: -32603,
  ConfigurationError: -32000,
  Unauthorized: -32001,
  Forbidden: -32003,
  NotFound: -32004,
};

export class McpError extends Error {
  constructor(code, message) {
    super(message);
    this.code = code;
    this.name = 'McpError';
  }
}

// Schema constants
export const CallToolRequestSchema = { id: 'call_tool' };
export const ListToolsRequestSchema = { id: 'list_tools' };
export const ListResourcesRequestSchema = { id: 'list_resources' };
export const ListResourceTemplatesRequestSchema = { id: 'list_resource_templates' };
export const ReadResourceRequestSchema = { id: 'read_resource' };

```

--------------------------------------------------------------------------------
/src/utils/github-api.ts:
--------------------------------------------------------------------------------

```typescript
import { Octokit } from '@octokit/rest';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

/**
 * GitHub API client wrapper
 */
export class GitHubApi {
  private octokit: Octokit;
  private baseUrl?: string;

  /**
   * Create a new GitHub API client
   * @param token GitHub Personal Access Token
   * @param baseUrl Optional base URL for GitHub Enterprise
   */
  constructor(token: string, baseUrl?: string) {
    if (!token) {
      throw new McpError(
        ErrorCode.ConfigurationError,
        'GitHub Personal Access Token is required'
      );
    }

    this.baseUrl = baseUrl;
    this.octokit = new Octokit({
      auth: token,
      ...(baseUrl ? { baseUrl } : {}),
    });
  }

  /**
   * Get the Octokit instance
   */
  getOctokit(): Octokit {
    return this.octokit;
  }

  /**
   * Check if a branch exists in a repository
   */
  async branchExists(owner: string, repo: string, branch: string): Promise<boolean> {
    try {
      await this.octokit.git.getRef({
        owner,
        repo,
        ref: `heads/${branch}`,
      });
      return true;
    } catch (error: any) {
      if (error.status === 404) {
        return false;
      }
      throw this.handleApiError(error);
    }
  }

  /**
   * Create a new branch in a repository
   */
  async createBranch(
    owner: string,
    repo: string,
    branch: string,
    fromBranch?: string
  ): Promise<any> {
    try {
      // Get the SHA of the latest commit on the default branch
      const defaultBranch = fromBranch || (await this.getDefaultBranch(owner, repo));
      const { data: refData } = await this.octokit.git.getRef({
        owner,
        repo,
        ref: `heads/${defaultBranch}`,
      });

      // Create a new branch from the default branch
      const { data } = await this.octokit.git.createRef({
        owner,
        repo,
        ref: `refs/heads/${branch}`,
        sha: refData.object.sha,
      });

      return data;
    } catch (error: any) {
      throw this.handleApiError(error);
    }
  }

  /**
   * Get the default branch of a repository
   */
  async getDefaultBranch(owner: string, repo: string): Promise<string> {
    try {
      const { data } = await this.octokit.repos.get({
        owner,
        repo,
      });
      return data.default_branch;
    } catch (error: any) {
      throw this.handleApiError(error);
    }
  }

  /**
   * Handle GitHub API errors
   */
  handleApiError(error: any): Error {
    if (error instanceof McpError) {
      return error;
    }

    const status = error.status || 500;
    const message = error.message || 'Unknown GitHub API error';
    const response = error.response?.data?.message || '';

    // Map HTTP status codes to MCP error codes
    let errorCode: ErrorCode;
    switch (status) {
      case 400:
        errorCode = ErrorCode.InvalidParams;
        break;
      case 401:
        errorCode = ErrorCode.Unauthorized;
        break;
      case 403:
        errorCode = ErrorCode.Forbidden;
        break;
      case 404:
        errorCode = ErrorCode.NotFound;
        break;
      case 422:
        errorCode = ErrorCode.InvalidParams;
        break;
      default:
        errorCode = ErrorCode.InternalError;
    }

    return new McpError(
      errorCode,
      `GitHub API Error: ${message}${response ? ` - ${response}` : ''}`
    );
  }
}

// Create a singleton instance
let githubApiInstance: GitHubApi | null = null;

/**
 * Get the GitHub API instance
 */
export function getGitHubApi(): GitHubApi {
  if (!githubApiInstance) {
    const token = process.env.GITHUB_PERSONAL_ACCESS_TOKEN;
    const baseUrl = process.env.GITHUB_API_URL;
    
    if (!token) {
      throw new McpError(
        ErrorCode.ConfigurationError,
        'GITHUB_PERSONAL_ACCESS_TOKEN environment variable is required'
      );
    }
    
    githubApiInstance = new GitHubApi(token, baseUrl);
  }
  
  return githubApiInstance;
}

```

--------------------------------------------------------------------------------
/src/tools/search.ts:
--------------------------------------------------------------------------------

```typescript
import { getGitHubApi } from '../utils/github-api.js';
import { tryCatchAsync } from '../utils/error-handling.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import {
  SearchCodeSchema,
  SearchIssuesSchema,
  SearchUsersSchema,
} from '../utils/validation.js';

/**
 * Search for code across GitHub repositories
 */
export async function searchCode(args: unknown): Promise<any> {
  const { q, order, page, per_page } = SearchCodeSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().search.code({
      q,
      order,
      page,
      per_page,
    });

    return {
      total_count: data.total_count,
      incomplete_results: data.incomplete_results,
      items: data.items.map((item) => ({
        name: item.name,
        path: item.path,
        sha: item.sha,
        url: item.html_url,
        repository: item.repository ? {
          name: item.repository.name,
          full_name: item.repository.full_name,
          owner: {
            login: item.repository.owner.login,
          },
        } : null,
        score: item.score,
      })),
    };
  }, 'Failed to search code');
}

/**
 * Search for issues and pull requests across GitHub repositories
 */
export async function searchIssues(args: unknown): Promise<any> {
  const { q, sort, order, page, per_page } = SearchIssuesSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().search.issuesAndPullRequests({
      q,
      sort: sort as any,
      order,
      page,
      per_page,
    });

    return {
      total_count: data.total_count,
      incomplete_results: data.incomplete_results,
      items: data.items.map((item) => ({
        id: item.id,
        number: item.number,
        title: item.title,
        state: item.state,
        locked: item.locked,
        repository: item.repository ? {
          name: item.repository.name,
          full_name: item.repository.full_name,
          owner: {
            login: item.repository.owner.login,
          },
        } : null,
        user: item.user ? {
          login: item.user.login,
          id: item.user.id,
        } : null,
        labels: item.labels?.map((label) => 
          typeof label === 'string' ? label : {
            name: label.name,
            color: label.color,
          }
        ),
        comments: item.comments,
        created_at: item.created_at,
        updated_at: item.updated_at,
        closed_at: item.closed_at,
        body: item.body,
        url: item.html_url,
        pull_request: item.pull_request ? {
          url: item.pull_request.html_url,
        } : null,
        score: item.score,
      })),
    };
  }, 'Failed to search issues');
}

/**
 * Search for users on GitHub
 */
export async function searchUsers(args: unknown): Promise<any> {
  const { q, sort, order, page, per_page } = SearchUsersSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().search.users({
      q,
      sort: sort as any,
      order,
      page,
      per_page,
    });

    return {
      total_count: data.total_count,
      incomplete_results: data.incomplete_results,
      items: data.items.map((user) => ({
        login: user.login,
        id: user.id,
        avatar_url: user.avatar_url,
        html_url: user.html_url,
        type: user.type,
        site_admin: user.site_admin,
        score: user.score,
      })),
    };
  }, 'Failed to search users');
}

/**
 * Get license information
 */
export async function getLicenseInfo(): Promise<any> {
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().licenses.getAllCommonlyUsed();

    return data.map((license) => ({
      key: license.key,
      name: license.name,
      spdx_id: license.spdx_id,
      url: license.url,
      node_id: license.node_id,
    }));
  }, 'Failed to get license information');
}

/**
 * Get GitHub Enterprise stats
 */
export async function getEnterpriseStats(): Promise<any> {
  const github = getGitHubApi();
  const baseUrl = process.env.GITHUB_API_URL;

  // This function is only available for GitHub Enterprise
  if (!baseUrl) {
    return {
      error: 'This function is only available for GitHub Enterprise',
    };
  }

  return tryCatchAsync(async () => {
    try {
      // Try to get enterprise stats
      const { data } = await github.getOctokit().request('GET /enterprise/stats/all');
      return data;
    } catch (error) {
      // If not available, return basic information
      return {
        message: 'Enterprise stats not available or insufficient permissions',
        api_url: baseUrl,
      };
    }
  }, 'Failed to get enterprise stats');
}

```

--------------------------------------------------------------------------------
/CLINE_INSTALLATION.md:
--------------------------------------------------------------------------------

```markdown
# Installing GitHub Enterprise MCP Server in Cline

This guide will help you install and configure the GitHub Enterprise MCP server in Cline, enabling you to use GitHub API functionality directly through Cline.

## Prerequisites

1. Node.js installed on your system
2. A GitHub Personal Access Token with appropriate permissions
3. Cline installed on your system

## Installation Steps

### 1. Clone the Repository

```bash
git clone https://github.com/piyushgIITian/github-enterprice-mcp.git
cd github-enterprise-mcp
```

### 2. Install Dependencies and Build

```bash
npm install
npm run build
```

This will create a `dist` directory with the compiled JavaScript files.

### 3. Create a GitHub Personal Access Token

1. Go to [GitHub Personal Access Tokens](https://github.com/settings/tokens) (in GitHub Settings > Developer settings)
2. Click "Generate new token"
3. Select which repositories you'd like this token to have access to (Public, All, or Select)
4. Create a token with the `repo` scope ("Full control of private repositories")
   - Alternatively, if working only with public repositories, select only the `public_repo` scope
5. Copy the generated token

### 4. Configure Cline MCP Settings

#### For Cline VS Code Extension

1. Open VS Code
2. Locate the Cline MCP settings file at:
   - Windows: `%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\settings\cline_mcp_settings.json`
   - macOS: `~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`
   - Linux: `~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`

3. Add the GitHub Enterprise MCP server configuration to the `mcpServers` object:

```json
{
  "mcpServers": {
    "github-enterprise": {
      "command": "node",
      "args": [
        "/absolute/path/to/github-enterprise-mcp/dist/index.js"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
        "GITHUB_API_URL": "https://api.github.com" // For GitHub.com
        // For GitHub Enterprise, use your instance URL, e.g., "https://github.yourdomain.com/api/v3"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

Replace `/absolute/path/to/github-enterprise-mcp/dist/index.js` with the absolute path to the built index.js file.

#### For Claude Desktop App

1. Locate the Claude Desktop configuration file at:
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`
   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Linux: `~/.config/Claude/claude_desktop_config.json`

2. Add the GitHub Enterprise MCP server configuration to the `mcpServers` object:

```json
{
  "mcpServers": {
    "github-enterprise": {
      "command": "node",
      "args": [
        "/absolute/path/to/github-enterprise-mcp/dist/index.js"
      ],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
        "GITHUB_API_URL": "https://api.github.com" // For GitHub.com
        // For GitHub Enterprise, use your instance URL, e.g., "https://github.yourdomain.com/api/v3"
      },
      "disabled": false,
      "autoApprove": []
    }
  }
}
```

### 5. Restart Cline

After configuring the MCP settings, restart Cline (VS Code or Claude Desktop) to apply the changes.

## Verification

To verify that the GitHub Enterprise MCP server is properly installed and configured, you can ask Cline to use one of the GitHub tools:

```
Can you search for repositories with the keyword "react" using the GitHub Enterprise MCP server?
```

Cline should be able to use the `search_repositories` tool to search for repositories with the keyword "react".

## Available Tools

The GitHub Enterprise MCP server provides a wide range of tools for interacting with GitHub, including:

- Repository management (create, update, delete)
- File operations (create, update, get contents)
- Issue and pull request management
- Code, issue, and user search
- Branch management
- And more

For a complete list of available tools and their usage, refer to the [README.md](./README.md) file.

## Troubleshooting

If you encounter issues with the GitHub Enterprise MCP server:

1. Check that the path to the index.js file is correct in your MCP settings
2. Verify that your GitHub Personal Access Token has the necessary permissions
3. Ensure that the GitHub API URL is correct for your GitHub instance
4. Check the logs for any error messages

## Additional Configuration Options

### GitHub API Version

You can specify a GitHub API version by adding the `GITHUB_API_VERSION` environment variable:

```json
"env": {
  "GITHUB_PERSONAL_ACCESS_TOKEN": "your-personal-access-token",
  "GITHUB_API_URL": "https://api.github.com",
  "GITHUB_API_VERSION": "2022-11-28"
}
```

### Enterprise Authentication

For GitHub Enterprise instances that use different authentication methods, you may need to provide additional configuration. Refer to the [Octokit documentation](https://github.com/octokit/rest.js) for more information.

```

--------------------------------------------------------------------------------
/src/tools/files.ts:
--------------------------------------------------------------------------------

```typescript
import { getGitHubApi } from '../utils/github-api.js';
import { tryCatchAsync, base64ToUtf8, utf8ToBase64 } from '../utils/error-handling.js';
import {
  CreateOrUpdateFileSchema,
  PushFilesSchema,
  GetFileContentsSchema,
} from '../utils/validation.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

/**
 * Create or update a file in a GitHub repository
 */
export async function createOrUpdateFile(args: unknown): Promise<any> {
  const { owner, repo, path, content, message, branch, sha } = CreateOrUpdateFileSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    // Check if branch exists, create it if it doesn't
    const branchExists = await github.branchExists(owner, repo, branch);
    if (!branchExists) {
      await github.createBranch(owner, repo, branch);
    }

    // Create or update the file
    const { data } = await github.getOctokit().repos.createOrUpdateFileContents({
      owner,
      repo,
      path,
      message,
      content: utf8ToBase64(content),
      branch,
      sha,
    });

    return {
      content: {
        name: data.content?.name,
        path: data.content?.path,
        sha: data.content?.sha,
        size: data.content?.size,
        url: data.content?.html_url,
      },
      commit: {
        sha: data.commit.sha,
        url: data.commit.html_url,
        message: data.commit.message,
        author: data.commit.author,
        committer: data.commit.committer,
      },
    };
  }, 'Failed to create or update file');
}

/**
 * Push multiple files to a GitHub repository in a single commit
 */
export async function pushFiles(args: unknown): Promise<any> {
  const { owner, repo, branch, files, message } = PushFilesSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    // Check if branch exists, create it if it doesn't
    const branchExists = await github.branchExists(owner, repo, branch);
    if (!branchExists) {
      await github.createBranch(owner, repo, branch);
    }

    // Get the latest commit SHA on the branch
    const { data: refData } = await github.getOctokit().git.getRef({
      owner,
      repo,
      ref: `heads/${branch}`,
    });
    const latestCommitSha = refData.object.sha;

    // Get the commit to get the tree SHA
    const { data: commitData } = await github.getOctokit().git.getCommit({
      owner,
      repo,
      commit_sha: latestCommitSha,
    });
    const baseTreeSha = commitData.tree.sha;

    // Create a new tree with the files
    const tree = await Promise.all(
      files.map(async (file) => {
        // Check if file exists to get its SHA
        let fileSha;
        try {
          const { data: existingFile } = await github.getOctokit().repos.getContent({
            owner,
            repo,
            path: file.path,
            ref: branch,
          });
          
          if (!Array.isArray(existingFile)) {
            fileSha = existingFile.sha;
          }
        } catch (error: any) {
          // File doesn't exist, which is fine for new files
          if (error.status !== 404) {
            throw error;
          }
        }

        return {
          path: file.path,
          mode: '100644' as '100644', // Regular file
          type: 'blob' as 'blob',
          content: file.content,
        };
      })
    );

    // Create a new tree
    const { data: newTree } = await github.getOctokit().git.createTree({
      owner,
      repo,
      base_tree: baseTreeSha,
      tree,
    });

    // Create a new commit
    const { data: newCommit } = await github.getOctokit().git.createCommit({
      owner,
      repo,
      message,
      tree: newTree.sha,
      parents: [latestCommitSha],
    });

    // Update the reference
    const { data: updatedRef } = await github.getOctokit().git.updateRef({
      owner,
      repo,
      ref: `heads/${branch}`,
      sha: newCommit.sha,
    });

    return {
      success: true,
      branch,
      commit: {
        sha: newCommit.sha,
        message,
        url: `https://github.com/${owner}/${repo}/commit/${newCommit.sha}`,
      },
      files: files.map((file) => file.path),
    };
  }, 'Failed to push files');
}

/**
 * Get the contents of a file or directory from a GitHub repository
 */
export async function getFileContents(args: unknown): Promise<any> {
  const { owner, repo, path, branch } = GetFileContentsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().repos.getContent({
      owner,
      repo,
      path,
      ref: branch,
    });

    // Handle directory listing
    if (Array.isArray(data)) {
      return data.map((item) => ({
        name: item.name,
        path: item.path,
        sha: item.sha,
        size: item.size,
        type: item.type,
        url: item.html_url,
        download_url: item.download_url,
      }));
    }

    // Handle file content
    if (data.type === 'file') {
      return {
        name: data.name,
        path: data.path,
        sha: data.sha,
        size: data.size,
        type: data.type,
        url: data.html_url,
        content: data.content ? base64ToUtf8(data.content) : null,
        encoding: data.encoding,
      };
    }

    // Handle submodule or symlink
    return {
      name: data.name,
      path: data.path,
      sha: data.sha,
      size: data.size,
      type: data.type,
      url: data.html_url,
    };
  }, 'Failed to get file contents');
}

/**
 * Fork a GitHub repository
 */
export async function forkRepository(args: unknown): Promise<any> {
  const { owner, repo, organization } = args as { owner: string; repo: string; organization?: string };
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().repos.createFork({
      owner,
      repo,
      organization,
    });

    return {
      id: data.id,
      name: data.name,
      full_name: data.full_name,
      owner: {
        login: data.owner.login,
        id: data.owner.id,
        type: data.owner.type,
      },
      private: data.private,
      html_url: data.html_url,
      description: data.description,
      fork: data.fork,
      created_at: data.created_at,
      updated_at: data.updated_at,
      pushed_at: data.pushed_at,
      default_branch: data.default_branch,
      parent: data.parent ? {
        name: data.parent.name,
        full_name: data.parent.full_name,
        owner: {
          login: data.parent.owner.login,
        },
      } : null,
      source: data.source ? {
        name: data.source.name,
        full_name: data.source.full_name,
        owner: {
          login: data.source.owner.login,
        },
      } : null,
    };
  }, 'Failed to fork repository');
}

/**
 * Get pull request files
 */
export async function getPullRequestFiles(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = args as { owner: string; repo: string; pull_number: number };
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.listFiles({
      owner,
      repo,
      pull_number,
    });

    return data.map((file) => ({
      sha: file.sha,
      filename: file.filename,
      status: file.status,
      additions: file.additions,
      deletions: file.deletions,
      changes: file.changes,
      blob_url: file.blob_url,
      raw_url: file.raw_url,
      contents_url: file.contents_url,
      patch: file.patch,
    }));
  }, 'Failed to get pull request files');
}

```

--------------------------------------------------------------------------------
/src/utils/validation.ts:
--------------------------------------------------------------------------------

```typescript
import { z } from 'zod';

// Common schemas
export const OwnerRepoSchema = z.object({
  owner: z.string().min(1, 'Repository owner is required'),
  repo: z.string().min(1, 'Repository name is required'),
});

export const PaginationSchema = z.object({
  page: z.number().optional(),
  perPage: z.number().min(1).max(100).optional(),
});

// File operations schemas
export const CreateOrUpdateFileSchema = OwnerRepoSchema.extend({
  path: z.string().min(1, 'File path is required'),
  content: z.string().min(1, 'File content is required'),
  message: z.string().min(1, 'Commit message is required'),
  branch: z.string().min(1, 'Branch name is required'),
  sha: z.string().optional(),
});

export const PushFilesSchema = OwnerRepoSchema.extend({
  branch: z.string().min(1, 'Branch name is required'),
  files: z.array(
    z.object({
      path: z.string().min(1, 'File path is required'),
      content: z.string().min(1, 'File content is required'),
    })
  ).min(1, 'At least one file is required'),
  message: z.string().min(1, 'Commit message is required'),
});

export const GetFileContentsSchema = OwnerRepoSchema.extend({
  path: z.string().min(1, 'File path is required'),
  branch: z.string().optional(),
});

// Repository schemas
export const SearchRepositoriesSchema = z.object({
  query: z.string().min(1, 'Search query is required'),
  page: z.number().optional(),
  perPage: z.number().min(1).max(100).optional(),
});

export const CreateRepositorySchema = z.object({
  name: z.string().min(1, 'Repository name is required'),
  description: z.string().optional(),
  private: z.boolean().optional(),
  autoInit: z.boolean().optional(),
  org: z.string().optional(),
});

export const UpdateRepositorySchema = OwnerRepoSchema.extend({
  description: z.string().optional(),
  private: z.boolean().optional(),
  default_branch: z.string().optional(),
  has_issues: z.boolean().optional(),
  has_projects: z.boolean().optional(),
  has_wiki: z.boolean().optional(),
  archived: z.boolean().optional(),
});

export const DeleteRepositorySchema = OwnerRepoSchema.extend({
  confirm: z.boolean().refine(val => val === true, {
    message: 'You must confirm deletion by setting confirm to true',
  }),
});

// Branch schemas
export const CreateBranchSchema = OwnerRepoSchema.extend({
  branch: z.string().min(1, 'Branch name is required'),
  from_branch: z.string().optional(),
});

// Issue schemas
export const ListIssuesSchema = OwnerRepoSchema.extend({
  state: z.enum(['open', 'closed', 'all']).optional(),
  labels: z.array(z.string()).optional(),
  sort: z.enum(['created', 'updated', 'comments']).optional(),
  direction: z.enum(['asc', 'desc']).optional(),
  since: z.string().optional(),
  page: z.number().optional(),
  per_page: z.number().optional(),
});

export const GetIssueSchema = OwnerRepoSchema.extend({
  issue_number: z.number().int().positive(),
});

export const CreateIssueSchema = OwnerRepoSchema.extend({
  title: z.string().min(1, 'Issue title is required'),
  body: z.string().optional(),
  assignees: z.array(z.string()).optional(),
  milestone: z.number().optional(),
  labels: z.array(z.string()).optional(),
});

export const UpdateIssueSchema = OwnerRepoSchema.extend({
  issue_number: z.number().int().positive(),
  title: z.string().optional(),
  body: z.string().optional(),
  assignees: z.array(z.string()).optional(),
  milestone: z.number().optional(),
  labels: z.array(z.string()).optional(),
  state: z.enum(['open', 'closed']).optional(),
});

export const AddIssueCommentSchema = OwnerRepoSchema.extend({
  issue_number: z.number().int().positive(),
  body: z.string().min(1, 'Comment body is required'),
});

// Pull request schemas
export const ListPullRequestsSchema = OwnerRepoSchema.extend({
  state: z.enum(['open', 'closed', 'all']).optional(),
  head: z.string().optional(),
  base: z.string().optional(),
  sort: z.enum(['created', 'updated', 'popularity', 'long-running']).optional(),
  direction: z.enum(['asc', 'desc']).optional(),
  per_page: z.number().optional(),
  page: z.number().optional(),
});

export const GetPullRequestSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
});

export const CreatePullRequestSchema = OwnerRepoSchema.extend({
  title: z.string().min(1, 'Pull request title is required'),
  head: z.string().min(1, 'Head branch is required'),
  base: z.string().min(1, 'Base branch is required'),
  body: z.string().optional(),
  draft: z.boolean().optional(),
  maintainer_can_modify: z.boolean().optional(),
});

export const CreatePullRequestReviewSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
  body: z.string().min(1, 'Review body is required'),
  event: z.enum(['APPROVE', 'REQUEST_CHANGES', 'COMMENT']),
  commit_id: z.string().optional(),
  comments: z
    .array(
      z.object({
        path: z.string().min(1, 'File path is required'),
        position: z.number().int().positive(),
        body: z.string().min(1, 'Comment body is required'),
      })
    )
    .optional(),
});

export const MergePullRequestSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
  commit_title: z.string().optional(),
  commit_message: z.string().optional(),
  merge_method: z.enum(['merge', 'squash', 'rebase']).optional(),
});

export const GetPullRequestFilesSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
});

export const GetPullRequestStatusSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
});

export const UpdatePullRequestBranchSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
  expected_head_sha: z.string().optional(),
});

export const GetPullRequestCommentsSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
});

export const GetPullRequestReviewsSchema = OwnerRepoSchema.extend({
  pull_number: z.number().int().positive(),
});

// Search schemas
export const SearchCodeSchema = z.object({
  q: z.string().min(1, 'Search query is required'),
  order: z.enum(['asc', 'desc']).optional(),
  page: z.number().min(1).optional(),
  per_page: z.number().min(1).max(100).optional(),
});

export const SearchIssuesSchema = z.object({
  q: z.string().min(1, 'Search query is required'),
  sort: z
    .enum([
      'comments',
      'reactions',
      'reactions-+1',
      'reactions--1',
      'reactions-smile',
      'reactions-thinking_face',
      'reactions-heart',
      'reactions-tada',
      'interactions',
      'created',
      'updated',
    ])
    .optional(),
  order: z.enum(['asc', 'desc']).optional(),
  page: z.number().min(1).optional(),
  per_page: z.number().min(1).max(100).optional(),
});

export const SearchUsersSchema = z.object({
  q: z.string().min(1, 'Search query is required'),
  sort: z.enum(['followers', 'repositories', 'joined']).optional(),
  order: z.enum(['asc', 'desc']).optional(),
  page: z.number().min(1).optional(),
  per_page: z.number().min(1).max(100).optional(),
});

// Commits schema
export const ListCommitsSchema = OwnerRepoSchema.extend({
  sha: z.string().optional(),
  page: z.number().optional(),
  perPage: z.number().optional(),
});

// Workflow schemas
export const ListWorkflowsSchema = OwnerRepoSchema.extend({
  page: z.number().int().optional(),
  perPage: z.number().int().optional(),
});

export const ListWorkflowRunsSchema = OwnerRepoSchema.extend({
  workflow_id: z.union([z.string(), z.number()]).optional(),
  branch: z.string().optional(),
  status: z
    .enum([
      'completed',
      'action_required',
      'cancelled',
      'failure',
      'neutral',
      'skipped',
      'stale',
      'success',
      'timed_out',
      'in_progress',
      'queued',
      'requested',
      'waiting',
    ])
    .optional(),
  page: z.number().int().optional(),
  perPage: z.number().int().optional(),
});

export const TriggerWorkflowSchema = OwnerRepoSchema.extend({
  workflow_id: z.union([z.string(), z.number()]),
  ref: z.string().min(1, 'Git reference is required'),
  inputs: z.record(z.string()).optional(),
});

```

--------------------------------------------------------------------------------
/src/tools/issues.ts:
--------------------------------------------------------------------------------

```typescript
import { getGitHubApi } from '../utils/github-api.js';
import { tryCatchAsync } from '../utils/error-handling.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import {
  ListIssuesSchema,
  GetIssueSchema,
  CreateIssueSchema,
  UpdateIssueSchema,
  AddIssueCommentSchema,
} from '../utils/validation.js';

/**
 * List issues in a GitHub repository
 */
export async function listIssues(args: unknown): Promise<any> {
  const { owner, repo, state, labels, sort, direction, since, page, per_page } = ListIssuesSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().issues.listForRepo({
      owner,
      repo,
      state,
      labels: labels?.join(','),
      sort,
      direction,
      since,
      page,
      per_page,
    });

    return data.map((issue) => ({
      id: issue.id,
      number: issue.number,
      title: issue.title,
      state: issue.state,
      locked: issue.locked,
      assignees: issue.assignees?.map((assignee) => ({
        login: assignee.login,
        id: assignee.id,
        type: assignee.type,
      })),
      user: issue.user ? {
        login: issue.user.login,
        id: issue.user.id,
        type: issue.user.type,
      } : null,
      labels: issue.labels?.map((label) => 
        typeof label === 'string' ? label : {
          name: label.name,
          color: label.color,
          description: label.description,
        }
      ),
      milestone: issue.milestone ? {
        id: issue.milestone.id,
        number: issue.milestone.number,
        title: issue.milestone.title,
        description: issue.milestone.description,
        state: issue.milestone.state,
      } : null,
      comments: issue.comments,
      created_at: issue.created_at,
      updated_at: issue.updated_at,
      closed_at: issue.closed_at,
      body: issue.body,
      url: issue.html_url,
      pull_request: issue.pull_request ? {
        url: issue.pull_request.html_url,
      } : null,
    }));
  }, 'Failed to list issues');
}

/**
 * Get a specific issue in a GitHub repository
 */
export async function getIssue(args: unknown): Promise<any> {
  const { owner, repo, issue_number } = GetIssueSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().issues.get({
      owner,
      repo,
      issue_number,
    });

    return {
      id: data.id,
      number: data.number,
      title: data.title,
      state: data.state,
      locked: data.locked,
      assignees: data.assignees?.map((assignee) => ({
        login: assignee.login,
        id: assignee.id,
        type: assignee.type,
      })),
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
        type: data.user.type,
      } : null,
      labels: data.labels?.map((label) => 
        typeof label === 'string' ? label : {
          name: label.name,
          color: label.color,
          description: label.description,
        }
      ),
      milestone: data.milestone ? {
        id: data.milestone.id,
        number: data.milestone.number,
        title: data.milestone.title,
        description: data.milestone.description,
        state: data.milestone.state,
      } : null,
      comments: data.comments,
      created_at: data.created_at,
      updated_at: data.updated_at,
      closed_at: data.closed_at,
      body: data.body,
      url: data.html_url,
      pull_request: data.pull_request ? {
        url: data.pull_request.html_url,
      } : null,
    };
  }, 'Failed to get issue');
}

/**
 * Create a new issue in a GitHub repository
 */
export async function createIssue(args: unknown): Promise<any> {
  const { owner, repo, title, body, assignees, milestone, labels } = CreateIssueSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().issues.create({
      owner,
      repo,
      title,
      body,
      assignees,
      milestone,
      labels,
    });

    return {
      id: data.id,
      number: data.number,
      title: data.title,
      state: data.state,
      assignees: data.assignees?.map((assignee) => ({
        login: assignee.login,
        id: assignee.id,
      })),
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
      } : null,
      labels: data.labels?.map((label) => 
        typeof label === 'string' ? label : {
          name: label.name,
          color: label.color,
        }
      ),
      milestone: data.milestone ? {
        number: data.milestone.number,
        title: data.milestone.title,
      } : null,
      created_at: data.created_at,
      updated_at: data.updated_at,
      body: data.body,
      url: data.html_url,
    };
  }, 'Failed to create issue');
}

/**
 * Update an existing issue in a GitHub repository
 */
export async function updateIssue(args: unknown): Promise<any> {
  const { owner, repo, issue_number, title, body, assignees, milestone, labels, state } = UpdateIssueSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().issues.update({
      owner,
      repo,
      issue_number,
      title,
      body,
      assignees,
      milestone,
      labels,
      state,
    });

    return {
      id: data.id,
      number: data.number,
      title: data.title,
      state: data.state,
      assignees: data.assignees?.map((assignee) => ({
        login: assignee.login,
        id: assignee.id,
      })),
      labels: data.labels?.map((label) => 
        typeof label === 'string' ? label : {
          name: label.name,
          color: label.color,
        }
      ),
      milestone: data.milestone ? {
        number: data.milestone.number,
        title: data.milestone.title,
      } : null,
      updated_at: data.updated_at,
      body: data.body,
      url: data.html_url,
    };
  }, 'Failed to update issue');
}

/**
 * Add a comment to an issue in a GitHub repository
 */
export async function addIssueComment(args: unknown): Promise<any> {
  const { owner, repo, issue_number, body } = AddIssueCommentSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().issues.createComment({
      owner,
      repo,
      issue_number,
      body,
    });

    return {
      id: data.id,
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
      } : null,
      created_at: data.created_at,
      updated_at: data.updated_at,
      body: data.body,
      url: data.html_url,
    };
  }, 'Failed to add issue comment');
}

/**
 * Search for issues and pull requests across GitHub repositories
 */
export async function searchIssues(args: unknown): Promise<any> {
  const { q, sort, order, page, per_page } = args as { 
    q: string; 
    sort?: string; 
    order?: 'asc' | 'desc'; 
    page?: number; 
    per_page?: number;
  };
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().search.issuesAndPullRequests({
      q,
      sort: sort as any,
      order,
      page,
      per_page,
    });

    return {
      total_count: data.total_count,
      incomplete_results: data.incomplete_results,
      items: data.items.map((item) => ({
        id: item.id,
        number: item.number,
        title: item.title,
        state: item.state,
        locked: item.locked,
        repository: item.repository ? {
          name: item.repository.name,
          full_name: item.repository.full_name,
          owner: {
            login: item.repository.owner.login,
          },
        } : null,
        user: item.user ? {
          login: item.user.login,
          id: item.user.id,
        } : null,
        labels: item.labels?.map((label) => 
          typeof label === 'string' ? label : {
            name: label.name,
            color: label.color,
          }
        ),
        comments: item.comments,
        created_at: item.created_at,
        updated_at: item.updated_at,
        closed_at: item.closed_at,
        body: item.body,
        url: item.html_url,
        pull_request: item.pull_request ? {
          url: item.pull_request.html_url,
        } : null,
      })),
    };
  }, 'Failed to search issues');
}

```

--------------------------------------------------------------------------------
/src/tools/repository.ts:
--------------------------------------------------------------------------------

```typescript
import { getGitHubApi } from '../utils/github-api.js';
import { tryCatchAsync } from '../utils/error-handling.js';
import {
  SearchRepositoriesSchema,
  CreateRepositorySchema,
  UpdateRepositorySchema,
  DeleteRepositorySchema,
  CreateBranchSchema,
  ListCommitsSchema,
  ListWorkflowsSchema,
  ListWorkflowRunsSchema,
  TriggerWorkflowSchema,
} from '../utils/validation.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';

/**
 * Search for GitHub repositories
 */
export async function searchRepositories(args: unknown): Promise<any> {
  const { query, page, perPage } = SearchRepositoriesSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().search.repos({
      q: query,
      page,
      per_page: perPage,
    });

    return {
      total_count: data.total_count,
      incomplete_results: data.incomplete_results,
      items: data.items.map((repo) => ({
        id: repo.id,
        name: repo.name,
        full_name: repo.full_name,
        owner: repo.owner ? {
          login: repo.owner.login,
          id: repo.owner.id,
          type: repo.owner.type,
        } : null,
        private: repo.private,
        description: repo.description,
        fork: repo.fork,
        created_at: repo.created_at,
        updated_at: repo.updated_at,
        pushed_at: repo.pushed_at,
        homepage: repo.homepage,
        size: repo.size,
        stargazers_count: repo.stargazers_count,
        watchers_count: repo.watchers_count,
        language: repo.language,
        forks_count: repo.forks_count,
        open_issues_count: repo.open_issues_count,
        default_branch: repo.default_branch,
        url: repo.html_url,
      })),
    };
  }, 'Failed to search repositories');
}

/**
 * Create a new GitHub repository
 */
export async function createRepository(args: unknown): Promise<any> {
  const { name, description, private: isPrivate, autoInit, org } = CreateRepositorySchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    let data;

    if (org) {
      // Create repository in an organization
      const response = await github.getOctokit().repos.createInOrg({
        org,
        name,
        description,
        private: isPrivate,
        auto_init: autoInit,
      });
      data = response.data;
    } else {
      // Create repository for the authenticated user
      const response = await github.getOctokit().repos.createForAuthenticatedUser({
        name,
        description,
        private: isPrivate,
        auto_init: autoInit,
      });
      data = response.data;
    }

    return {
      id: data.id,
      name: data.name,
      full_name: data.full_name,
      private: data.private,
      description: data.description,
      html_url: data.html_url,
      clone_url: data.clone_url,
      ssh_url: data.ssh_url,
      created_at: data.created_at,
      updated_at: data.updated_at,
      default_branch: data.default_branch,
    };
  }, 'Failed to create repository');
}

/**
 * Update an existing GitHub repository
 */
export async function updateRepository(args: unknown): Promise<any> {
  const {
    owner,
    repo,
    description,
    private: isPrivate,
    default_branch,
    has_issues,
    has_projects,
    has_wiki,
    archived,
  } = UpdateRepositorySchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().repos.update({
      owner,
      repo,
      description,
      private: isPrivate,
      default_branch,
      has_issues,
      has_projects,
      has_wiki,
      archived,
    });

    return {
      id: data.id,
      name: data.name,
      full_name: data.full_name,
      private: data.private,
      description: data.description,
      html_url: data.html_url,
      default_branch: data.default_branch,
      has_issues: data.has_issues,
      has_projects: data.has_projects,
      has_wiki: data.has_wiki,
      archived: data.archived,
      updated_at: data.updated_at,
    };
  }, 'Failed to update repository');
}

/**
 * Delete a GitHub repository
 */
export async function deleteRepository(args: unknown): Promise<any> {
  const { owner, repo, confirm } = DeleteRepositorySchema.parse(args);
  
  if (!confirm) {
    throw new McpError(
      ErrorCode.InvalidParams,
      'You must confirm deletion by setting confirm to true'
    );
  }
  
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    await github.getOctokit().repos.delete({
      owner,
      repo,
    });

    return {
      success: true,
      message: `Repository ${owner}/${repo} has been deleted`,
    };
  }, 'Failed to delete repository');
}

/**
 * Create a new branch in a GitHub repository
 */
export async function createBranch(args: unknown): Promise<any> {
  const { owner, repo, branch, from_branch } = CreateBranchSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    // Check if branch already exists
    try {
      await github.getOctokit().git.getRef({
        owner,
        repo,
        ref: `heads/${branch}`,
      });
      
      return {
        success: false,
        message: `Branch '${branch}' already exists in ${owner}/${repo}`,
      };
    } catch (error: any) {
      // If error is not 404 (not found), rethrow it
      if (error.status !== 404) {
        throw error;
      }
    }

    // Get the SHA of the latest commit on the source branch
    const sourceBranch = from_branch || await github.getDefaultBranch(owner, repo);
    const { data: refData } = await github.getOctokit().git.getRef({
      owner,
      repo,
      ref: `heads/${sourceBranch}`,
    });

    // Create a new branch from the source branch
    const { data } = await github.getOctokit().git.createRef({
      owner,
      repo,
      ref: `refs/heads/${branch}`,
      sha: refData.object.sha,
    });

    return {
      success: true,
      ref: data.ref,
      url: data.url,
      object: {
        sha: data.object.sha,
        type: data.object.type,
        url: data.object.url,
      },
      message: `Branch '${branch}' created from '${sourceBranch}' in ${owner}/${repo}`,
    };
  }, 'Failed to create branch');
}

/**
 * List commits in a GitHub repository
 */
export async function listCommits(args: unknown): Promise<any> {
  const { owner, repo, sha, page, perPage } = ListCommitsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().repos.listCommits({
      owner,
      repo,
      sha,
      page,
      per_page: perPage,
    });

    return data.map((commit) => ({
      sha: commit.sha,
      commit: {
        author: commit.commit.author,
        committer: commit.commit.committer,
        message: commit.commit.message,
      },
      author: commit.author ? {
        login: commit.author.login,
        id: commit.author.id,
        type: commit.author.type,
      } : null,
      committer: commit.committer ? {
        login: commit.committer.login,
        id: commit.committer.id,
        type: commit.committer.type,
      } : null,
      html_url: commit.html_url,
    }));
  }, 'Failed to list commits');
}

/**
 * List workflows in a GitHub repository
 */
export async function listWorkflows(args: unknown): Promise<any> {
  const { owner, repo, page, perPage } = ListWorkflowsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().actions.listRepoWorkflows({
      owner,
      repo,
      page,
      per_page: perPage,
    });

    return {
      total_count: data.total_count,
      workflows: data.workflows.map((workflow) => ({
        id: workflow.id,
        name: workflow.name,
        path: workflow.path,
        state: workflow.state,
        created_at: workflow.created_at,
        updated_at: workflow.updated_at,
        url: workflow.html_url,
      })),
    };
  }, 'Failed to list workflows');
}

/**
 * List workflow runs in a GitHub repository
 */
export async function listWorkflowRuns(args: unknown): Promise<any> {
  const { owner, repo, workflow_id, branch, status, page, perPage } = ListWorkflowRunsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    let data;

    if (workflow_id) {
      // List runs for a specific workflow
      const response = await github.getOctokit().actions.listWorkflowRuns({
        owner,
        repo,
        workflow_id,
        branch,
        status: status as any,
        page,
        per_page: perPage,
      });
      data = response.data;
    } else {
      // List all workflow runs
      const response = await github.getOctokit().actions.listWorkflowRunsForRepo({
        owner,
        repo,
        branch,
        status: status as any,
        page,
        per_page: perPage,
      });
      data = response.data;
    }

    return {
      total_count: data.total_count,
      workflow_runs: data.workflow_runs.map((run) => ({
        id: run.id,
        name: run.name,
        workflow_id: run.workflow_id,
        head_branch: run.head_branch,
        head_sha: run.head_sha,
        run_number: run.run_number,
        event: run.event,
        status: run.status,
        conclusion: run.conclusion,
        created_at: run.created_at,
        updated_at: run.updated_at,
        url: run.html_url,
      })),
    };
  }, 'Failed to list workflow runs');
}

/**
 * Trigger a workflow run in a GitHub repository
 */
export async function triggerWorkflow(args: unknown): Promise<any> {
  const { owner, repo, workflow_id, ref, inputs } = TriggerWorkflowSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().actions.createWorkflowDispatch({
      owner,
      repo,
      workflow_id,
      ref,
      inputs,
    });

    return {
      success: true,
      message: `Workflow dispatch event created for workflow ${workflow_id} on ref ${ref}`,
      data,
    };
  }, 'Failed to trigger workflow');
}

```

--------------------------------------------------------------------------------
/src/tools/pull-requests.ts:
--------------------------------------------------------------------------------

```typescript
import { getGitHubApi } from '../utils/github-api.js';
import { tryCatchAsync } from '../utils/error-handling.js';
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import {
  ListPullRequestsSchema,
  GetPullRequestSchema,
  CreatePullRequestSchema,
  CreatePullRequestReviewSchema,
  MergePullRequestSchema,
  GetPullRequestFilesSchema,
  GetPullRequestStatusSchema,
  UpdatePullRequestBranchSchema,
  GetPullRequestCommentsSchema,
  GetPullRequestReviewsSchema,
} from '../utils/validation.js';

/**
 * List pull requests in a GitHub repository
 */
export async function listPullRequests(args: unknown): Promise<any> {
  const { owner, repo, state, head, base, sort, direction, per_page, page } = ListPullRequestsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.list({
      owner,
      repo,
      state,
      head,
      base,
      sort,
      direction,
      per_page,
      page,
    });

    return data.map((pr) => ({
      id: pr.id,
      number: pr.number,
      title: pr.title,
      state: pr.state,
      locked: pr.locked,
      user: pr.user ? {
        login: pr.user.login,
        id: pr.user.id,
        type: pr.user.type,
      } : null,
      created_at: pr.created_at,
      updated_at: pr.updated_at,
      closed_at: pr.closed_at,
      merged_at: pr.merged_at,
      merge_commit_sha: pr.merge_commit_sha,
      draft: pr.draft,
      head: {
        ref: pr.head.ref,
        sha: pr.head.sha,
        repo: pr.head.repo ? {
          name: pr.head.repo.name,
          full_name: pr.head.repo.full_name,
          owner: {
            login: pr.head.repo.owner.login,
          },
        } : null,
      },
      base: {
        ref: pr.base.ref,
        sha: pr.base.sha,
        repo: pr.base.repo ? {
          name: pr.base.repo.name,
          full_name: pr.base.repo.full_name,
          owner: {
            login: pr.base.repo.owner.login,
          },
        } : null,
      },
      body: pr.body,
      url: pr.html_url,
    }));
  }, 'Failed to list pull requests');
}

/**
 * Get a specific pull request in a GitHub repository
 */
export async function getPullRequest(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = GetPullRequestSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.get({
      owner,
      repo,
      pull_number,
    });

    return {
      id: data.id,
      number: data.number,
      title: data.title,
      state: data.state,
      locked: data.locked,
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
        type: data.user.type,
      } : null,
      created_at: data.created_at,
      updated_at: data.updated_at,
      closed_at: data.closed_at,
      merged_at: data.merged_at,
      merge_commit_sha: data.merge_commit_sha,
      draft: data.draft,
      head: {
        ref: data.head.ref,
        sha: data.head.sha,
        repo: data.head.repo ? {
          name: data.head.repo.name,
          full_name: data.head.repo.full_name,
          owner: {
            login: data.head.repo.owner.login,
          },
        } : null,
      },
      base: {
        ref: data.base.ref,
        sha: data.base.sha,
        repo: data.base.repo ? {
          name: data.base.repo.name,
          full_name: data.base.repo.full_name,
          owner: {
            login: data.base.repo.owner.login,
          },
        } : null,
      },
      body: data.body,
      url: data.html_url,
      mergeable: data.mergeable,
      mergeable_state: data.mergeable_state,
      merged: data.merged,
      merged_by: data.merged_by ? {
        login: data.merged_by.login,
        id: data.merged_by.id,
      } : null,
      comments: data.comments,
      review_comments: data.review_comments,
      commits: data.commits,
      additions: data.additions,
      deletions: data.deletions,
      changed_files: data.changed_files,
    };
  }, 'Failed to get pull request');
}

/**
 * Create a new pull request in a GitHub repository
 */
export async function createPullRequest(args: unknown): Promise<any> {
  const { owner, repo, title, head, base, body, draft, maintainer_can_modify } = CreatePullRequestSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.create({
      owner,
      repo,
      title,
      head,
      base,
      body,
      draft,
      maintainer_can_modify,
    });

    return {
      id: data.id,
      number: data.number,
      title: data.title,
      state: data.state,
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
      } : null,
      created_at: data.created_at,
      updated_at: data.updated_at,
      head: {
        ref: data.head.ref,
        sha: data.head.sha,
        repo: data.head.repo ? {
          name: data.head.repo.name,
          full_name: data.head.repo.full_name,
        } : null,
      },
      base: {
        ref: data.base.ref,
        sha: data.base.sha,
        repo: data.base.repo ? {
          name: data.base.repo.name,
          full_name: data.base.repo.full_name,
        } : null,
      },
      body: data.body,
      draft: data.draft,
      url: data.html_url,
    };
  }, 'Failed to create pull request');
}

/**
 * Create a review on a pull request
 */
export async function createPullRequestReview(args: unknown): Promise<any> {
  const { owner, repo, pull_number, body, event, commit_id, comments } = CreatePullRequestReviewSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.createReview({
      owner,
      repo,
      pull_number,
      body,
      event,
      commit_id,
      comments,
    });

    return {
      id: data.id,
      user: data.user ? {
        login: data.user.login,
        id: data.user.id,
      } : null,
      body: data.body,
      state: data.state,
      commit_id: data.commit_id,
      submitted_at: data.submitted_at,
      url: data.html_url,
    };
  }, 'Failed to create pull request review');
}

/**
 * Merge a pull request
 */
export async function mergePullRequest(args: unknown): Promise<any> {
  const { owner, repo, pull_number, commit_title, commit_message, merge_method } = MergePullRequestSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.merge({
      owner,
      repo,
      pull_number,
      commit_title,
      commit_message,
      merge_method,
    });

    return {
      merged: data.merged,
      message: data.message,
      sha: data.sha,
    };
  }, 'Failed to merge pull request');
}

/**
 * Get the list of files changed in a pull request
 */
export async function getPullRequestFiles(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = GetPullRequestFilesSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.listFiles({
      owner,
      repo,
      pull_number,
    });

    return data.map((file) => ({
      sha: file.sha,
      filename: file.filename,
      status: file.status,
      additions: file.additions,
      deletions: file.deletions,
      changes: file.changes,
      blob_url: file.blob_url,
      raw_url: file.raw_url,
      contents_url: file.contents_url,
      patch: file.patch,
    }));
  }, 'Failed to get pull request files');
}

/**
 * Get the combined status of all status checks for a pull request
 */
export async function getPullRequestStatus(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = GetPullRequestStatusSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    // First get the pull request to get the head SHA
    const { data: pr } = await github.getOctokit().pulls.get({
      owner,
      repo,
      pull_number,
    });

    // Then get the combined status for the head SHA
    const { data } = await github.getOctokit().repos.getCombinedStatusForRef({
      owner,
      repo,
      ref: pr.head.sha,
    });

    return {
      state: data.state,
      statuses: data.statuses.map((status) => ({
        context: status.context,
        state: status.state,
        description: status.description,
        target_url: status.target_url,
        created_at: status.created_at,
        updated_at: status.updated_at,
      })),
      sha: data.sha,
      total_count: data.total_count,
      repository: {
        name: data.repository.name,
        full_name: data.repository.full_name,
        owner: {
          login: data.repository.owner.login,
        },
      },
    };
  }, 'Failed to get pull request status');
}

/**
 * Update a pull request branch with the latest changes from the base branch
 */
export async function updatePullRequestBranch(args: unknown): Promise<any> {
  const { owner, repo, pull_number, expected_head_sha } = UpdatePullRequestBranchSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.updateBranch({
      owner,
      repo,
      pull_number,
      expected_head_sha,
    });

    return {
      message: data.message,
      url: data.url,
    };
  }, 'Failed to update pull request branch');
}

/**
 * Get the review comments on a pull request
 */
export async function getPullRequestComments(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = GetPullRequestCommentsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.listReviewComments({
      owner,
      repo,
      pull_number,
    });

    return data.map((comment) => ({
      id: comment.id,
      user: comment.user ? {
        login: comment.user.login,
        id: comment.user.id,
      } : null,
      body: comment.body,
      created_at: comment.created_at,
      updated_at: comment.updated_at,
      path: comment.path,
      position: comment.position,
      commit_id: comment.commit_id,
      url: comment.html_url,
    }));
  }, 'Failed to get pull request comments');
}

/**
 * Get the reviews on a pull request
 */
export async function getPullRequestReviews(args: unknown): Promise<any> {
  const { owner, repo, pull_number } = GetPullRequestReviewsSchema.parse(args);
  const github = getGitHubApi();

  return tryCatchAsync(async () => {
    const { data } = await github.getOctokit().pulls.listReviews({
      owner,
      repo,
      pull_number,
    });

    return data.map((review) => ({
      id: review.id,
      user: review.user ? {
        login: review.user.login,
        id: review.user.id,
      } : null,
      body: review.body,
      state: review.state,
      commit_id: review.commit_id,
      submitted_at: review.submitted_at,
      url: review.html_url,
    }));
  }, 'Failed to get pull request reviews');
}

```

--------------------------------------------------------------------------------
/src/server.ts:
--------------------------------------------------------------------------------

```typescript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
  McpError,
  ErrorCode,
} from '@modelcontextprotocol/sdk/types.js';
import { validateEnvVariables } from './utils/error-handling.js';
import { safeJsonParse } from './utils/error-handling.js';

// Import all tools
import {
  searchRepositories,
  createRepository,
  updateRepository,
  deleteRepository,
  createBranch,
  listCommits,
  listWorkflows,
  listWorkflowRuns,
  triggerWorkflow,
} from './tools/repository.js';

import {
  createOrUpdateFile,
  pushFiles,
  getFileContents,
  forkRepository,
  getPullRequestFiles,
} from './tools/files.js';

import {
  listIssues,
  getIssue,
  createIssue,
  updateIssue,
  addIssueComment,
  searchIssues as searchIssuesAndPRs,
} from './tools/issues.js';

import {
  listPullRequests,
  getPullRequest,
  createPullRequest,
  createPullRequestReview,
  mergePullRequest,
  getPullRequestStatus,
  updatePullRequestBranch,
  getPullRequestComments,
  getPullRequestReviews,
} from './tools/pull-requests.js';

import {
  searchCode,
  searchIssues,
  searchUsers,
  getLicenseInfo,
  getEnterpriseStats,
} from './tools/search.js';

/**
 * GitHub Enterprise MCP Server
 */
export class GitHubEnterpriseServer {
  private server: Server;

  constructor() {
    // Validate required environment variables
    validateEnvVariables(['GITHUB_PERSONAL_ACCESS_TOKEN']);

    // Create MCP server
    this.server = new Server(
      {
        name: 'github-enterprise',
        version: '1.0.0',
      },
      {
        capabilities: {
          tools: {},
        },
      }
    );

    // Set up request handlers
    this.setupRequestHandlers();

    // Set up error handler
    this.server.onerror = (error) => {
      console.error('[GitHub Enterprise MCP Server Error]', error);
    };
  }

  /**
   * Set up request handlers for the MCP server
   */
  private setupRequestHandlers(): void {
    // List available tools
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        // Repository tools
        {
          name: 'search-repositories',
          description: 'Search for GitHub repositories',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: 'Search query (see GitHub search syntax)',
              },
              page: {
                type: 'number',
                description: 'Page number for pagination (default: 1)',
              },
              perPage: {
                type: 'number',
                description: 'Number of results per page (default: 30, max: 100)',
              },
            },
            required: ['query'],
            additionalProperties: false,
          },
        },
        {
          name: 'create-repository',
          description: 'Create a new GitHub repository in your account',
          inputSchema: {
            type: 'object',
            properties: {
              name: {
                type: 'string',
                description: 'Repository name',
              },
              description: {
                type: 'string',
                description: 'Repository description',
              },
              private: {
                type: 'boolean',
                description: 'Whether the repository should be private',
              },
              autoInit: {
                type: 'boolean',
                description: 'Initialize with README.md',
              },
            },
            required: ['name'],
            additionalProperties: false,
          },
        },
        {
          name: 'update-repository',
          description: 'Update an existing GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              description: {
                type: 'string',
                description: 'New description',
              },
              private: {
                type: 'boolean',
                description: 'Change privacy setting',
              },
              default_branch: {
                type: 'string',
                description: 'Change default branch',
              },
              has_issues: {
                type: 'boolean',
                description: 'Enable/disable issues',
              },
              has_projects: {
                type: 'boolean',
                description: 'Enable/disable projects',
              },
              has_wiki: {
                type: 'boolean',
                description: 'Enable/disable wiki',
              },
              archived: {
                type: 'boolean',
                description: 'Archive/unarchive repository',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'delete-repository',
          description: 'Delete a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              confirm: {
                type: 'boolean',
                description: 'Confirmation for deletion (must be true)',
              },
            },
            required: ['owner', 'repo', 'confirm'],
            additionalProperties: false,
          },
        },
        {
          name: 'create-branch',
          description: 'Create a new branch in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              branch: {
                type: 'string',
                description: 'Name for the new branch',
              },
              from_branch: {
                type: 'string',
                description: 'Source branch to create from (defaults to the repository\'s default branch)',
              },
            },
            required: ['owner', 'repo', 'branch'],
            additionalProperties: false,
          },
        },
        {
          name: 'list-commits',
          description: 'Get list of commits of a branch in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              sha: {
                type: 'string',
              },
              page: {
                type: 'number',
              },
              perPage: {
                type: 'number',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'list-workflows',
          description: 'List workflows in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              page: {
                type: 'integer',
                description: 'Page number',
              },
              perPage: {
                type: 'integer',
                description: 'Items per page',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'list-workflow-runs',
          description: 'List workflow runs in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              workflow_id: {
                type: ['string', 'number'],
                description: 'Workflow ID or file name',
              },
              branch: {
                type: 'string',
                description: 'Filter by branch name',
              },
              status: {
                type: 'string',
                enum: [
                  'completed',
                  'action_required',
                  'cancelled',
                  'failure',
                  'neutral',
                  'skipped',
                  'stale',
                  'success',
                  'timed_out',
                  'in_progress',
                  'queued',
                  'requested',
                  'waiting',
                ],
                description: 'Filter by run status',
              },
              page: {
                type: 'integer',
                description: 'Page number',
              },
              perPage: {
                type: 'integer',
                description: 'Items per page',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'trigger-workflow',
          description: 'Trigger a workflow run in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              workflow_id: {
                type: ['string', 'number'],
                description: 'Workflow ID or file name',
              },
              ref: {
                type: 'string',
                description: 'Git reference (branch, tag, SHA)',
              },
              inputs: {
                type: 'object',
                description: 'Workflow inputs',
              },
            },
            required: ['owner', 'repo', 'workflow_id', 'ref'],
            additionalProperties: false,
          },
        },
        // File operations tools
        {
          name: 'create-or-update-file',
          description: 'Create or update a single file in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              path: {
                type: 'string',
                description: 'Path where to create/update the file',
              },
              content: {
                type: 'string',
                description: 'Content of the file',
              },
              message: {
                type: 'string',
                description: 'Commit message',
              },
              branch: {
                type: 'string',
                description: 'Branch to create/update the file in',
              },
              sha: {
                type: 'string',
                description: 'SHA of the file being replaced (required when updating existing files)',
              },
            },
            required: ['owner', 'repo', 'path', 'content', 'message', 'branch'],
            additionalProperties: false,
          },
        },
        {
          name: 'push-files',
          description: 'Push multiple files to a GitHub repository in a single commit',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              branch: {
                type: 'string',
                description: 'Branch to push to (e.g., \'main\' or \'master\')',
              },
              files: {
                type: 'array',
                items: {
                  type: 'object',
                  properties: {
                    path: {
                      type: 'string',
                    },
                    content: {
                      type: 'string',
                    },
                  },
                  required: ['path', 'content'],
                  additionalProperties: false,
                },
                description: 'Array of files to push',
              },
              message: {
                type: 'string',
                description: 'Commit message',
              },
            },
            required: ['owner', 'repo', 'branch', 'files', 'message'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-file-contents',
          description: 'Get the contents of a file or directory from a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              path: {
                type: 'string',
                description: 'Path to the file or directory',
              },
              branch: {
                type: 'string',
                description: 'Branch to get contents from',
              },
            },
            required: ['owner', 'repo', 'path'],
            additionalProperties: false,
          },
        },
        {
          name: 'fork-repository',
          description: 'Fork a GitHub repository to your account or specified organization',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              organization: {
                type: 'string',
                description: 'Optional: organization to fork to (defaults to your personal account)',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        // Issue tools
        {
          name: 'list-issues',
          description: 'List and filter repository issues',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              state: {
                type: 'string',
                enum: ['open', 'closed', 'all'],
              },
              labels: {
                type: 'array',
                items: {
                  type: 'string',
                },
              },
              sort: {
                type: 'string',
                enum: ['created', 'updated', 'comments'],
              },
              direction: {
                type: 'string',
                enum: ['asc', 'desc'],
              },
              since: {
                type: 'string',
              },
              page: {
                type: 'number',
              },
              per_page: {
                type: 'number',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-issue',
          description: 'Get details of a specific issue in a GitHub repository.',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              issue_number: {
                type: 'number',
              },
            },
            required: ['owner', 'repo', 'issue_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'create-issue',
          description: 'Create a new issue in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              title: {
                type: 'string',
              },
              body: {
                type: 'string',
              },
              assignees: {
                type: 'array',
                items: {
                  type: 'string',
                },
              },
              milestone: {
                type: 'number',
              },
              labels: {
                type: 'array',
                items: {
                  type: 'string',
                },
              },
            },
            required: ['owner', 'repo', 'title'],
            additionalProperties: false,
          },
        },
        {
          name: 'update-issue',
          description: 'Update an existing issue in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              issue_number: {
                type: 'number',
              },
              title: {
                type: 'string',
              },
              body: {
                type: 'string',
              },
              assignees: {
                type: 'array',
                items: {
                  type: 'string',
                },
              },
              milestone: {
                type: 'number',
              },
              labels: {
                type: 'array',
                items: {
                  type: 'string',
                },
              },
              state: {
                type: 'string',
                enum: ['open', 'closed'],
              },
            },
            required: ['owner', 'repo', 'issue_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'add-issue-comment',
          description: 'Add a comment to an existing issue',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
              },
              repo: {
                type: 'string',
              },
              issue_number: {
                type: 'number',
              },
              body: {
                type: 'string',
              },
            },
            required: ['owner', 'repo', 'issue_number', 'body'],
            additionalProperties: false,
          },
        },
        // Pull request tools
        {
          name: 'list-pull-requests',
          description: 'List and filter repository pull requests',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              state: {
                type: 'string',
                enum: ['open', 'closed', 'all'],
                description: 'State of the pull requests to return',
              },
              head: {
                type: 'string',
                description: 'Filter by head user or head organization and branch name',
              },
              base: {
                type: 'string',
                description: 'Filter by base branch name',
              },
              sort: {
                type: 'string',
                enum: ['created', 'updated', 'popularity', 'long-running'],
                description: 'What to sort results by',
              },
              direction: {
                type: 'string',
                enum: ['asc', 'desc'],
                description: 'The direction of the sort',
              },
              per_page: {
                type: 'number',
                description: 'Results per page (max 100)',
              },
              page: {
                type: 'number',
                description: 'Page number of the results',
              },
            },
            required: ['owner', 'repo'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-pull-request',
          description: 'Get details of a specific pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'create-pull-request',
          description: 'Create a new pull request in a GitHub repository',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              title: {
                type: 'string',
                description: 'Pull request title',
              },
              body: {
                type: 'string',
                description: 'Pull request body/description',
              },
              head: {
                type: 'string',
                description: 'The name of the branch where your changes are implemented',
              },
              base: {
                type: 'string',
                description: 'The name of the branch you want the changes pulled into',
              },
              draft: {
                type: 'boolean',
                description: 'Whether to create the pull request as a draft',
              },
              maintainer_can_modify: {
                type: 'boolean',
                description: 'Whether maintainers can modify the pull request',
              },
            },
            required: ['owner', 'repo', 'title', 'head', 'base'],
            additionalProperties: false,
          },
        },
        {
          name: 'create-pull-request-review',
          description: 'Create a review on a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
              commit_id: {
                type: 'string',
                description: 'The SHA of the commit that needs a review',
              },
              body: {
                type: 'string',
                description: 'The body text of the review',
              },
              event: {
                type: 'string',
                enum: ['APPROVE', 'REQUEST_CHANGES', 'COMMENT'],
                description: 'The review action to perform',
              },
              comments: {
                type: 'array',
                items: {
                  type: 'object',
                  properties: {
                    path: {
                      type: 'string',
                      description: 'The relative path to the file being commented on',
                    },
                    position: {
                      type: 'number',
                      description: 'The position in the diff where you want to add a review comment',
                    },
                    body: {
                      type: 'string',
                      description: 'Text of the review comment',
                    },
                  },
                  required: ['path', 'position', 'body'],
                  additionalProperties: false,
                },
                description: 'Comments to post as part of the review',
              },
            },
            required: ['owner', 'repo', 'pull_number', 'body', 'event'],
            additionalProperties: false,
          },
        },
        {
          name: 'merge-pull-request',
          description: 'Merge a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
              commit_title: {
                type: 'string',
                description: 'Title for the automatic commit message',
              },
              commit_message: {
                type: 'string',
                description: 'Extra detail to append to automatic commit message',
              },
              merge_method: {
                type: 'string',
                enum: ['merge', 'squash', 'rebase'],
                description: 'Merge method to use',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-pull-request-files',
          description: 'Get the list of files changed in a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-pull-request-status',
          description: 'Get the combined status of all status checks for a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'update-pull-request-branch',
          description: 'Update a pull request branch with the latest changes from the base branch',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
              expected_head_sha: {
                type: 'string',
                description: 'The expected SHA of the pull request\'s HEAD ref',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-pull-request-comments',
          description: 'Get the review comments on a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-pull-request-reviews',
          description: 'Get the reviews on a pull request',
          inputSchema: {
            type: 'object',
            properties: {
              owner: {
                type: 'string',
                description: 'Repository owner (username or organization)',
              },
              repo: {
                type: 'string',
                description: 'Repository name',
              },
              pull_number: {
                type: 'number',
                description: 'Pull request number',
              },
            },
            required: ['owner', 'repo', 'pull_number'],
            additionalProperties: false,
          },
        },
        // Search tools
        {
          name: 'search-code',
          description: 'Search for code across GitHub repositories',
          inputSchema: {
            type: 'object',
            properties: {
              q: {
                type: 'string',
              },
              order: {
                type: 'string',
                enum: ['asc', 'desc'],
              },
              page: {
                type: 'number',
                minimum: 1,
              },
              per_page: {
                type: 'number',
                minimum: 1,
                maximum: 100,
              },
            },
            required: ['q'],
            additionalProperties: false,
          },
        },
        {
          name: 'search-issues',
          description: 'Search for issues and pull requests across GitHub repositories',
          inputSchema: {
            type: 'object',
            properties: {
              q: {
                type: 'string',
              },
              order: {
                type: 'string',
                enum: ['asc', 'desc'],
              },
              page: {
                type: 'number',
                minimum: 1,
              },
              per_page: {
                type: 'number',
                minimum: 1,
                maximum: 100,
              },
              sort: {
                type: 'string',
                enum: [
                  'comments',
                  'reactions',
                  'reactions-+1',
                  'reactions--1',
                  'reactions-smile',
                  'reactions-thinking_face',
                  'reactions-heart',
                  'reactions-tada',
                  'interactions',
                  'created',
                  'updated',
                ],
              },
            },
            required: ['q'],
            additionalProperties: false,
          },
        },
        {
          name: 'search-users',
          description: 'Search for users on GitHub',
          inputSchema: {
            type: 'object',
            properties: {
              q: {
                type: 'string',
              },
              order: {
                type: 'string',
                enum: ['asc', 'desc'],
              },
              page: {
                type: 'number',
                minimum: 1,
              },
              per_page: {
                type: 'number',
                minimum: 1,
                maximum: 100,
              },
              sort: {
                type: 'string',
                enum: ['followers', 'repositories', 'joined'],
              },
            },
            required: ['q'],
            additionalProperties: false,
          },
        },
        {
          name: 'get-license-info',
          description: 'Get information about commonly used licenses on GitHub',
          inputSchema: {
            type: 'object',
            properties: {},
            additionalProperties: false,
          },
        },
        {
          name: 'get-enterprise-stats',
          description: 'Get GitHub Enterprise statistics (only available for GitHub Enterprise)',
          inputSchema: {
            type: 'object',
            properties: {},
            additionalProperties: false,
          },
        },
      ],
    }));

    // Handle tool calls
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;
      let parsedArgs;

      try {
        // Parse arguments if they are provided as a string
        if (typeof args === 'string') {
          parsedArgs = safeJsonParse(args);
        } else {
          parsedArgs = args;
        }

        // Call the appropriate tool
        let result;
        switch (name) {
          // Repository tools
          case 'search-repositories':
            result = await searchRepositories(parsedArgs);
            break;
          case 'create-repository':
            result = await createRepository(parsedArgs);
            break;
          case 'update-repository':
            result = await updateRepository(parsedArgs);
            break;
          case 'delete-repository':
            result = await deleteRepository(parsedArgs);
            break;
          case 'create-branch':
            result = await createBranch(parsedArgs);
            break;
          case 'list-commits':
            result = await listCommits(parsedArgs);
            break;
          case 'list-workflows':
            result = await listWorkflows(parsedArgs);
            break;
          case 'list-workflow-runs':
            result = await listWorkflowRuns(parsedArgs);
            break;
          case 'trigger-workflow':
            result = await triggerWorkflow(parsedArgs);
            break;

          // File operations tools
          case 'create-or-update-file':
            result = await createOrUpdateFile(parsedArgs);
            break;
          case 'push-files':
            result = await pushFiles(parsedArgs);
            break;
          case 'get-file-contents':
            result = await getFileContents(parsedArgs);
            break;
          case 'fork-repository':
            result = await forkRepository(parsedArgs);
            break;
          case 'get-pull-request-files':
            result = await getPullRequestFiles(parsedArgs);
            break;

          // Issue tools
          case 'list-issues':
            result = await listIssues(parsedArgs);
            break;
          case 'get-issue':
            result = await getIssue(parsedArgs);
            break;
          case 'create-issue':
            result = await createIssue(parsedArgs);
            break;
          case 'update-issue':
            result = await updateIssue(parsedArgs);
            break;
          case 'add-issue-comment':
            result = await addIssueComment(parsedArgs);
            break;

          // Pull request tools
          case 'list-pull-requests':
            result = await listPullRequests(parsedArgs);
            break;
          case 'get-pull-request':
            result = await getPullRequest(parsedArgs);
            break;
          case 'create-pull-request':
            result = await createPullRequest(parsedArgs);
            break;
          case 'create-pull-request-review':
            result = await createPullRequestReview(parsedArgs);
            break;
          case 'merge-pull-request':
            result = await mergePullRequest(parsedArgs);
            break;
          case 'get-pull-request-status':
            result = await getPullRequestStatus(parsedArgs);
            break;
          case 'update-pull-request-branch':
            result = await updatePullRequestBranch(parsedArgs);
            break;
          case 'get-pull-request-comments':
            result = await getPullRequestComments(parsedArgs);
            break;
          case 'get-pull-request-reviews':
            result = await getPullRequestReviews(parsedArgs);
            break;

          // Search tools
          case 'search-code':
            result = await searchCode(parsedArgs);
            break;
          case 'search-issues':
            result = await searchIssues(parsedArgs);
            break;
          case 'search-users':
            result = await searchUsers(parsedArgs);
            break;
          case 'get-license-info':
            result = await getLicenseInfo();
            break;
          case 'get-enterprise-stats':
            result = await getEnterpriseStats();
            break;

          default:
            throw new McpError(
              ErrorCode.MethodNotFound,
              `Unknown tool: ${name}`
            );
        }

        return {
          content: [
            {
              type: 'text',
              text: JSON.stringify(result, null, 2),
            },
          ],
        };
      } catch (error: any) {
        // Handle errors
        if (error instanceof McpError) {
          throw error;
        }

        // Convert other errors to MCP errors
        throw new McpError(
          ErrorCode.InternalError,
          `Error executing tool ${name}: ${error.message}`
        );
      }
    });
  }

  /**
   * Start the MCP server
   */
  async run(): Promise<void> {
    try {
      const transport = new StdioServerTransport();
      await this.server.connect(transport);
      console.error('GitHub Enterprise MCP server running on stdio');

      // Handle process termination
      process.on('SIGINT', async () => {
        await this.server.close();
        process.exit(0);
      });
    } catch (error: any) {
      console.error('Failed to start GitHub Enterprise MCP server:', error);
      process.exit(1);
    }
  }
}

```