Skip to main content
Glama

pr-ready-mcp

An MCP server for people who let coding agents open and look after pull requests. It has one read-only tool, pr_readiness, that checks an agent's "the PR is ready" against current GitHub data before the agent says it. It answers with a verdict pinned to a head commit and a time, every reason the PR is not verified ready, and whose move each reason is.

It is not GitHub's merge button, permission to merge, or a code review. Its rule is stricter than GitHub's merge eligibility, on purpose (see the rule).

One call, end to end: the agent asks about a PR, the tool reads GitHub once, applies the rule, and answers with a verdict pinned to a commit and a time.

Sequence diagram: a coding agent calls pr_readiness with a PR and, after a push, the commit it expects; the tool sends one read-only GraphQL query to GitHub, applies the rule to the snapshot, and returns a verdict with reasons, each naming an owner, plus head_sha and checked_at.

How the verdict is decided: a wrong head is not_ready even on a merged or closed PR, merged and closed PRs are otherwise reported rather than judged, and an open PR is ready only when no reason applies.

Flowchart: the head commit is compared with the expected sha; a mismatch is stale_head and the verdict is not_ready; a merged or closed PR with the right head is reported as merged or closed; an open PR collects every applicable reason about merge state, checks on the head commit, review and merge queue, each with an owner; ready only when no reason is listed.

Why

Agents say "green" too early. They read a check list before the last check finished. They read checks that belong to the previous push. They see 100 passing checks and miss the five failures listed after them. They report "CI passed" on a PR that still needs a review, or call an unknown merge state "fine". Each mistake is small. The person who trusted the claim finds out at merge time.

You can compose the right answer yourself from gh pr view --json … and gh pr checks. It takes about ten rules: pending is not passed; checks belong to one commit; GitHub's aggregate covers more checks than one page lists; BEHIND and BLOCKED mean something; some reviews block; UNKNOWN means ask again; no checks at all means no evidence. This tool applies those rules in one call and returns the result as data an agent can branch on.

A verdict that names the head sha and the time it was observed can be checked later. "The agent said it was green" cannot. Every reason carries a code and an owner (author, reviewer, wait, unknown), so an agent loop can tell "fix it", "ask someone", "wait" and "go and look" apart without parsing prose.

Whether this beats a well-instructed gh workflow is a claim, so it was measured. In a small paired run on six live public PRs, the agent using this tool gave the expected claim and hand-off in 6 of 6; the same agent using gh gave it in 3 of 6, with no false "ready" in either arm. That is a small sample, not a benchmark: the method, the raw counts and their limits are in DECISIONS.md.

Related MCP server: mcp-merge-guard

What it looks like

The same question, same model, same policy text, on cli/cli#14716 at 2026-10-22 15:38 UTC (transcripts):

With gh: "I can't confirm yet that cli/cli#14716 is ready to merge. … the two allowed commands don't show whether the PR is in a merge queue."

With pr_readiness: "Yes, cli/cli#14716 looks ready to merge. GitHub reported this at 2026-10-22 15:38 UTC for head commit 936921fa9e67cdbf78fb25abc6252afabafef056: merge state CLEAN … The rollup is SUCCESS. Of 16 checks, 9 passed and 7 were skipped. … The PR is not in a merge queue."

The gh baseline was given a fixed field list without isInMergeQueue, which is why it could not finish; the tool reads that field.

Install

Requires Node.js 20 or newer and a GitHub token (see Auth). The package is not on npm yet, so run it from a checkout:

git clone https://github.com/fabriciopirini/pr-ready-mcp.git
cd pr-ready-mcp
npm ci            # installs and builds dist/

Then point your client at node /absolute/path/to/pr-ready-mcp/dist/index.js. After the package is published, npx -y pr-ready-mcp replaces that command.

Claude Code

claude mcp add pr-ready -- node /absolute/path/to/pr-ready-mcp/dist/index.js

Cursor: ~/.cursor/mcp.json, or .cursor/mcp.json in a project:

{ "mcpServers": { "pr-ready": { "command": "node", "args": ["/absolute/path/to/pr-ready-mcp/dist/index.js"] } } }

Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows). Desktop apps do not inherit your shell, so pass the token:

{
  "mcpServers": {
    "pr-ready": {
      "command": "node",
      "args": ["/absolute/path/to/pr-ready-mcp/dist/index.js"],
      "env": { "GITHUB_TOKEN": "<token>" }
    }
  }
}

Codex: ~/.codex/config.toml:

[mcp_servers.pr-ready]
command = "node"
args = ["/absolute/path/to/pr-ready-mcp/dist/index.js"]

Any other stdio client: command node, argument /absolute/path/to/pr-ready-mcp/dist/index.js, optional env GITHUB_TOKEN.

Which of these were exercised, and how, is listed in DECISIONS.md.

Using it

Input: {"pr": "owner/repo#42"} or {"pr": "https://github.com/owner/repo/pull/42"}, plus "expected_head_sha" (the full 40-character git rev-parse HEAD) after a push. Call it before claiming ready, after every push, and again right before any final claim.

