Skip to main content
Glama
darenkeck-dev

PR Viewer MCP Server

README.md
# Dev MCP Server

MCP server for local development workflows. Tools for branching and diff review,
designed to be called by AI coding assistants.

## Setup

```bash
uv sync --group dev
```

## Tools

| Tool | Description |
|---|---|
| `health_check` | Confirms the server is reachable. |
| `open_branch` | Checks the working tree is clean, then creates a new branch. |
| `open_review` | Launches a diff visualizer and blocks until the user accepts or rejects. |

### `open_branch`

| Parameter | Default | Description |
|---|---|---|
| `repo_path` | — | Absolute path to a git repo. |
| `branch_name` | — | Name for the new branch. |
| `base_ref` | `main` | Ref to branch from. |

Returns `"Created branch '<name>' from <base_ref>"` on success, or an error
string describing why it failed (dirty tree, branch already exists, bad ref).

### `open_review`

| Parameter | Default | Description |
|---|---|---|
| `repo_path` | — | Absolute path to a git repo. |
| `base_ref` | `main` | The base git ref (e.g. `main`, `origin/main`). |
| `head_ref` | `HEAD` | The head ref to diff against base (branch name, commit SHA, etc.). |

Blocks until the user finishes reviewing. Returns `"accepted"` or `"rejected"`.

## Wiring in a visualizer

Create a shell script that receives the repo context via env vars, launches the
visualizer, captures the user's decision, and signals the result back to the
server via the provided IPC path:

```bash
#!/usr/bin/env bash
# Env vars provided by the server:
#   REPO_PATH   – absolute path to the git repo
#   BASE_REF    – base ref (e.g. main)
#   HEAD_REF    – head ref (e.g. feature/add-greet)
#   RESULT_PATH – IPC path the script writes "accepted" or "rejected" to

# launch your visualizer, capture the decision, then signal the result:
echo "accepted" > "$RESULT_PATH"
```

The default visualizer (`scripts/launch-octorus.sh`) opens octorus in a new
terminal window and prompts accept/reject after the user quits.

## Connecting to AI coding assistants

### Claude Code

Add to `~/.claude/mcp.json` (global) or `.mcp.json` at a project root:

```json
{
  "mcpServers": {
    "devflow": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/pr-viewer", "devflow-mcp"]
    }
  }
}
```

### OpenCode

```bash
opencode mcp add pr-viewer
```

Follow the prompts: choose **stdio**, set command to `uv`, args to
`run --directory /path/to/pr-viewer devflow-mcp`. This writes to
`~/.config/opencode/opencode.jsonc`.

### Codex

```bash
codex mcp add pr-viewer -- uv run --directory /path/to/pr-viewer devflow-mcp
```

This writes to `~/.codex/config.toml`.

### Example prompts

```
Create a branch called feature/add-login in /path/to/repo from main.
```

```
Open a review of feature/add-greet in /path/to/repo against main.
If it's accepted, merge it with `gh pr merge --merge`.
If it's rejected, post a comment explaining what needs to change.
```

## Manual end-to-end test with a toy repo

### 1. Create the toy repo

```bash
./scripts/setup-toy-repo.sh
```

Creates `./toy-repo/` with a `main` branch and a `feature/add-greet` branch.
To remove it when done:

```bash
./scripts/teardown-toy-repo.sh
```

### 2. Start the MCP inspector

```bash
uv run mcp dev src/devflow_mcp/server.py
```

Open the inspector URL printed in the terminal (default: `http://localhost:5173`).

### 3. Test open_branch

In the MCP inspector, select **open_branch** and fill in:

```json
{
  "repo_path": "<absolute-path-to-project>/toy-repo",
  "branch_name": "test-branch"
}
```

### 4. Test open_review

Select **open_review** and fill in:

```json
{
  "repo_path": "<absolute-path-to-project>/toy-repo",
  "base_ref": "main",
  "head_ref": "feature/add-greet"
}
```

The tool blocks — the inspector shows a spinner until the review is complete.
A terminal window opens automatically; answer the accept/reject prompt when you
quit octorus.

## Programmatic use

```python
import asyncio
from mcp.client.stdio import stdio_client, StdioServerParameters
from mcp.client.session import ClientSession

async def main() -> None:
    server = StdioServerParameters(
        command="uv",
        args=["run", "--directory", "/path/to/pr-viewer", "devflow-mcp"],
    )
    async with stdio_client(server) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            await session.call_tool("open_branch", {
                "repo_path": "/path/to/repo",
                "branch_name": "feature/my-feature",
            })
            result = await session.call_tool("open_review", {
                "repo_path": "/path/to/repo",
                "base_ref": "main",
                "head_ref": "feature/my-feature",
            })
            print(result.content[0].text)  # "accepted" or "rejected"

asyncio.run(main())
```

## Tests

```bash
uv run pytest
```

TDQS

A3.6/5.0

Scored across 2 tools

Disambiguation5/5

The two tools have completely distinct purposes: one checks server health, the other initiates a review workflow. There is no overlap or ambiguity.

Naming Consistency4/5

Both names use snake_case, but 'health_check' is a noun phrase while 'open_review' is a verb phrase, creating a minor inconsistency in grammatical pattern.

Tool Count2/5

Only two tools for a 'PR Viewer' server is very thin. The scope appears limited, and typical MCP servers offer more operations for meaningful interaction.

Completeness1/5

The server lacks essential tools for a PR viewer, such as listing PRs, viewing details, or commenting. Only a health check and a single review tool are provided, leaving major gaps.

Maintenance

ActivityInactive
ResponsivenessNo issues