Skip to main content
Glama
JigeeshaJain

gh-review-queue-mcp

gh-review-queue-mcp

M8ven Score

次に何をレビューすべきか。この問いに答えるための MCP サーバーです。

このサーバーが公開するツールは、ちょうど1つだけ、get_review_queue です。これは、あなたの GitHub プルリクエストのレビューキューを、ランキング済み・重複除去済みのビューとして返します。あなたに直接依頼されたレビュー、あなたのチームに依頼されたレビュー、そして誰かの対応を待っているあなた自身のプルリクエストです。

ツールを1つだけにするのは、意図的な制約です。list_prssearch_prsget_pr_status のどれを使うか選ばなければならないアシスタントは、最初のターンを「選ぶこと」に費やします。しかし、すでに優先順位付けされたリストを返す1つのツールを持つアシスタントは、ただ答を返すだけです。


実際の動作

ツールが呼び出されると、次の4つのことが順番に起こります。

1. あなたとあなたのチームを特定する

サーバーは GraphQL クエリで viewer { login } に加えて、あなたが属するチーム(organizations.teams(role: MEMBER))を取得します。チームの slug が重要なのは、GitHub の検索 API には「自分のチームのどれかに依頼された」という検索句がないため、各チームを明示的に指定する必要がからです。read:org スコープがトークンに必要となる理由は、これだけです。

2. 複数検索を1つのバッチにまとめる

GitHub には「対応が必要なすべて」を一度に検索するクエリはありません。そこでサーバーは複数の検索を実行し、結果を結合します。これらの検索はエイアスを使って 1つの GraphQL ドキュメント にまとめて送られるため、属しているチームの数に関係なくHTTP の往復は1回だけです。

エイアス

検索

変換後の理由

requested_of_me

is:pr is:open archived:false review-requested:@me

requested_of_me

my_pr_awaiting_review

is:pr is:open archived:false author:@me

my_pr_awaiting_review

team_0, team_1, …

is:pr is:open archived:false team-review-requested:<org>/<team>

requested_of_my_teams

検索文字列は GraphQL の 変数 として渡され、クエリ本文に文字列補間されることはありません。そのため、チームの slug がクエリの形を変えることはできません。

同じクエリは rateLimit { remaining resetAt } も要求します。これにより、2回目の呼び出しなしで毎回のレスポンスに残り利用可能枠を報告できます。

レスポンスの形について2点注意があります。GitHub の search(type: ISSUE) はプルリクエストだけでなくイシューも返しますが、選択セットが PullRequest 上の中間フラグメントであるため、イシューは空のノードとして返ってきて、パースの際に捨てられます。また、statusCheckRollupcommits(last: 1) から取得されます。つまり、ブランチ全体の履歴ではなく、先頭コミットの CI 状況です。

3. 結合、重複除去、フィルタ、順位付け

同じプルリクエストは、複数の検索結果に出てくることがよくあります。あなたが直接レビューし、かつチームにも依頼されている PR は、2つのカテゴリに現れます。これらは GraphQL ノードID で重複排除され、理由は1つのエントリに蓄積されるため、レスポンスは同じ項目を2回列挙するのではなく「この項目は2つの理由にあたります」と示します。

その後、あなたのフィルタが適用され、残った項目がスコアリングされて順序付けされます。

4. シリアライズ

ランク付きのリストは構造化された出力として返されます。ツールは完全な JSON 出力スキーマを宣言するため、クライアントは解析が必要な文章ではなく、型付けのされたフィールドを受け取ります。


Related MCP server: github-ops-mcp

ランキングの仕組み

ランキングは、重みの自動調整ではなく階層制です。各プルリクエストはちょうど1つの階層に入り、その階層の基点数は、階層内で蓄積されるどの要素よりもはるかに大きい値です。

階層

条件

基点数

3

自分のPRでCIが失敗している

300

2

自分のPRで変更が要求されている

200

1

自分に直接依頼されたレビュー

100

0

チームへの依頼、またはただ待っているだけの自分のPR

0

階層性内では、2つの小さなシグナルが適用されます。

  • 年齢 — プルリクエストが開かれてからの日数に応じて1日あたり2点、上限は20点です。古いレビュー依頼も表に出てきますが、6ヶ月前のPRがずっと上位を占め続けることはありません。

  • 小さな差分 — 100行以下の差分には8点一律のボーナス。今終わる割ができる小さなレビューが、後で延ばす大きなレビューより勝つという考え方です。

