Repository navigation
feat: add list_pull_request_review_threads tool to expose PRRT_ node IDs for resolving threads #2229
Description
Problem
resolve_pull_request_review_thread requires a thread node ID in PRRT_xxx format. However, this ID is not returned by any existing REST-based MCP tool — it is only obtainable via the GraphQL API.
Currently there is no way to complete the "list unresolved threads → resolve them" flow using the MCP tools alone, because there is no tool to retrieve the PRRT_xxx node IDs needed by resolve_pull_request_review_thread.
Proposed Solution
Add a list_pull_request_review_threads tool that uses the existing githubv4 GraphQL client (already a dependency) to query review threads and return their node IDs.
Tool Definition
Name: list_pull_request_review_threads
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
owner |
string | ✅ | Repository owner |
repo |
string | ✅ | Repository name |
pull_number |
integer | ✅ | Pull request number |
is_resolved |
boolean | ❌ | Filter by resolution status. Omit to return all threads. |
Output (per thread):
| Field | Type | Description |
|---|---|---|
id |
string | Node ID in PRRT_xxx format — required for resolve_pull_request_review_thread |
isResolved |
boolean | Whether the thread has been resolved |
isOutdated |
boolean | Whether the thread is outdated (code changed after the comment) |
path |
string | File path the thread is on |
line |
integer | End line number |
startLine |
integer | Start line number |
firstComment.body |
string | Body of the first comment in the thread |
firstComment.author |
string | Login of the commenter |
firstComment.createdAt |
string | ISO 8601 timestamp |
Response envelope:
{
"threads": [...],
"totalCount": 4,
"truncated": false
}Suggested GraphQL Query
query($owner: String!, $repo: String!, $number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
totalCount
nodes {
id
isResolved
isOutdated
path
line
startLine
comments(first: 1) {
nodes {
body
author { login }
createdAt
}
}
}
}
}
}
}Registration
Would fit naturally in AllTools() in pkg/github/tools.go, alongside the existing resolve_pull_request_review_thread tool in ToolsetMetadataPullRequests.
Use Case / Motivation
The intended workflow is:
list_pull_request_review_threads(owner, repo, pull_number, is_resolved=false)
→ returns [{ id: "PRRT_kwDO...", ... }, ...]
resolve_pull_request_review_thread(threadId: "PRRT_kwDO...")
→ marks thread as resolved
Without list_pull_request_review_threads, an AI agent has no way to obtain the PRRT_xxx ID, making resolve_pull_request_review_thread effectively unusable from an MCP context.
Validation
We implemented this tool as a local patch against the current main branch and validated the end-to-end flow:
- Tool appears in the MCP tool list ✅
- Returns
PRRT_xxxnode IDs correctly ✅ is_resolved=falsefilter works as expected ✅- Returned IDs successfully used with
resolve_pull_request_review_threadto resolve all 4 unresolved threads in a live PR ✅
The patch implementation is available at:
https://github.com/scottlz0310/Mcp-Docker/blob/main/patches/github/list_pr_review_threads.go
Additional Notes
- No new dependencies required — uses the existing
github.com/shurcooL/githubv4client is_resolveduses a 3-value pattern (nil = all, true = resolved only, false = unresolved only) consistent with similar optional boolean filters in the codebase- Type names chosen to avoid collision with existing
reviewThreadsQuery/reviewThreadNodetypes inpullrequests.go
Happy to submit a PR if this direction looks good to the maintainers.
Activity
scottlz0310-user commentedon Apr 27, 2026
Closing this issue as we've since taken a different approach.
We've implemented
list_pull_request_review_threads(along withget_copilot_review_statusand related tools) as a standalone MCP service in a separate repository: https://github.com/scottlz0310/copilot-review-mcpThis service runs alongside the official
github-mcp-serverand provides the full PR review thread workflow without requiring changes to the upstream server. This approach gives us the flexibility to iterate independently.Thank you to everyone who reacted to this issue — the problem (PRRT_ node IDs not being accessible via MCP tools) remains valid, and if the upstream maintainers ever want to address it natively, the implementation details in this issue may still be useful reference.
Withdrawing the request.
SamMorrowDrums commentedon Apr 27, 2026
@scottlz0310-user we may yet get to n this, you're welcome to leave open even though it's resolved for you yourself with additional server.
We haven't ruled it out, there's just a lot of things we are responsible for, use-cases and problems like this are really helpful.
MitchTalmadge commentedon Apr 27, 2026
I also vote to leave it open or make a duplicate :) Still need this
scottlz0310-user commentedon Apr 27, 2026
@SamMorrowDrums
Happy to reopen! The standalone copilot-review-mcp works well for our use case,
but native support in github-mcp-server would definitely benefit more users
(as MitchTalmadge's comment confirms). Leaving it open for upstream consideration.
kaovilai commentedon Apr 30, 2026
Note
Responses generated with Claude
It looks like this may already be resolved by existing tools:
pull_request_readwith methodget_review_commentsreturns threads with metadata including thread IDspull_request_review_writewith methodresolve_threadacceptsthreadId(PRRT_ node ID)The
pull_request_review_writetool description itself says: "Get thread IDs from pull_request_read with method get_review_comments."This suggests the end-to-end flow described in this issue (list unresolved threads → get PRRT_ IDs → resolve them) is now possible without a separate
list_pull_request_review_threadstool. Could this be closed?scottlz0310-user commentedon Apr 30, 2026
@kaovilai
This issue will be resolved by #2245, which restores the
idfieldto
MinimalReviewThreadinget_review_comments.Note for #issuecomment-4356412600: the end-to-end flow is NOT yet
possible — #2245 is still open and unmerged. The
idfield is absentfrom the current shipped response, as confirmed by hands-on testing
(which is why copilot-review-mcp exists).
Supporting #2245. 👍
kaovilai commentedon Apr 30, 2026
ic thx.
aarondglover commentedon May 6, 2026
yes I was about to log an issue for this very sisue
get_review_commentsdoes not return thread node IDs required byresolve_threadSummary
The
pull_request_readtool withmethod: get_review_commentsdocuments that it returns thread IDs for use withresolve_thread, but the actual response omits the thread node ID (PRRT_kwDO...format) from each thread object. This makes
resolve_threadunusable without a separate GraphQL call outside the MCP toolset.Expected behaviour
Each thread object returned by
get_review_commentsshould include aid(ornode_id) field containing the thread's GraphQL node ID (e.g.PRRT_kwDOKv9N8c6AQpXZ), consistent with the tooldescription which states:
Actual behaviour
The response contains
review_threadsobjects with only:{ "is_resolved": false, "is_outdated": false, "is_collapsed": false, "comments": [ ... ], "total_count": 2 }There is no id or node_id on the thread itself. Individual comments have an html_url like https://github.com/.../pull/429#discussion_r3194795661, but the discussion_r... value is the comment ID, not the
thread node ID required by resolve_thread.
Attempting to use resolve_thread with a guessed PRRT_... ID returns:
failed to resolve review thread: Could not resolve to a node with the global id of 'PRRT_...'
Impact
resolve_thread and unresolve_thread are completely unusable through the MCP toolset alone. Workarounds require either:
Steps to reproduce
Suggested fix
Add a id field (the GraphQL node_id, e.g. PRRT_kwDO...) to each thread object in the get_review_comments response. This field is available on PullRequestReviewThread.id in GitHub's GraphQL schema and is
already used internally to power resolve_thread.
Environment
scottlz0310-user commentedon May 7, 2026
@aarondglover
Thank you for the detailed report — this is exactly what #2229 tracks.
The fix is proposed in #2245, which restores the
idfield to each thread object inget_review_comments. Untilthat's merged, copilot-review-mcp is available as a
tandalone workaround that exposes the full thread-resolve workflow independently.
SamMorrowDrums commentedon May 8, 2026
Triage note: tracking this with #2245 for now. If that PR lands, it should restore the thread IDs needed for the
get_review_comments->resolve_threadflow without adding a separate listing tool.scottlz0310-user commentedon Jun 2, 2026
Update: the core issue has been fixed on
mainby #2245.#2245 restores the review thread
idfield in the existingget_review_commentsresponse, which enables the MCP-only workflow:get_review_comments→ obtain threadid→resolve_thread/unresolve_threadThis is a cleaner upstream fix than the new
list_pull_request_review_threadstool proposed here.I'll keep this issue open until the fix is included in a tagged release, since the latest release (
v1.1.2) does not appear to include #2245 yet. Once a release containing #2245 is available, this issue can be closed as resolved.scottlz0310-user commentedon Jun 7, 2026
resolved by #2515 / also addressed by #2245