Content
# GitHub PR Review MCP Server
> An MCP server that gives any LLM client the ability to list, read, review, and comment on GitHub pull requests — turning your AI assistant into a fully capable code reviewer.
---
## Overview
This server wraps the GitHub REST API using [FastMCP](https://gofastmcp.com), exposing pull request operations as tools any MCP-compatible client can call. Connect it to Claude Desktop and you can ask Claude to review your open PRs, read diffs, post inline comments, approve, or request changes — all without leaving your conversation.
The server maintains a single authenticated `httpx` client across its lifetime, initialised on startup and shared across all tool calls via FastMCP's lifespan context.
---
## Tools
| Tool | Description |
|---|---|
| `list_open_prs` | List all open PRs with author, title, draft status, and URL |
| `get_pr_diff` | Get file changes and unified diffs for a specific PR |
| `get_pr_comments` | Get all existing review comments on a PR |
| `post_review_comment` | Post an inline comment on a specific file and line |
| `approve_pr` | Approve a PR with an optional review message |
| `request_changes` | Request changes on a PR with a review message |
> **Note:** `approve_pr` and `request_changes` require the authenticated user to be different from the PR author. GitHub does not permit self-review.
---
## Project Structure
```
github-pr-mcp/
├── server.py # FastMCP instance, lifespan, tool registration
├── config.py # Environment variables and constants
├── tools/
│ ├── __init__.py
│ ├── prs.py # list_open_prs, get_pr_diff
│ └── reviews.py # get_pr_comments, post_review_comment, approve_pr, request_changes
├── .env # Your secrets (never committed)
├── .env.example # Template
├── requirements.txt
├── Dockerfile
└── README.md
```
---
## Requirements
- Python 3.11+
- [uv](https://docs.astral.sh/uv/getting-started/installation/)
- A GitHub Personal Access Token with `repo` scope
---
## Setup
**1. Clone the repository:**
```bash
git clone https://github.com/Festuskipkoech/github-pr-mcp.git
cd github-pr-mcp
```
**2. Install dependencies:**
```bash
uv sync
```
**3. Configure your environment:**
```bash
cp .env.example .env
```
Edit `.env` and fill in your values:
```
GITHUB_TOKEN=your_personal_access_token
GITHUB_OWNER=your_github_username
GITHUB_REPO=your_repository_name
```
Generate a token at **GitHub Settings → Developer Settings → Personal Access Tokens**. Enable full `repo` scope for read and write access.
---
## Running Locally
```bash
uv run python server.py
```
Or with the FastMCP CLI on Streamable HTTP transport:
```bash
fastmcp run server.py:mcp --transport streamable-http
```
---
## Testing with MCP Inspector
Start the server in one terminal:
```bash
fastmcp run server.py:mcp --transport streamable-http
```
Launch the Inspector in a second terminal:
```bash
npx -y @modelcontextprotocol/inspector
```
In the Inspector UI:
- **Transport:** Streamable HTTP
- **URL:** `http://127.0.0.1:8000/mcp`
- Click **Connect**
**Recommended test sequence:**
| Step | Tool | Input |
|---|---|---|
| 1 | `list_open_prs` | _(no arguments)_ |
| 2 | `get_pr_diff` | `{"pr_number": 1}` |
| 3 | `get_pr_comments` | `{"pr_number": 1}` |
| 4 | `post_review_comment` | `{"pr_number": 1, "body": "Looks good", "path": "file.py", "line": 1}` |
---
## Using with Claude Desktop
Add the following to `~/.config/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"github-pr-review": {
"command": "/home/your-user/.local/bin/uv",
"args": [
"run",
"--directory",
"/absolute/path/to/github-pr-mcp",
"python",
"server.py"
]
}
}
}
```
Use the full path to `uv` (find it with `which uv`). Credentials are read from the `.env` file automatically — no need to pass them in the config.
Restart Claude Desktop, then try:
```
List all open pull requests in my repo and show me the diff for PR number 1
```
Claude calls `list_open_prs` and `get_pr_diff` and returns structured results:

Full PR diff and file changes returned inline:

---
## Running with Docker
```bash
docker build -t github-pr-mcp .
docker run --env-file .env -p 8000:8000 github-pr-mcp
```
For Streamable HTTP transport, update `server.py` to run with:
```python
mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
```
---
## Troubleshooting
| Error | Cause | Fix |
|---|---|---|
| `401 Unauthorized` | Invalid or expired token | Regenerate PAT on GitHub |
| `403 Forbidden` | Token lacks write scope | Enable full `repo` scope on your PAT |
| `404 Not Found` | Wrong owner or repo name | Check `.env` — use just the repo name, not the full URL |
| `422 Unprocessable` on approve | Self-review attempt | GitHub blocks approving your own PRs by design |