get_pull_request_review_comments
Fetch detailed line-by-line review comments for any GitHub pull request to analyze code feedback.
Instructions
Get review comments (line-by-line code comments) for a specific pull request.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| owner | Yes | Repository owner | |
| repo | Yes | Repository name | |
| pullNumber | Yes | Pull request number | |
| sort | No | Sort comments by created or updated time | |
| direction | No | Sort direction | |
| since | No | Only show comments updated after this time (ISO 8601 format) | |
| per_page | No | Results per page (default 10, max 100) | |
| page | No | Page number (default 1) |
Implementation Reference
- src/tools/pullrequests.ts:704-793 (handler)The async handler function that executes the tool logic: calls octokit.rest.pulls.listReviewComments with the provided parameters, formats the results as markdown, and returns them.
async ({ owner, repo, pullNumber, sort, direction, since, per_page, page, }) => { try { const response = await octokit.rest.pulls.listReviewComments({ owner, repo, pull_number: pullNumber, sort, direction, since, per_page, page, }) const comments = response.data if (comments.length === 0) { return { content: [ { type: "text", text: "No review comments found for this pull request.", }, ], } } // Format as clean markdown let markdown = `# Review Comments for Pull Request #${pullNumber}\n\n` markdown += `Showing ${comments.length} review comment(s) - Page ${page}\n` if (comments.length === per_page) { markdown += `*Note: More results may be available. Use 'page' parameter to see next page.*\n` } markdown += `\n` comments.forEach((comment, index) => { markdown += `## Comment ${index + 1}\n\n` markdown += `- **Author:** ${comment.user?.login || "Unknown"}\n` markdown += `- **File:** ${comment.path}\n` if (comment.line) { markdown += `- **Line:** ${comment.line}\n` } if (comment.start_line && comment.start_line !== comment.line) { markdown += `- **Lines:** ${comment.start_line}-${comment.line}\n` } markdown += `- **Side:** ${comment.side || "RIGHT"}\n` markdown += `- **Created:** ${new Date(comment.created_at).toLocaleDateString()}\n` if (comment.updated_at !== comment.created_at) { markdown += `- **Updated:** ${new Date(comment.updated_at).toLocaleDateString()}\n` } if (comment.commit_id) { markdown += `- **Commit:** ${comment.commit_id.substring(0, 7)}\n` } if (comment.in_reply_to_id) { markdown += `- **Reply to:** Comment #${comment.in_reply_to_id}\n` } markdown += `\n**Comment:**\n${comment.body}\n` if (comment.html_url) { markdown += `\n**URL:** ${comment.html_url}\n` } markdown += `\n---\n\n` }) return { content: [{ type: "text", text: markdown }], } } catch (e: any) { return { content: [{ type: "text", text: `Error: ${e.message}` }], } } }, ) - src/tools/pullrequests.ts:678-703 (schema)Zod schema definitions for input validation: owner, repo, pullNumber (required), and optional sort, direction, since, per_page, page.
{ owner: z.string().describe("Repository owner"), repo: z.string().describe("Repository name"), pullNumber: z.number().describe("Pull request number"), sort: z .enum(["created", "updated"]) .optional() .describe("Sort comments by created or updated time"), direction: z.enum(["asc", "desc"]).optional().describe("Sort direction"), since: z .string() .optional() .describe( "Only show comments updated after this time (ISO 8601 format)", ), per_page: z .number() .optional() .default(10) .describe("Results per page (default 10, max 100)"), page: z .number() .optional() .default(1) .describe("Page number (default 1)"), }, - src/tools/pullrequests.ts:674-793 (registration)Registration of the tool using server.tool() with the name 'get_pull_request_review_comments' and descriptive text.
// Tool: Get Pull Request Review Comments server.tool( "get_pull_request_review_comments", "Get review comments (line-by-line code comments) for a specific pull request.", { owner: z.string().describe("Repository owner"), repo: z.string().describe("Repository name"), pullNumber: z.number().describe("Pull request number"), sort: z .enum(["created", "updated"]) .optional() .describe("Sort comments by created or updated time"), direction: z.enum(["asc", "desc"]).optional().describe("Sort direction"), since: z .string() .optional() .describe( "Only show comments updated after this time (ISO 8601 format)", ), per_page: z .number() .optional() .default(10) .describe("Results per page (default 10, max 100)"), page: z .number() .optional() .default(1) .describe("Page number (default 1)"), }, async ({ owner, repo, pullNumber, sort, direction, since, per_page, page, }) => { try { const response = await octokit.rest.pulls.listReviewComments({ owner, repo, pull_number: pullNumber, sort, direction, since, per_page, page, }) const comments = response.data if (comments.length === 0) { return { content: [ { type: "text", text: "No review comments found for this pull request.", }, ], } } // Format as clean markdown let markdown = `# Review Comments for Pull Request #${pullNumber}\n\n` markdown += `Showing ${comments.length} review comment(s) - Page ${page}\n` if (comments.length === per_page) { markdown += `*Note: More results may be available. Use 'page' parameter to see next page.*\n` } markdown += `\n` comments.forEach((comment, index) => { markdown += `## Comment ${index + 1}\n\n` markdown += `- **Author:** ${comment.user?.login || "Unknown"}\n` markdown += `- **File:** ${comment.path}\n` if (comment.line) { markdown += `- **Line:** ${comment.line}\n` } if (comment.start_line && comment.start_line !== comment.line) { markdown += `- **Lines:** ${comment.start_line}-${comment.line}\n` } markdown += `- **Side:** ${comment.side || "RIGHT"}\n` markdown += `- **Created:** ${new Date(comment.created_at).toLocaleDateString()}\n` if (comment.updated_at !== comment.created_at) { markdown += `- **Updated:** ${new Date(comment.updated_at).toLocaleDateString()}\n` } if (comment.commit_id) { markdown += `- **Commit:** ${comment.commit_id.substring(0, 7)}\n` } if (comment.in_reply_to_id) { markdown += `- **Reply to:** Comment #${comment.in_reply_to_id}\n` } markdown += `\n**Comment:**\n${comment.body}\n` if (comment.html_url) { markdown += `\n**URL:** ${comment.html_url}\n` } markdown += `\n---\n\n` }) return { content: [{ type: "text", text: markdown }], } } catch (e: any) { return { content: [{ type: "text", text: `Error: ${e.message}` }], } } }, )