上限こそがポイントです。階層内で蓄積される最大値は20 + 8 = 28で、階層の刻み幅100よりはるかに小さい。したがって、階層の優先位は構造上で保証されます。新しい直接依頼が過去のチーム依頼を常に優先し、将来の重み調整がこの保証を静かに覆すことはありません。スコアリングのシグナルを追加する際はは、階層内の合計を100未満に保ってください。でないとその保証は壊れます。

同点の場合は、もっとも最近の活動地(updatedAt)で決定されます。そのため、同じスコアの場合は停止しき会話より活発な会話が上回ります。

全項目には priority_reasons が含まれます。これは「私のPR、CI失敗」「3日日経過」のような読み取れる文字列が入ります。これにより、順位付けの根拠が説明のない目数ではなく、あなたに分かる形で説明される形で渡されます。


インストール

Python 3.1+ と uv が必要です。

git clone <this repo>
cd ReviewQueueMcp
uv sync

トークン

サーバーは GITHUB_TOKEN から GitHub 個人的なアクセストークンを読読み込みます:

cp .env.example .env      # then edit it
export GITHUB_TOKEN=ghp_...

必要なスコープ:

  • repo — プライベートのりポジトリ内のプルリクエストを読む取り

  • read:org — 所属チームを読み取るための、チームレビュー依頼の検索に使用する

クラシック な PAT がもっとも簡単です。新細グレーンなトークンめる場合、「Pull requests: read」と組織メンバーの読み取り許可があれば機能ます。https://github.com/settings/tokens で作成できます。

GITHUB_GRAPHQL_URL はオプションで、GitHub Enterprise Server のエンドポイントを上書きします。

トークンは起点で起動時ではなく、ツール呼び出しのたびに読み込まれます。そのため、トークンがなくてもサーバーは正常に起動し、呼び出された時に実行できるエラーを返します。MCP のハンドシェク中にサーバーが死んで、クライアントに壊れたパイプしか見え、という結果にはりません。


実行方法

uv run gh-review-queue-mcp

stdio を経由した MCP を話し、そあたのクライが必要です。直接実行するば、ただ待ち続けるだけです。

MCP Designer を使用する

npx @modelcontextprotocol/inspector uv --directory /absolute/path/to/ReviewQueueMcp run gh-review-queue-mcp

印字されたURLを開いて接切すると、生成された入力スキーマとともにツールがToolsに表示されます。

Claude Desktop を使用する

claude_desktop_config.json に追加します。macOS では ~/Library/Application Support/Claude/claude_desktop_config.json です。

{
  "mcpServers": {
    "gh-review-queue": {
      "command": "uv",
      "args": [
        "--directory",
        "/absolute/path/to/ReviewQueueMcp",
        "run",
        "gh-review-queue-mcp"
      ],
      "env": {
        "GITHUB_TOKEN": "ghp_..."
      }
    }
  }
}

パスは絶対パスで指定する必要があります。Claude Desktop はシェル経由でサーバーを起動しないため、作業デイレクトリの環境変数を受継ません。編集後、 Claude Desktop を再起動します。あとは「今日はどんなレビューをすればいい?」と聞いてると機能しません。