Prompt

What happens

Expected answer

"I just pushed. Is octo-org/widgets#42 ready?"

pr_readiness with expected_head_sha. The PR head is still the previous commit.

"Cannot verify yet: the PR head is 4f1c…, not the commit you pushed. Check whether the push landed."

"CI is green on octo-org/widgets#42. Can I tell the team it's ready?"

Verdict not_ready, reason review_required (owner reviewer).

"Not ready: the required review is not satisfied. Ask a reviewer."

"Is octo-org/widgets#42 ready?" right after a push

Verdict not_ready, reason checks_missing (owner wait).

"Cannot verify yet: no check has reported on this head. Ask again in a minute."

Full schemas: docs/tools.md. Machine-readable summary: llms.txt.

When is a PR ready?

ready means: GitHub's aggregate for the head commit is CLEAN, the check rollup on that commit is SUCCESS, no review decision blocks, the PR is not queued, and the head is the one you expected. not_ready means not verified ready: its reason codes distinguish a known blocker from evidence that is not in yet, scope the tool does not cover, or the wrong head. merged and closed are reported, not judged.

A failing or still-running optional check does not stop GitHub's merge button, but this rule waits for it: until it finishes, the PR's colour is not final. facts.merge_state always carries GitHub's own aggregate, and each listed check carries required.

Code

Owner

Meaning

draft

author

The PR is a draft.

conflicts

author

It conflicts with the base branch.

behind_base

author

GitHub reports the head as out of date with the base.

checks_failing

author

A check failed, errored, was cancelled or timed out on the head.

checks_pending

wait

A check is queued or running.

review_required

reviewer

The review requirement is not satisfied.

changes_requested

author

A reviewer requested changes.

merge_queue

wait

The PR is in the merge queue.

blocked_by_branch_rule

unknown

GitHub blocks the merge for a rule the tool cannot read (signatures, code owners, deployments …).

mergeable_unknown

wait

Cannot verify yet: GitHub has not computed mergeability.

checks_missing

wait

Cannot verify yet: no check has reported on the head.

stale_head

wait / author

Cannot verify yet: checks are for an older commit, or the head is not the commit you expected.

unsupported_merge_state

unknown

Cannot verify: HAS_HOOKS, an unexplained UNSTABLE, or a state the tool does not know.

owner is a hand-off hint: whose move it is. It is not permission to act, not a statement of who caused the problem, and not a claim that anything else is clear. A fix never contains a write command.

A merged or closed PR queried with a different expected_head_sha is not_ready with stale_head: it reached that state, but not with the commit you asked about.

Errors

Failures return isError: true and JSON text, never a verdict:

{
  "code": "rate_limited",
  "message": "GitHub rate limit reached; retry in 60s.",
  "retryable": true,
  "retry_after_seconds": 60
}

Codes: invalid_input, auth_required, forbidden, not_found_or_inaccessible, rate_limited, upstream_error, invalid_response. retry_after_seconds appears only when GitHub sent a reset time. Any GraphQL error, even beside partial data, is invalid_response: a missing field is never judged as a pass. Arguments that fail the input schema are rejected by the MCP SDK with its own plain-text error.

Auth

The token is read on the first call: GITHUB_TOKEN, then GH_TOKEN, then gh auth token. Classic tokens and the gh token usually carry far more access than this tool needs. For public repositories, a fine-grained token with "Public repositories (read-only)" access should be enough; private repositories additionally need read access to pull requests, commit statuses and checks. Neither fine-grained setup has been exercised yet; see DECISIONS.md.

Limitations

  • GitHub.com only, one PR per call, PRs with CI. A repository without CI gets checks_missing, never ready.

  • Check names are read for the first 100 checks. GitHub's rollup and per-state counts cover all of them, so the verdict does not depend on the cap; facts.checks.details_complete says when the name lists are a sample.

  • Branch rules are not read. When GitHub says BLOCKED and nothing visible explains it, the tool says so (blocked_by_branch_rule) and points at the PR page.

  • Every call is a fresh read. A verdict is an observation at checked_at, not a lock: a review, a rerun or a base change can alter it on the same head.

  • The server only reads. It never merges, marks a draft ready, pushes, re-runs checks or writes any file.

Development

npm ci
npm test              # contract tests, offline, no token
npm run typecheck
npm run lint
npm run docs          # regenerate docs/tools.md after changing the schema or description
node scripts/smoke.mjs   # start the built server and run a replayed decision over stdio

test/fixtures/ holds recorded public PR responses (node scripts/record-fixture.ts <pr> <name>) and scenarios.json, one explicit override per failure mode with the reason it exists. evals/agent/ holds the agent runs: run.mjs (Claude Code, adversarial or paired comparison), score.mjs, and the transcripts.

License

MIT

Available Tools

1 tool
pr_readinessPR readinessA
Read-onlyIdempotent

Check whether a GitHub pull request is verified ready to merge, from live GitHub data.

Call it before you say a PR is ready, green, mergeable or done; after every push; and again immediately before any final claim. Pass expected_head_sha = the full sha from git rev-parse HEAD after your push.

