Metadata-Version: 2.4
Name: codereviewbuddy
Version: 0.10.0
Summary: codereview buddy helps your AI agent interact with AI code review--smoothly!
Keywords: mcp,model-context-protocol,code-review,ai,github,pr,unblocked,devin,coderabbit
Author: Ismar Iljazovic
Author-email: Ismar Iljazovic <ismart@gmail.com>
License-Expression: ISC
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Documentation
Classifier: Topic :: Software Development
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Dist: fastmcp>=3.0.0b2
Requires-Dist: httpx>=0.28.1
Requires-Dist: packaging>=26.0
Requires-Python: >=3.14
Project-URL: Homepage, https://detailobsessed.github.io/codereviewbuddy
Project-URL: Documentation, https://detailobsessed.github.io/codereviewbuddy
Project-URL: Changelog, https://detailobsessed.github.io/codereviewbuddy/changelog
Project-URL: Repository, https://github.com/detailobsessed/codereviewbuddy
Project-URL: Issues, https://github.com/detailobsessed/codereviewbuddy/issues
Project-URL: Discussions, https://github.com/detailobsessed/codereviewbuddy/discussions
Project-URL: Funding, https://github.com/sponsors/ichoosetoaccept
Description-Content-Type: text/markdown

<!-- mcp-name: io.github.detailobsessed/codereviewbuddy -->
# codereviewbuddy