(原文"Then ask even"等" -> Need to reflect "対応able".

Let me finish the rest.

Hmm I see I wrote パス must be absolute - I should preserve "パスは絶対パスにする必要があります。 Claude Desktop はシェルから起動しないので、作業ディレクトリも環境変数もありません。編集後 Claude Desktop を再起動してください。その後「今日は何をレビューすればいい ?」と聞いてみてください。

The hmm I had "といった" mistake.

ツールリファーンス

get_review_queue

すべての引数はオプションです。

引数

デフォルト

意味

include

requested_of_me | requested_of_my_teams | my_pr_awaiting_review の配列

全3つ

含める理由の選択。項目は、その理由のいずれかが含まれていれば残ります。

exclude_drafts

ブーリアン

true

ドラフトを除外します。外しで、格下げでは除外されません。ドラフトはまだけレビュー可能な状態でない。

max_age_days

整数

なし

この日数より前に開かれたPRを除外します。境界の日数は含まれます。

repos

owner/name の配列

なし

指定したリポジトリに限定。完全一致です。

limit

整数1–20

25

返りる最大項目数。total_matching まだ全件数を報告します。

レスポンス:

It may be slightly mis-tying. OK.

{
  "viewer": "octocat",
  "generated_at": "2026-08-20T12:00:00Z",
  "returned": 5,
  "total_matching": 5,
  "rate_limit_remaining": 4712,
  "warnings": [],
  "items": [
    {
      "repository": "acme/payments-api",
      "number": 4830,
      "title": "Add idempotency keys",
      "url": "https://github.com/acme/payments-api/pull/4830",
      "author": "octocat",
      "reasons": ["my_pr_awaiting_review"],
      "priority_score": 306.0,
      "priority_reasons": ["my PR, CI failing", "3 days old"],
      "age_days": 3.0,
      "diff_size": 374,
      "changed_files": 12,
      "is_draft": false,
      "review_decision": "REVIEW_REQUIRED",
      "ci_status": "FAILURE"
    }
  ]
}

returedtotal_matching を分けることで、「実際に25件です」と「全部25件あります」との区別ができます。この区別がないと、先頭に25件限定した表示と全部表示の区別ができなくなります。

warnings は、GraphQL の部分的な壊を運びます。GitHub は、エラーと共存して利用可能なデータを返すことがあります。(1つの組織の読取の壊れ、1つの検索が失敗する)キュー全体を捨てる代わりに、これらのエラーは warnings に何の込み:

不要。: hmm.

Let me re-translate clean: "warnings carries GraphQL partial failures. GitHub can return usable data alongside errors (one org unreadables, one search failing); rather than throwing away the whole queue, those degrade to warnings and the rest of the results still come back."

I'll write:

warnings には、GraphQL の部分失敗が格納されます。GitHub はエラーを伴いながらも利用可能なデータを返すことがあります(ある組織が読み取れない、ある検索が失敗する)。キュー全体を破棄する代わりに、それらはワーニングに格下げされ、残りの結果はただちに返されます。

Yes.

アーキテクチュア

src/gh_review_queue/ 配下に4つのジュールがあり、セスージュール間の境界が構造を支えています。

server.py    MCP wiring. Parse arguments -> call client -> domain layer -> serialize.
   |         Deliberately thin; its docstring sets a ~120-line budget.
   v
github.py    The only module that touches the network. Builds GraphQL, handles HTTP
   |         and GraphQL errors, returns domain objects. Never ranks or filters.
   v
queue.py     Pure functions: merge -> apply_filters -> rank/score, via build_queue.
   |         Input is a snapshot and a clock. Nothing else.
   v
models.py    Frozen pydantic value objects. The only place GitHub's nested GraphQL
             shape is flattened. No network types.

ここでの成果は queue.py です。これは QueueSnapshotdatetime だけを受け取り、それ以外の依存を持たないため、すべてのランキングルールをプレーンなデータと モックなし、ネットワークなし、クロック改造なし でテストできます。これが分割の理由であり、httpx のインポートが queue.py に到達してはけない理由でもあります。

失敗ではなくデグレード

GitHub から返る未知の enum 値(新しい reviewDecision、新しい CI ロールアップ状態)は、例外を起こす代わりに None に変換されます。GitHub 側で追加された状態が、自分のキュー全体を壊すべきではありません。率いて: The same instinct runs through the parsing layer: missing authors become ghost (GitHub's own convention for deleted account), non-PR search results are dropped, and absent timestamps are the only genuinely unrecoverable case which raises.

I'll write: この同じ考えは、パース層にも貫かれています。不明の著者は ghost(削除済みアカウントに関する GitHub の標準)に変換され、PR 以外の検索結果はすてられ、そ存在しないタイムスタンプだけは、もと純では復元できなケースであり、この例外が発生します。

Hmm "absent timestamps raise" ~ "不存在のタイムスタンプは、単一的に復旧が不可なため、エラーを発生します。"

開発

uv run pytest                       # all tests
uv run pytest tests/test_queue.py   # one file
uv run pytest -k "rank or score"    # by name
uv run ruff check .                 # lint
uv run ruff format .                # format
uv run mypy                         # typecheck (strict)

mypy はは、対象を pyproject.toml[toole.mypy] files から取るため、パスを引数に渡してチェックすると、意図したよりも範囲が狭くなります。

(Mmm exact) Actually mypy bare: run it without argvs. I wrote enough.

テストの進め方

テストは tests/fixtures/queue_response.json を使います。このJSONは、本来GraphQL のレスポンスをキャプチャしたもので、面倒なケースをすべて含むように作られています:* 2つのバケット中に現れるPR、 1つの draft(下書)、 とても古いPR、 自分がアウトの CI 失敗 PR、 *ヌルの status rollup。

test_rank_orders_the_fixture_the_way_a_reviewer_would_read_it は、固定の時計に対して排他的な正確なスコアを検証します。これはスコアリング変更のカナリャです。失ルした場合は、数値を更新前に、新しい順序が本当に良くなっているのかを判断してください。

Wait the phrase: "fixed clock" -> 固定の時刻.

But I've printed random. Let me clean.

ステータス

フェーズ

スコープ

状 態

1

スキャフォルド、パッケージン、ツール支援

完了

2

model.pyqueue.py、ドメインのテス ト

完了

3

github.py GraphQL クライアント、実務の server.py

完了

4

クライアントとサーバーのテ ス ト

未着手

5

ドキュメンテーション

このファイル

Phase 3 is verified end-to-end – 実 MCP stdio のハンドシェク, ツール発見, ツール呼出し Optional – しか, tests/test_server.py まだ placeholder. The client error paths (401, 403, GraphQL 部分失敗, 接続先のホスト到達不能) are written but not yet covered by automated tests.

So:

フェーズ3は、エンドツーエンドとして検証されています。実物の MCP stdio のハンドシェク、ツールの発見、そして実ツールの呼び出しまで動いています。しかし tests/test_server.py はまだプレースホルダーのままです。クライアント側のエラー経路(401403、GraphQL の部分失敗、ホスト到達不能)は作られていますが、自動テストのカバレッジは未作です。

ライセンス

このプロジェクトは Apache License 2.0 の下で提供されます。詳細は LICENSE` ファイルを参照。

Available Tools

1 tool
get_review_queueA

Return the viewer's GitHub pull request review queue, ranked by what needs attention first: their own pull requests with failing CI, then their own with changes requested, then reviews requested of them directly, then reviews requested of their teams. Within a tier, older and smaller pull requests rank higher. Every item carries priority_reasons explaining its position, and total_matching reports how many matched before the limit.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum items to return.
reposNoRestrict to these repositories, as 'owner/name'.
includeNoWhich reasons to include. Defaults to all three.
max_age_daysNoDrop pull requests opened more than this many days ago.
exclude_draftsNoDrop draft pull requests. Defaults to true.

Output Schema

ParametersJSON Schema
NameRequiredDescription
itemsYes
viewerYes
returnedYes
warningsNo
generated_atYes
total_matchingYes
rate_limit_remainingNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the burden of disclosure. It reveals the ranking tiers, tie-breaking rules, and the fact that results include priority_reasons and total_matching. It does not discuss auth, errors, or side effects, but the operation is clearly read-oriented and described in useful detail.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and ranking intent, then economically conveys the tier order and output signals in two structurally clear runs. Every clause earns its place and no filler exists.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is complete enough for reliable invocation. It covers behavior, output information, ordering, and scoping semantics, the output schema and full parameter documentation handle the remaining return-value details, and there are no required parameters or sibling tools to complicate selection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description does not elaborate on the individual parameters such as limit, repos, include, max_age_days, or exclude_drafts, but it does not need to because those parameters are already well-documented in the input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: "Return the viewer's GitHub pull request review queue," and goes further by specifying the exact ranking logic. It is immediately clear what this tool does and how it differs from a generic list-pull-requests tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There are no siblings to contrast against, so the explicit when/when-not language is less necessary. The description makes the intended use clear: retrieve a prioritized review queue with tiered attention ordering, which is sufficient context for an agent to select it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 1 tool updatev0.1.0
    • First observedget_review_queue

TDQS

A4.4/5.0
Disambiguation5/5

The set contains only one tool, so there is no possibility of overlap or selecting the wrong tool. Its purpose is clearly and specifically described.

Naming Consistency5/5

The single tool name follows the conventional verb_noun pattern with a clear action and resource. There are no other tool names to create inconsistency.

Tool Count4/5

One tool is small, but the server is narrow by design: it exists specifically to fetch a GitHub review queue. The tool is substantial rather than trivial, so the count is slightly lean but still appropriate for the server's scope.

Completeness5/5

The tool covers the full review queue surface described: own PRs, requested changes, direct review requests, and team review requests, along with ranking reasons and match counts. There are no obvious read-model gaps within this narrow domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JigeeshaJain/ReviewQueueMcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server