verdict: ready | not_ready | merged | closed. ready means GitHub's merge state is CLEAN, every check on the head passed, no review decision blocks, the PR is not queued, and the head is the one you expected. Stricter than the merge button: an optional failing or running check also blocks. not_ready means not verified ready; reasons say why.

Each reason has a code, an owner, a detail and a fix. The codes mergeable_unknown, checks_missing, stale_head and unsupported_merge_state mean "cannot verify yet": report them as that, not as a defect. Every other code is a known obstacle, checks_pending and blocked_by_branch_rule included. owner (author | reviewer | wait | unknown) says whose move it is; it is not permission to act and not a claim that anything else is clear.

This tool reads; it never merges, publishes a draft, pushes or rewrites history, and its verdict does not authorise you to. Ready, green, merged and done are different words: use the one the verdict supports, with head_sha and checked_at.

Errors come back as isError with JSON text {code, message, retryable, retry_after_seconds?}.

Example: {"pr": "octo-org/widgets#42", "expected_head_sha": "4f1c2e7a9b0d3c6e8f1a2b4c5d6e7f8091a2b3c4"}

ParametersJSON Schema
NameRequiredDescriptionDefault
prYesThe pull request: "owner/repo#42" or "https://github.com/owner/repo/pull/42". GitHub.com only.
expected_head_shaNoThe full 40-character sha you expect at the PR head: run `git rev-parse HEAD` after your push. If the PR head differs, the verdict is not_ready with stale_head.

Output Schema

ParametersJSON Schema
NameRequiredDescription
prYesThe canonical PR URL.
factsYes
reasonsYesEvery reason the PR is not verified ready. Empty when ready, merged or closed.
verdictYesready only when reasons is empty. not_ready means not verified ready; reasons say why.
head_shaYesThe PR head commit this verdict is for.
checked_atYesWhen GitHub was read (ISO 8601). An observation, not a lease.

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond the readOnly/destructive annotations: it defines the four verdict values and their exact preconditions, discloses that the tool is 'Stricter than the merge button' (optional failing/running checks also block), and classifies which reason codes mean 'cannot verify yet' versus genuine obstacles. It also states the negative capability boundary ('never merges, publishes a draft, pushes or rewrites history') and the error envelope shape {code, message, retryable, retry_after_seconds?}.

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

Conciseness4/5

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

Front-loaded with a single-sentence purpose, then ordered as when-to-use, verdict semantics, reason codes, safety boundary, errors, example — a sensible reading order. It is dense and somewhat long, and lines like 'Ready, green, merged and done are different words' shade into coaching, but each block carries operational weight.

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?

For a two-parameter verification tool with an output schema, virtually nothing an agent needs is missing: verdict meanings, blocking conditions, reason-code taxonomy, owner semantics, error format, and a concrete call example. Even though an output schema exists, the verdict vocabulary is explained in prose where it matters most.

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

Parameters4/5

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

Schema coverage is 100%, so baseline is 3; the description earns an increment by tying the sha parameter to a concrete workflow (pass the full sha from `git rev-parse HEAD` after your push) and surfacing the stale_head consequence in the verdict vocabulary. Much of this duplicates the schema's own field descriptions, so it is reinforcement rather than new information.

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?

States a specific verb and resource ('Check whether a GitHub pull request is verified ready to merge') and adds the source qualifier 'from live GitHub data', which signals freshness rather than cached state. An agent knows exactly what it gets back — a verification verdict, not a generic PR fetch.

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

Usage Guidelines5/5

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

Explicit invocation timing is given three ways: 'before you say a PR is ready, green, mergeable or done', 'after every push', and 'again immediately before any final claim'. It also names the alternative behaviour it replaces (asserting readiness without verification) and specifies the expected_head_sha workflow with `git rev-parse HEAD`.

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.

  1. 1 tool updatev0.1.0
    • First observedpr_readiness

TDQS

A4.8/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no overlap or ambiguity. Its purpose—verifying PR merge readiness from live GitHub data—is clearly and narrowly defined.

Naming Consistency5/5

The sole tool uses a clear snake_case name, pr_readiness, matching the server's purpose. With a single tool there is no inconsistency, and the name is descriptive and predictable.

Tool Count4/5

The server has a narrow, single-purpose scope, and the one comprehensive tool earns its place by covering verdicts, reasons, errors, and head-sha verification. A one-tool surface is inherently thin, but it is not trivial or mismatched to the purpose.

Completeness5/5

For the domain of PR readiness checking, the tool covers the full lifecycle: verdict states, reason codes with ownership and fixes, expected head SHA, timestamp, and structured errors. No obvious gaps exist for the stated read-only purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to scan GitHub repositories for security vulnerabilities, deployment blockers, and code quality issues. It provides detailed findings and auto-generated code patches to help developers ensure their code is production-ready.
    18 npm
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables coding agents to scout, rank, and preflight software work before implementation, returning evidence-backed ACT, VERIFY, or SKIP decisions for issues and pull requests.
    38 npm
    2
    MIT