[![ci](https://github.com/detailobsessed/codereviewbuddy/workflows/ci/badge.svg)](https://github.com/detailobsessed/codereviewbuddy/actions?query=workflow%3Aci)
[![release](https://img.shields.io/github/v/release/detailobsessed/codereviewbuddy)](https://github.com/detailobsessed/codereviewbuddy/releases)
[![documentation](https://img.shields.io/badge/docs-mkdocs-blue.svg)](https://detailobsessed.github.io/codereviewbuddy/)
[![Python 3.14+](https://img.shields.io/badge/python-3.14+-blue.svg)](https://www.python.org/downloads/)
[![FastMCP v3 beta](https://img.shields.io/badge/FastMCP-v3.0.0b2-orange.svg)](https://github.com/jlowin/fastmcp)

An MCP server that helps your AI coding agent interact with AI code reviewers — smoothly.

Manages review comments from **Unblocked**, **Devin**, and **CodeRabbit** on GitHub PRs with staleness detection, batch resolution, re-review triggering, and issue tracking.

> [!WARNING]
> **Bleeding edge.** This server runs on **Python 3.14** and **FastMCP v3 beta** (`>=3.0.0b2`). FastMCP v3 is pre-release software — APIs may change before stable. We track the beta closely and pin to specific beta versions in `uv.lock` for reproducibility, but be aware that upstream breaking changes are possible.

## Features

### Review comment management

- **List review comments** — inline threads, PR-level reviews, and bot comments (codecov, netlify, vercel, etc.) with reviewer identification and staleness detection
- **Stacked PR support** — `list_stack_review_comments` fetches comments across an entire PR stack in one call
- **Resolve comments** — individually or bulk-resolve stale ones (files changed since the review)
- **Smart skip logic** — `resolve_stale_comments` skips reviewers that auto-resolve their own comments (Devin, CodeRabbit), only batch-resolving threads from reviewers that don't (Unblocked)
- **Reply to anything** — inline review threads (`PRRT_`), PR-level reviews (`PRR_`), and bot issue comments (`IC_`) all routed to the correct GitHub API
- **Request re-reviews** — per-reviewer logic handles differences automatically (manual trigger for Unblocked, auto for Devin/CodeRabbit)

### Issue tracking

- **Create issues from review comments** — turn useful AI suggestions into GitHub issues with labels, PR backlinks, file/line location, and quoted comment text

### Server features (FastMCP v3)

- **Typed output schemas** — all tools return Pydantic models with JSON Schema, giving MCP clients structured data instead of raw strings
- **Progress reporting** — long-running operations report progress via FastMCP context (visible in MCP clients that support it)
- **Production middleware** — ErrorHandling (transforms exceptions to clean MCP errors with tracebacks), Timing (logs execution duration for every tool call), and Logging (request/response payloads for debugging)
- **Update checker** — `check_for_updates` compares the running version against PyPI and suggests upgrade commands
- **Zero config auth** — uses `gh` CLI, no PAT tokens or `.env` files

### CLI testing (free with FastMCP v3)

FastMCP v3 gives you terminal testing of the server with no extra code:

```bash
# List all tools with their signatures
fastmcp list codereviewbuddy.server:mcp

# Call a tool directly from the terminal
fastmcp call codereviewbuddy.server:mcp list_review_comments pr_number=42

# Inspect server metadata
fastmcp inspect codereviewbuddy.server:mcp

# Run with MCP Inspector for interactive debugging
fastmcp dev codereviewbuddy.server:mcp
```

## Prerequisites

- [GitHub CLI (`gh`)](https://cli.github.com/) installed and authenticated (`gh auth login`)
- Python 3.14+

## Installation

This project uses [`uv`](https://docs.astral.sh/uv/). No install needed — run directly:

```bash
uvx codereviewbuddy
```

Or install permanently:

```bash
uv tool install codereviewbuddy
```

## MCP Client Configuration

### Windsurf

Add to your MCP settings (`~/.codeium/windsurf/mcp_config.json`):

```json
{
  "mcpServers": {
    "codereviewbuddy": {
      "command": "uvx",
      "args": ["--prerelease=allow", "codereviewbuddy@latest"]
    }
  }
}
```

> **Why `--prerelease=allow`?** codereviewbuddy depends on FastMCP v3 beta (`>=3.0.0b2`). Without this flag, `uvx` refuses to resolve pre-release dependencies.
>
> **Why `@latest`?** Without it, `uvx` caches the first resolved version and never upgrades automatically.

### Claude Desktop

Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "codereviewbuddy": {
      "command": "uvx",
      "args": ["--prerelease=allow", "codereviewbuddy@latest"]
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json` in your project:

```json
{
  "mcpServers": {
    "codereviewbuddy": {
      "command": "uvx",
      "args": ["--prerelease=allow", "codereviewbuddy@latest"]
    }
  }
}
```

### From source (development)

```json
{
  "mcpServers": {
    "codereviewbuddy": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/codereviewbuddy", "codereviewbuddy"]
    }
  }
}
```

## MCP Tools

| Tool | Description |
| ---- | ----------- |
| `list_review_comments` | Fetch all review threads, PR-level reviews, and bot comments with reviewer ID, status, and staleness |
| `list_stack_review_comments` | Fetch comments for multiple PRs in a stack in one call, grouped by PR number |
| `resolve_comment` | Resolve a single inline thread by GraphQL node ID (`PRRT_...`) |
| `resolve_stale_comments` | Bulk-resolve threads on files modified since the review, with smart skip for auto-resolving reviewers |
| `reply_to_comment` | Reply to inline threads (`PRRT_`), PR-level reviews (`PRR_`), or bot comments (`IC_`) |
| `request_rereview` | Trigger re-reviews per reviewer (handles differences automatically) |
| `create_issue_from_comment` | Create a GitHub issue from a review comment with labels, PR backlink, and quoted text |
| `check_for_updates` | Check if a newer version is available on PyPI |

## Configuration

codereviewbuddy works **zero-config** with sensible defaults. To customize per-reviewer behavior, create a `.codereviewbuddy.toml` in your project root:

```bash
codereviewbuddy init   # generates a self-documenting config file
```

Or create it manually:

```toml
# .codereviewbuddy.toml

[reviewers.devin]
enabled = true                    # Set to false to ignore Devin comments entirely
auto_resolve_stale = false        # Devin auto-resolves its own threads; we skip them
resolve_levels = ["info"]         # Only allow resolving info-level threads

[reviewers.unblocked]
enabled = true
auto_resolve_stale = true         # We batch-resolve Unblocked's stale threads
resolve_levels = ["info", "warning", "flagged", "bug"]

[reviewers.coderabbit]
enabled = true
auto_resolve_stale = false        # CodeRabbit handles its own resolution
resolve_levels = []               # Don't resolve any CodeRabbit threads
```

### Config options

| Option | Type | Default | Description |
| ------ | ---- | ------- | ----------- |
| `enabled` | bool | `true` | Whether to include this reviewer's threads in results |
| `auto_resolve_stale` | bool | varies | Whether `resolve_stale_comments` touches this reviewer's threads |
| `resolve_levels` | list | varies | Severity levels that are allowed to be resolved |

### Severity levels

Each reviewer adapter classifies comments using its own format. Currently only Devin has a known severity format (emoji markers). Unblocked and CodeRabbit comments default to `info` until their formats are investigated.

**Devin's emoji markers:**

| Emoji | Level | Meaning |
| ----- | ----- | ------- |
| 🔴 | `bug` | Critical issue, must fix before merge |
| 🚩 | `flagged` | Likely needs a code change |
| 🟡 | `warning` | Worth addressing but not blocking |
| 📝 | `info` | Informational, no action required |
| *(none)* | `info` | Default when no marker is present |

Reviewers without a known format classify all comments as `info`. This means `resolve_levels = ["info"]` would allow resolving all their threads, while `resolve_levels = []` blocks everything.

### Resolve enforcement

The `resolve_levels` config is **enforced server-side**. If an agent tries to resolve a thread whose severity exceeds the allowed levels, the server returns an error. This prevents agents from resolving critical review comments regardless of their instructions.

For example, with the default config, resolving a 🔴 bug from Devin is blocked — only 📝 info threads can be resolved.

### Config discovery

The server walks up from the current working directory looking for `.codereviewbuddy.toml`, stopping at the `.git` root. If no config file is found, all defaults apply. The loaded config path is logged at startup.

## Reviewer behavior

| Reviewer | Auto-reviews on push | Auto-resolves comments | Re-review trigger |
| -------- | ------------------- | -------------------- | ----------------- |
| **Unblocked** | No | No | `request_rereview` posts "@unblocked please re-review" |
| **Devin** | Yes | Yes | Auto on push (no action needed) |
| **CodeRabbit** | Yes | Yes | Auto on push (no action needed) |

## Typical workflow

```
1. Push a fix
2. list_review_comments(pr_number=42)           # See all threads with staleness
3. resolve_stale_comments(pr_number=42)          # Batch-resolve changed files
4. reply_to_comment(42, thread_id, "Fixed in ...")  # Reply to remaining threads
5. request_rereview(pr_number=42)                # Trigger fresh review cycle
```

For stacked PRs, use `list_stack_review_comments` with all PR numbers to get a full picture before deciding what to fix.

## Development

```bash
git clone https://github.com/detailobsessed/codereviewbuddy.git
cd codereviewbuddy
uv sync
```

### Testing

```bash
poe test          # Run tests (excludes slow)
poe test-cov      # Run with coverage report
poe test-all      # Run all tests including slow
```

### Quality checks

```bash
poe lint          # ruff check
poe typecheck     # ty check
poe check         # lint + typecheck
poe prek          # run all pre-commit hooks
```

### Architecture

The server is built on [FastMCP v3](https://github.com/jlowin/fastmcp) with a clean separation:

- **`server.py`** — FastMCP server with tool registration, middleware, and instructions
- **`config.py`** — Per-reviewer configuration (`.codereviewbuddy.toml` loader, severity classifier, resolve policy)
- **`tools/`** — Tool implementations (`comments.py`, `issues.py`, `rereview.py`, `version.py`)
- **`reviewers/`** — Pluggable reviewer adapters with behavior flags (auto-resolve, re-review triggers)
- **`gh.py`** — Thin wrapper around the `gh` CLI for GraphQL and REST calls
- **`models.py`** — Pydantic models for typed tool outputs

All blocking `gh` CLI calls are wrapped with `call_sync_fn_in_threadpool` to avoid blocking the async event loop.

## Template Updates

This project was generated with [copier-uv-bleeding](https://github.com/detailobsessed/copier-uv-bleeding). To pull the latest template changes:

```bash
copier update --trust .
```
