From gosu-mcp-core
Utility scripts for GitHub pull request management. Includes tools for fetching bot-generated review comments (linters, security scanners, dependabot), replying to review threads programmatically, listing merged pull requests with filtering, resolving conversations, and automating PR review workflows. Useful for batch processing comments, CI/CD integration, quality metrics tracking, release notes generation, and automated responses to bot reviewers.
npx claudepluginhub gosu-code/claude-plugin --plugin gosu-mcp-coreThis skill uses the workspace's default tool permissions.
A collection of utility scripts for managing GitHub pull requests, including review comment management, merged PR tracking, and automated workflows. These scripts are designed for handling bot-generated review feedback, generating release notes, and automating PR review workflows.
Executes GitHub operations (PRs, issues, milestones, labels, comments, merges) using Python scripts with structured output and error handling. Use for pull requests, issues, review comments, CI checks, milestones instead of raw gh.
Executes GitHub operations on PRs, issues, milestones, labels, comments, and merges using Python scripts with structured output and error handling. Use for pull requests, issues, review comments, CI checks, or milestones instead of raw gh.
Resolves GitHub PR issues including review comments, CI failures via triage-dispatch workflow with code edits, replies, and verification.
Share bugs, ideas, or general feedback.
A collection of utility scripts for managing GitHub pull requests, including review comment management, merged PR tracking, and automated workflows. These scripts are designed for handling bot-generated review feedback, generating release notes, and automating PR review workflows.
These scripts can be executed in two ways depending on your environment:
Requirements:
gh CLI version 2.4+jq CLI version 1.5+When to use:
gh and jq installed on your host system with correct versiongh CLI is authenticated (check with gh auth status)Requirements:
mcp__gosu__run_cli is available on the Gosu MCP serverWhen to use:
gh or jq are not installed on your host systemgh CLI is not authenticated on your host systemFetches all bot-authored review comments for a pull request using the GitHub GraphQL API.
scripts/get_pr_bot_review_comments.sh [OPTIONS] <owner> <repo> <pr_number>
--exclude-resolved - Filter out resolved review threads--exclude-outdated - Filter out outdated review comments--include-github-user login1,login2 - Also include comments from specific GitHub users (comma-separated list)--include-diff-hunk - Include the diff hunk context for each comment, do use this option unless explicitly requested by user.-h, --help - Display help message<owner> - Repository owner (organization or user)<repo> - Repository name<pr_number> - Pull request numberReturns a JSON array of review comments with the following structure:
[
{
"threadId": "PRRT_...",
"threadPath": "src/file.go",
"threadLine": 42,
"threadStartLine": null,
"threadOriginalLine": null,
"threadOriginalStartLine": null,
"threadIsResolved": false,
"threadIsOutdated": false,
"comment": {
"id": "PRRC_...",
"databaseId": 123456789,
"url": "https://github.com/...",
"createdAt": "2024-01-01T00:00:00Z",
"updatedAt": "2024-01-01T00:00:00Z",
"body": "Comment text here",
"isMinimized": false,
"minimizedReason": null,
"outdated": false,
"path": "src/file.go",
"position": 42,
"originalPosition": null,
"diffHunk": "@@ -40,7 +40,7 @@ ...",
"author": {
"__typename": "Bot",
"login": "bot-name[bot]"
},
"commit": {
"oid": "abc123..."
}
}
}
]
Fetch all bot comments for a PR:
scripts/get_pr_bot_review_comments.sh gosu-code gosu-mcp-server 123
Fetch unresolved bot comments:
scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
gosu-code gosu-mcp-server 123
Fetch unresolved & not outdated bot comments:
scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
--exclude-outdated \
gosu-code gosu-mcp-server 123
Fetch comments from bot and also non bot users:
scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
--include-github-user dependabot,renovate \
gosu-code gosu-mcp-server 123
Process comments with jq:
# Count total bot comments
scripts/get_pr_bot_review_comments.sh gosu-code gosu-mcp-server 123 | jq 'length'
# Extract comment bodies only
scripts/get_pr_bot_review_comments.sh gosu-code gosu-mcp-server 123 | \
jq -r '.[].comment.body'
# Group comments by file
scripts/get_pr_bot_review_comments.sh gosu-code gosu-mcp-server 123 | \
jq 'group_by(.threadPath) | map({path: .[0].threadPath, count: length})'
Reply to an existing pull request review comment thread using the GitHub REST API.
scripts/reply_pr_review_comments_thread.sh [OPTIONS] <owner> <repo> <comment_id>
Body Input (choose one):
--body "text" - Inline Markdown body for the reply (prefer to use this unless the text is long or contain special character)--body-file path - Read reply body from a file--stdin - Read reply body from STDIN (not recommended to use)Additional Options:
--thread-id id - GraphQL thread node ID (required with --resolve-thread)--resolve-thread - Resolve the review thread after posting (requires --thread-id)-h, --help - Display help message<owner> - Repository owner (organization or user)<repo> - Repository name<comment_id> - Comment ID (either numeric database ID or GraphQL node ID like PRRC_*)Reply with inline text:
scripts/reply_pr_review_comments_thread.sh \
--body "Thanks for catching that! Fixed in the latest commit." \
gosu-code gosu-mcp-server 2451122234
Reply from a file:
scripts/reply_pr_review_comments_thread.sh \
--body-file reply.md \
gosu-code gosu-mcp-server 2451122234
Compose reply in editor:
scripts/reply_pr_review_comments_thread.sh \
gosu-code gosu-mcp-server 2451122234
Reply with confirmation prompt:
scripts/reply_pr_review_comments_thread.sh \
--body "Updated the implementation." \
gosu-code gosu-mcp-server 2451122234
Reply and resolve the thread:
scripts/reply_pr_review_comments_thread.sh \
--body "Done! Resolving this thread." \
--thread-id PRRT_kwDODds1es5e2SRi \
--resolve-thread \
gosu-code gosu-mcp-server 2451122234
Dry run to preview:
scripts/reply_pr_review_comments_thread.sh \
--body "Test reply" \
gosu-code gosu-mcp-server 2451122234
List merged pull requests with optional filtering by authors and date range. Supports saving PR details to individual markdown files for documentation or release notes.
scripts/list_merged_pr.sh [OPTIONS]
Filtering Options:
-a, --authors USERS - Comma-separated list of GitHub usernames to filter by-f, --from DATE - Start date for PR merge filter (YYYY-MM-DD format)-t, --to DATE - End date for PR merge filter (YYYY-MM-DD format)-d, --days DAYS - Number of days to look back (alternative to --from), default: 7-r, --repo REPO - GitHub repository in format "owner/repo", default: current repositoryOutput Options:
-s, --save [DIR] - Save PR details to files (one file per PR), optional directory path, default: ./out-h, --help - Display help messageConsole Output: Displays a tab-separated list of PRs with: PR number, title (truncated to 120 chars), author, merge date, and URL.
File Output (with --save):
Creates one markdown file per PR with the format PR-{number}-{title}.md containing:
List all merged PRs from last 7 days (default):
scripts/list_merged_pr.sh
List merged PRs from specific authors:
scripts/list_merged_pr.sh --authors "john,jane,bob"
List merged PRs from last 30 days:
scripts/list_merged_pr.sh --days 30
List merged PRs within a specific date range:
scripts/list_merged_pr.sh --from "2025-10-01" --to "2025-10-31"
Combine filters: specific authors and date range:
scripts/list_merged_pr.sh --authors "john,jane" --from "2025-10-01" --to "2025-10-31"
Query a specific repository:
scripts/list_merged_pr.sh --repo "owner/repo" --days 30
Save PR details to files in ./out directory:
scripts/list_merged_pr.sh --save
Save PR details to custom directory:
scripts/list_merged_pr.sh --save /path/to/output --days 30
Process with jq:
# Count merged PRs
scripts/list_merged_pr.sh --days 30 | wc -l
# Extract just PR numbers
scripts/list_merged_pr.sh | cut -f1 | sed 's/#//'
# Fetch all unresolved bot comments
comments=$(scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
gosu-code gosu-mcp-server 123)
# Loop through and reply to each
echo "$comments" | jq -r '.[].comment.databaseId' | while read -r comment_id; do
scripts/reply_pr_review_comments_thread.sh \
--body "Addressed in latest commit." \
gosu-code gosu-mcp-server "$comment_id"
done
# Fetch comments with the entire file diff context
scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
--include-diff-hunk \
gosu-code gosu-mcp-server 123 > bot_comments.json
# Generate markdown report with from json output
jq -r '.[] | "## \(.threadPath):\(.threadLine)\n\n\(.comment.body)\n\n```diff\n\(.comment.diffHunk)\n```\n"' \
bot_comments.json > bot_review_summary.md
# Get comments from bots and also `dependabot` user
dependabot_comments=$(scripts/get_pr_bot_review_comments.sh \
--include-github-user dependabot \
gosu-code gosu-mcp-server 123)
# Reply to each with specific message
echo "$dependabot_comments" | jq -r '.[].comment.databaseId' | while read -r comment_id; do
echo "Acknowledged, Will fix this in another PR." | \
scripts/reply_pr_review_comments_thread.sh \
--stdin \
gosu-code gosu-mcp-server "$comment_id"
done
# Fetch all unresolved comments
scripts/get_pr_bot_review_comments.sh \
--exclude-resolved \
gosu-code gosu-mcp-server 123 | \
jq -r '.[] | "\n=== \(.threadPath):\(.threadLine) ===\n\(.comment.body)\n\nComment ID: \(.comment.databaseId)"'
get_pr_bot_review_comments.sh script identifies bots by checking if the author's __typename is "Bot" or if the login contains "[bot]"Authentication errors: Confirm if user is authenticated in the GitHub CLI, if not inform user to login with a credential that have the right access
gh auth status
Permission errors:
When gh or jq are not available on your host system, you can use the Gosu MCP server's run_cli tool (tool full name: mcp__gosu__run_cli) to execute these scripts in a sandboxed environment where all required tools are available.
The MCP run_cli tool:
GH_TOKEN from server configuration for authenticationbash, gh, jq, git, python3, and othersStep 1: Copy Scripts to Workspace
cp -rf ${CLAUDE_PLUGIN_ROOT}/skills/github-pr-utils/scripts ./scripts/
Step 2: Use MCP run_cli Tool
Basic structure of an MCP run_cli call:
{
"program": "bash",
"arguments": ["scripts/script-name.sh", "arg1", "arg2", "..."],
"timeout": 120
}
Step 3: Process Results
The tool returns:
{
"exit_code": 0,
"stdout": "script output here",
"stderr": "",
"duration_ms": 1543,
"truncated": false,
"stderr_truncated": false
}
| Parameter | Type | Required | Description |
|---|---|---|---|
program | string | Yes | "bash" for shell scripts, "jq" for JSON processing, "gh" for GitHub CLI |
arguments | array | Yes | For bash: ["scripts/script.sh", "args..."]For jq: ["filter", "file.json"] |
timeout | number | No | Timeout in seconds (default: 60, max: 300) |
environment | object | No | Additional environment variables (GH_TOKEN auto-injected) |
stdin_input | string | No | String to pipe to stdin (mutually exclusive with stdin_file) |
stdin_file | string | No | File path to read for stdin (mutually exclusive with stdin_input) |
output_file | string | No | Redirect stdout to file (for large outputs > 100KB) |
error_file | string | No | Redirect stderr to file |
Important Notes:
"program": "bash" only for running .sh scripts, not inline bash commands"program": "jq" for JSON processing instead of bash -c "jq ..."bash and gh programsWhen using these scripts via MCP run_cli:
bash and gh programs - no manual gh auth login requiredoutput_file or error_file parameters../) are blocked for securityexit_code in response - 0 indicates success, non-zero indicates error, 124 indicates timeoutstderr field in response for error messages when exit_code is non-zeroFetch all bot comments:
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "bot_comments.json"
}
Fetch unresolved bot comments:
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"--exclude-resolved",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "unresolved_comments.json"
}
Fetch unresolved & not outdated comments:
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"--exclude-resolved",
"--exclude-outdated",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "active_comments.json"
}
Include specific GitHub users:
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"--exclude-resolved",
"--include-github-user",
"dependabot,renovate",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "bot_and_user_comments.json"
}
Process JSON with jq:
{
"program": "jq",
"arguments": ["length", "bot_comments.json"]
}
Extract comment bodies:
{
"program": "jq",
"arguments": ["-r", ".[].comment.body", "bot_comments.json"]
}
Group comments by file:
{
"program": "jq",
"arguments": [
"group_by(.threadPath) | map({path: .[0].threadPath, count: length})",
"bot_comments.json"
]
}
Reply with inline text:
{
"program": "bash",
"arguments": [
"scripts/reply_pr_review_comments_thread.sh",
"--body",
"Thanks for catching that! Fixed in the latest commit.",
"gosu-code",
"gosu-mcp-server",
"2451122234"
]
}
Reply from file content:
First, create the reply file:
{
"program": "bash",
"arguments": [
"-c",
"echo 'Updated the implementation as suggested.' > reply.md"
]
}
Then reply using the file:
{
"program": "bash",
"arguments": [
"scripts/reply_pr_review_comments_thread.sh",
"--body-file",
"reply.md",
"gosu-code",
"gosu-mcp-server",
"2451122234"
]
}
Reply and resolve thread:
{
"program": "bash",
"arguments": [
"scripts/reply_pr_review_comments_thread.sh",
"--body",
"Done! Resolving this thread.",
"--thread-id",
"PRRT_kwDODds1es5e2SRi",
"--resolve-thread",
"gosu-code",
"gosu-mcp-server",
"2451122234"
]
}
Multiple sequential replies:
Loop through comment IDs and reply to each:
{
"program": "bash",
"arguments": [
"-c",
"jq -r '.[].comment.databaseId' bot_comments.json | while read -r id; do scripts/reply_pr_review_comments_thread.sh --body 'Addressed in latest commit.' gosu-code gosu-mcp-server \"$id\"; done"
],
"timeout": 180
}
List all merged PRs from last 7 days:
{
"program": "bash",
"arguments": ["scripts/list_merged_pr.sh"],
"output_file": "merged_prs.txt"
}
Filter by specific authors:
{
"program": "bash",
"arguments": [
"scripts/list_merged_pr.sh",
"--authors",
"john,jane,bob"
],
"output_file": "team_prs.txt"
}
List PRs from last 30 days:
{
"program": "bash",
"arguments": [
"scripts/list_merged_pr.sh",
"--days",
"30"
],
"output_file": "monthly_prs.txt"
}
Specific date range:
{
"program": "bash",
"arguments": [
"scripts/list_merged_pr.sh",
"--from",
"2025-10-01",
"--to",
"2025-10-31"
],
"output_file": "october_prs.txt"
}
Save PR details to files:
{
"program": "bash",
"arguments": [
"scripts/list_merged_pr.sh",
"--save",
"./out",
"--days",
"30"
],
"timeout": 180
}
Query specific repository:
{
"program": "bash",
"arguments": [
"scripts/list_merged_pr.sh",
"--repo",
"owner/repo",
"--days",
"30"
],
"output_file": "repo_prs.txt"
}
Fetch comments, then process with jq:
# Step 1: Fetch comments
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"--exclude-resolved",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "comments.json"
}
# Step 2: Count comments
{
"program": "jq",
"arguments": ["length", "comments.json"]
}
# Step 3: Extract thread IDs
{
"program": "jq",
"arguments": ["-r", ".[].threadId", "comments.json"],
"output_file": "thread_ids.txt"
}
Always check exit_code in the response:
{
"program": "bash",
"arguments": ["scripts/get_pr_bot_review_comments.sh", "owner", "repo", "123"],
"output_file": "comments.json"
}
// Response:
{
"exit_code": 0, // 0 = success, non-zero = error
"stdout": "",
"stderr": "",
"duration_ms": 1543,
"output_file": "comments.json"
}
If exit_code is non-zero, check stderr for error details.
For operations that produce large output (> 100KB), use output_file:
{
"program": "bash",
"arguments": [
"scripts/get_pr_bot_review_comments.sh",
"--include-diff-hunk",
"gosu-code",
"gosu-mcp-server",
"123"
],
"output_file": "large_comments.json",
"timeout": 120
}
Then read the file separately or process it with subsequent jq commands.
Pass data to program via stdin:
{
"program": "jq",
"arguments": [".[] | select(.threadIsResolved == false)"],
"stdin_input": "[{\"threadId\":\"PRRT_123\",\"threadIsResolved\":false},{\"threadId\":\"PRRT_456\",\"threadIsResolved\":true}]"
}
Script not found error:
exit_code: 127
stderr: "bash: scripts/get_pr_bot_review_comments.sh: No such file or directory"
Solution: Ensure scripts are copied to workspace directory and path is correct relative to workspace root.
Output truncated warning:
{
"exit_code": 0,
"stdout": "...",
"truncated": true
}
Solution: Use output_file parameter to redirect output to a file and avoid 100KB truncation limit.
Timeout error:
exit_code: 124
stderr: "signal: killed"
Solution: Increase timeout parameter (max 300 seconds) for long-running operations.
Path traversal blocked:
stderr: "Error: path traversal attempt detected"
Solution: Use relative paths only. Paths like ../ or absolute paths are blocked for security.
Permission denied errors:
exit_code: 1
stderr: "permission denied: scripts/get_pr_bot_review_comments.sh"
Solutions:
chmod +x scripts/*.shJSON parsing errors with jq:
exit_code: 1
stderr: "jq: parse error: Invalid JSON"
Solutions:
cat file.json | jq .output_file to inspect intermediate outputs for debugging