gh-review-queue-mcp
gh-review-queue-mcp
一个 MCP 服务器,只回答一个问题:接下来我该审阅什么?
它只暴露一个工具 get_review_queue,该工具返回你的 GitHub 拉取请求审阅队列的排名去重视图——包括请求你审阅的、请求你所在团队审阅的,以及等待他人审阅的你自己提交的拉取请求。
只提供一个工具是刻意为之的约束。一个助手如果不得不在 list_prs、search_prs 和 get_pr_status 之间选择,它的第一轮就会花在选择上;而一个只有一个工具、能返回已排序列表的助手,可以直接给出答案。
它实际做什么
调用该工具时,按顺序发生四件事。
1. 识别你和你的团队
服务器会针对 viewer { login } 发出 GraphQL 查询,再加上你所属的团队(organizations.teams(role: MEMBER))。团队 slug 很关键,因为 GitHub 的搜索 API 没有“请求我的任何团队审阅”这样的限定符——你必须显式指名每个团队。这也是令牌需要 read:org 权限范围的唯一原因。
2. 扇出为一次批量搜索
GitHub 没有单一查询能表达“所有需要我关注的内容”,因此服务器会运行多个搜索并合并结果。所有这些搜索通过别名在一个 GraphQL 文档中发出,因此无论你属于多少个团队,都只有一次 HTTP 往返:
别名 | 搜索 | 成为的原因 |
|
|
|
|
|
|
|
|
|
搜索字符串作为 GraphQL 变量传递,绝不插值到查询文档中,因此团队 slug 无法改变查询结构。
同一个查询还会请求 rateLimit { remaining resetAt },因此每次响应都能报告你剩余的限额,而无需再次调用。
关于响应形态有两点说明。GitHub 的 search(type: ISSUE) 同时返回 issue 和拉取请求;由于选择集是 PullRequest 上的内联片段,issue 会以空节点返回,并在解析时被丢弃。另外,statusCheckRollup 是从 commits(last: 1) 读取的——即头部提交的 CI 状态,而不是整个分支历史。
3. 合并、去重、过滤、排名
同一个拉取请求经常从多个搜索中返回——一个你既是直接审阅人、并且你的团队也被请求的 PR,会出现在两个桶里。它们按 GraphQL 节点 ID 去重,原因会累积到同一条目上,因此响应会说“它因为两个原因出现在这里”,而不是把它列出两次。
然后应用你的过滤条件,幸存下来的内容再被打分和排序。
4. 序列化
排名列表以结构化输出返回——该工具声明了完整的 JSON 输出模式,因此客户端获得的是有类型的字段,而不是需要自行解析的散文。
Related MCP server: github-ops-mcp
排名机制
排名是分层的,而不是调权重。每个拉取请求恰好落在一个层级中,层级的价值远远大于层级内部累积的任何分值:
层级 | 条件 | 基础分 |
3 | 你自己的 PR,CI 失败 | 300 |
2 | 你自己的 PR,被请求更改 | 200 |
1 | 直接请求你审阅的 | 100 |
0 | 团队请求,或你自己的 PR 只是在等待 | 0 |
在层级内部,还有两个较小的信号会生效:
年龄——自 PR 打开以来每天 2 分,上限 20。旧的审阅请求会浮现出来,但六个月前的 PR 不可能永远主导。
小改动——对 100 行或更少的改动给予固定 8 分奖励,理由是你现在能完成的小审阅,胜过你以后才会去做的的大审阅。
上限才是关键所在。层级内部最多能累积 20 + 8 = 28 分,远低于 100 的层级步进,因此层级主导性在构造上就成立:一个全新的直接请求永远胜过古老的团队请求,未来的权重调整无法悄悄翻转这一点。如果你要新增一个打分信号,请保持层级内总分低于 100,否则这一保证就会被打破。
同分按最近活动时间(updatedAt)打破,因此在相同分数下,活跃的讨论会胜过停滞的讨论。
每个条目都带有 priority_reasons——人类可读的字符串,如 ["my PR, CI failing", "3 days old"]——这样排名可以向你解释清楚,而不是以一个无法解释的数字呈现。
安装
需要 Python 3.11+ 和 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——读取你的团队成员关系,用于 team-review-requested 搜索
经典 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 Inspector
npx @modelcontextprotocol/inspector uv --directory /absolute/path/to/ReviewQueueMcp run gh-review-queue-mcp打开打印出的 URL,连接后,该工具会出现在工具下,并带有其生成的输入模式。
使用 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 不会从你的 shell 启动服务器,因此它没有可继承的工作目录或已导出的环境。编辑后重启 Claude Desktop,然后问它“今天该审阅什么?”
工具参考
get_review_queue
所有参数都是可选的。
参数 | 类型 | 默认值 | 含义 |
|
| 全部三项 | 要包含哪些原因。只要某条目的任一原因被包含,该条目就会保留。 |
| 布尔值 |
| 丢弃草稿。它们是直接被排除,而不是降级——草稿还不可审阅。 |
| 整数 | 无 | 丢弃打开时间超过这个天数上限的 PR。边界值包含在内。 |
|
| 无 | 限制在这些仓库中。精确匹配。 |
| 1–100 的整数 |
| 返回的最大条目数。 |
响应:
{
"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"
}
]
}returned 与 total_matching 区分了“这里有 25 条”和“数量很多”——没有它,受限的响应与完整的响应就无从区分。
warnings 承载 GraphQL 部分失败。GitHub 可以在返回错误的同时返回可用数据(某个组织不可读、某个搜索失败);与其丢弃整个队列,不如将这些降级为警告,其余结果仍然会返回。
架构
src/gh_review_queue/ 下有四个模块,并且模块间的边界起着承重作用:
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:因为它只接收一个 QueueSnapshot 和一个 datetime,除此之外再无其他,所以每条排名规则都可以用纯数据进行测试,无需 mock、无需网络、也无需修补时钟。这正是拆分的原因,也是为什么 httpx 导入绝不能触及它的原因。
降级而非失败
来自 GitHub 的未知枚举值——新的 reviewDecision、新的 CI rollup 状态——会被映射为 None,而不是抛出异常。GitHub 侧新增的状态绝不应破坏你的整个队列。同样的思路贯穿解析层:缺失的作者会变成 ghost(GitHub 自己对已删除账户的约定),非 PR 的搜索结果会被丢弃,而缺失时间戳是唯一真正无法恢复、确实会抛出异常的情况。
开发
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 中的 [tool.mypy] files 读取目标,因此传入路径所检查的内容会比预期的少。
测试方法
测试基于 tests/fixtures/queue_response.json 运行,这是一份捕获的 GraphQL 响应,专门构造来包含那些棘手的情况:一条出现在两个桶中的 PR、一个草稿、一条非常陈旧的 PR、一条属于查看者且 CI 失败的 PR,以及一个为 null 的 status rollup。
test_rank_orders_the_fixture_the_way_a_reviewer_would_read_it 针对固定的时钟断言精确的分数。它是打分规则变更的金丝雀——如果它失败了,在更新数字之前,先判断新的排序是否确实更好。
状态
阶段 | 范围 | 状态 |
1 | 脚手架、打包、工具链 | 已完成 |
2 |
| 已完成 |
3 |
| 已完成 |
4 | 客户端和服务器测试 | 未开始 |
5 | 文档 | 本文件 |
第 3 阶段已端到端验证——真实的 MCP stdio 握手、工具发现和一次工具调用——但 tests/test_server.py 仍是一个占位符。客户端的错误路径(401、403、部分 GraphQL 失败、主机不可达)已编写,但尚未被自动化测试覆盖。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseAqualityDmaintenanceA minimal MCP server that exposes a focused set of GitHub PR review tools to AI agents, enabling PR listing, detail retrieval, comment viewing, and thread management.5
- AlicenseAqualityBmaintenanceAn MCP server that provides operational tooling over the GitHub API — issue triage, PR review monitoring, repo health audits, and team access reviews.111MIT
- FlicenseAqualityBmaintenanceAn MCP server exposing AI-powered GitHub PR review as tools.5
- AlicenseAqualityCmaintenanceA production-ready MCP server for triaging and reviewing GitHub pull requests via the GitHub REST API, providing typed tools to list, inspect, comment, add labels, and submit reviews.821MIT
Related MCP Connectors
A Model Context Protocol (MCP) application for automated GitHub PR analysis and issue management.…
An MCP server that gives your AI access to the source code and docs of all public github repos
A MCP server built for developers enabling Git based project management with project and personal…
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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