mirror of
https://github.com/block/goose.git
synced 2026-06-02 06:19:33 +02:00
Add a code review step which uses a short-lived provider token (#7932)
This commit is contained in:
Executable
+84
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = ["mcp"]
|
||||
# ///
|
||||
"""MCP server for collecting PR review comments and conclusion."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from mcp.server.fastmcp import FastMCP
|
||||
|
||||
server = FastMCP("pr-review")
|
||||
|
||||
output_dir = Path(os.environ.get("REVIEW_OUTPUT_DIR", "/tmp"))
|
||||
|
||||
|
||||
def _append_comment(comment: dict) -> int:
|
||||
"""Append a comment to the comments file and return the new total."""
|
||||
comments_file = output_dir / "comments.json"
|
||||
comments = json.loads(comments_file.read_text()) if comments_file.exists() else []
|
||||
comments.append(comment)
|
||||
comments_file.write_text(json.dumps(comments, indent=2))
|
||||
return len(comments)
|
||||
|
||||
|
||||
@server.tool()
|
||||
def add_comment(
|
||||
path: str,
|
||||
line: int,
|
||||
body: str,
|
||||
suggestion: str | None = None,
|
||||
side: str = "RIGHT",
|
||||
start_line: int | None = None,
|
||||
) -> str:
|
||||
"""Add a review comment on a specific line in the PR diff.
|
||||
|
||||
Args:
|
||||
path: The relative file path in the repository (e.g. "src/main.rs").
|
||||
line: The line number in the file that the comment applies to.
|
||||
For added or modified lines, use the line number in the new version of the file (side=RIGHT).
|
||||
For deleted lines, use the line number in the old version of the file (side=LEFT).
|
||||
body: The review comment text (Markdown supported).
|
||||
suggestion: Optional replacement code for the line(s). When provided, GitHub renders an
|
||||
"Apply suggestion" button the author can click. The suggestion replaces the
|
||||
entire line (or range if start_line is set).
|
||||
side: Which version of the file the line number refers to.
|
||||
"RIGHT" for the new/modified version (default), "LEFT" for the old/deleted version.
|
||||
start_line: For multi-line comments, the first line of the range. When set, `line` is the last line.
|
||||
"""
|
||||
if suggestion is not None:
|
||||
body = (
|
||||
f"{body}\n\n```suggestion\n{suggestion}\n```"
|
||||
if body
|
||||
else f"```suggestion\n{suggestion}\n```"
|
||||
)
|
||||
|
||||
comment = {"path": path, "line": line, "side": side, "body": body}
|
||||
if start_line is not None:
|
||||
comment["start_line"] = start_line
|
||||
comment["start_side"] = side
|
||||
|
||||
total = _append_comment(comment)
|
||||
return f"Comment added on {path}:{line} ({total} total)."
|
||||
|
||||
|
||||
@server.tool()
|
||||
def finish_review(body: str = "") -> str:
|
||||
"""Finish the review.
|
||||
|
||||
Args:
|
||||
body: Optional top-level review body (Markdown supported). Only include if it
|
||||
contains information not already covered by inline comments. Most reviews
|
||||
should leave this empty.
|
||||
"""
|
||||
conclusion = {"body": body, "event": "COMMENT"}
|
||||
conclusion_file = output_dir / "conclusion.json"
|
||||
conclusion_file.write_text(json.dumps(conclusion, indent=2))
|
||||
return "Review finished."
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
server.run(transport="stdio")
|
||||
Reference in New Issue
Block a user