Skip to main content
Glama
maycwu

GitHub MCP Server

by maycwu
README.md
# GitHub MCP Server

A Model Context Protocol (MCP) server that connects Claude to your GitHub repositories. Query repos, review PRs, manage issues, search code, and automate GitHub workflows—all from Claude.

## Features

### Included Tools

- **list_repos** — List your repositories with metadata (stars, language, etc.)
- **read_file** — Read files from any repo (source code, docs, configs)
- **list_prs** — Fetch pull requests with filtering (open/closed/all)
- **get_pr** — Get PR details including full diff for code review
- **list_issues** — Search and filter issues by state, labels, etc.
- **create_issue** — File new issues programmatically
- **add_pr_comment** — Add review comments to pull requests
- **search_code** — Search code across repos using GitHub search syntax
- **get_repo_info** — Fetch repo metadata (description, stars, topics, etc.)

## Quick Start

### 1. Set Up Authentication

Create a GitHub Personal Access Token:
1. Go to [github.com/settings/personal-access-tokens](https://github.com/settings/personal-access-tokens)
2. Click **Generate new token** → **Generate new token (fine-grained)**
3. Name it `claude-mcp`
4. Under **Repository access**, select **All repositories** or specific repos
5. Under **Permissions**, grant:
   - **Contents**: Read-only
   - **Issues**: Read & write (if you want to create issues)
   - **Pull requests**: Read & write (if you want to comment on PRs)
6. Click **Generate token** and copy it

### 2. Install Dependencies

```bash
cd /Users/maywu/Projects/github-mcp-server
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
```

### 3. Set Your GitHub Token

```bash
cp .env.example .env
# Edit .env and paste your token:
# GITHUB_TOKEN=ghp_xxxxx
```

Or set it directly:
```bash
export GITHUB_TOKEN="your_github_pat_here"
```

### 4. Connect to Claude Code

```bash
# From the project root:
claude mcp add --env GITHUB_TOKEN="your_github_pat_here" \
  --transport stdio github \
  -- python server.py
```

Verify it connected:
```bash
claude mcp list
```

You should see: `✓ github — 9 tools`

## Usage

Once connected, you can ask Claude to:

```
List my repositories
```

```
Review PR #456 and suggest improvements for anthropic/claude-code
```

```
Create an issue for the bug we just found in my-repo
```

```
Find all instances of TODO comments in my codebase
```

```
Read the CONTRIBUTING.md from owner/repo
```

```
List all open issues labeled 'bug' and 'critical' in my-org/my-repo
```

## Local Development & Testing

### Run the server directly (for debugging)

```bash
export GITHUB_TOKEN="your_token"
python server.py
```

You should see:
```
INFO:mcp.server:Started MCP server
```

If there are errors, you'll see them here.

### Test a tool manually

Once connected to Claude Code, run:
```bash
claude
```

Then in the session:
```
Use the github server to list my repos and show me the 5 most recently updated ones
```

Claude will call the `list_repos` tool and display results.

### Common Issues

**"Error: GITHUB_TOKEN environment variable not set"**
- Make sure your token is exported: `echo $GITHUB_TOKEN`
- If using Claude, pass it with `--env`: `claude mcp add --env GITHUB_TOKEN="token" ...`

**"Error: Unauthorized (401)"**
- Your token may have expired or insufficient permissions
- Generate a new token at github.com/settings/personal-access-tokens
- Check that the token has Contents and Issues scopes enabled

**"Timeout connecting to server"**
- The server may be crashing on startup. Run it directly to see errors: `python server.py`
- Try increasing the timeout: `MCP_TIMEOUT=60000 claude`

## Architecture

### Server Structure

```
server.py
├── list_tools()          — Define all available tools
├── call_tool()           — Route tool calls to handlers
└── _<tool_name>()        — Handler for each tool (async)
```

### Adding New Tools

To add a new GitHub operation:

1. Add the tool definition in `list_tools()`:
```python
Tool(
    name="my_new_tool",
    description="What this tool does",
    inputSchema={
        "type": "object",
        "properties": {...},
        "required": [...]
    }
)
```

2. Add a handler function:
```python
async def _my_new_tool(arguments: dict) -> list[ToolResult]:
    # Your implementation here
    return [ToolResult(content=[TextContent(text="result")])]
```

3. Add a route in `call_tool()`:
```python
elif name == "my_new_tool":
    return await _my_new_tool(arguments)
```

## GitHub API Limits

- **Authenticated requests**: 5,000/hour
- **Unauthenticated**: 60/hour

This server always uses your token, so you get the 5,000/hour limit.

## Security

- Never commit your `.env` file or tokens to version control
- Use fine-grained personal access tokens (not classic tokens)
- Scope tokens to minimal required permissions
- Rotate tokens regularly
- If a token is leaked, revoke it immediately at github.com/settings/personal-access-tokens

## Troubleshooting

### Check server status

```bash
claude mcp list
```

Should show:
```
github (stdio)
  ✓ Connected
  9 tools available
```

### View server logs

If running in Claude Code, check the MCP logs:
```bash
claude mcp logs github
```

### Test the API directly

```bash
curl -H "Authorization: Bearer $GITHUB_TOKEN" \
  https://api.github.com/user/repos
```

## Next Steps

- **Share with teammates**: Commit `.env.example` and `server.py` to a project repo, have teammates set their own `GITHUB_TOKEN`
- **Deploy as a service**: Run on a server and use `--transport http` instead of `stdio`
- **Add more tools**: Extend with webhooks, actions, releases, discussions, etc.
- **Integrate with workflows**: Build Claude-assisted code review, release notes generation, or issue triage

## Resources

- [MCP Documentation](https://modelcontextprotocol.io)
- [GitHub API Docs](https://docs.github.com/en/rest)
- [Claude Code MCP Setup](https://code.claude.com/docs)