Skip to content

Pr

pr

GitPRTool — create GitHub pull requests via gh CLI.

GitPRTool

Bases: AXMTool

Create a GitHub pull request with optional auto-merge.

Registered as git_pr via axm.tools entry point.

Source code in packages/axm-git/src/axm_git/tools/pr.py
Python
class GitPRTool(AXMTool):
    """Create a GitHub pull request with optional auto-merge.

    Registered as ``git_pr`` via axm.tools entry point.
    """

    @property
    def name(self) -> str:
        """Tool name used for MCP registration."""
        return "git_pr"

    def execute(  # type: ignore[override]
        self,
        *,
        title: str,
        body: str | None = None,
        base: str = "main",
        auto_merge: bool = True,
        path: str = ".",
        **kwargs: object,
    ) -> ToolResult:
        """Create a GitHub pull request.

        Args:
            title: PR title (required).
            body: PR body/description.
            base: Base branch (default ``main``).
            auto_merge: Enable auto-merge with squash (default ``True``).
            path: Repository path.

        Returns:
            ToolResult with ``pr_url`` and ``pr_number`` on success.
        """
        resolved = Path(path).resolve()

        try:
            # 1. Verify this is a git repo.
            check = run_git(["rev-parse", "--git-dir"], resolved)
            if check.returncode != 0:
                return not_a_repo_error(check.stderr, resolved)

            # 2. Check gh availability.
            if not gh_available():
                return ToolResult(
                    success=False,
                    error="gh CLI not available",
                )

            # 3. Create the PR.
            create_args = ["pr", "create", "--title", title, "--base", base]
            if body:
                create_args.extend(["--body", body])

            result = run_gh(create_args, resolved)
            if result.returncode != 0:
                return ToolResult(
                    success=False,
                    error=result.stderr.strip() or result.stdout.strip(),
                )

            pr_url = result.stdout.strip()
            pr_number = pr_url.rstrip("/").rsplit("/", maxsplit=1)[-1]

            # 4. Enable auto-merge if requested.
            if auto_merge:
                merge_result = run_gh(
                    ["pr", "merge", pr_number, "--auto", "--squash"],
                    resolved,
                )
                return ToolResult(
                    success=True,
                    data={
                        "pr_url": pr_url,
                        "pr_number": pr_number,
                        "auto_merge": merge_result.returncode == 0,
                    },
                )
        except subprocess.TimeoutExpired as exc:
            return timeout_error_result(exc)

        return ToolResult(
            success=True,
            data={
                "pr_url": pr_url,
                "pr_number": pr_number,
                "auto_merge": False,
            },
        )
name property

Tool name used for MCP registration.

execute(*, title, body=None, base='main', auto_merge=True, path='.', **kwargs)

Create a GitHub pull request.

Parameters:

Name Type Description Default
title str

PR title (required).

required
body str | None

PR body/description.

None
base str

Base branch (default main).

'main'
auto_merge bool

Enable auto-merge with squash (default True).

True
path str

Repository path.

'.'

Returns:

Type Description
ToolResult

ToolResult with pr_url and pr_number on success.

Source code in packages/axm-git/src/axm_git/tools/pr.py
Python
def execute(  # type: ignore[override]
    self,
    *,
    title: str,
    body: str | None = None,
    base: str = "main",
    auto_merge: bool = True,
    path: str = ".",
    **kwargs: object,
) -> ToolResult:
    """Create a GitHub pull request.

    Args:
        title: PR title (required).
        body: PR body/description.
        base: Base branch (default ``main``).
        auto_merge: Enable auto-merge with squash (default ``True``).
        path: Repository path.

    Returns:
        ToolResult with ``pr_url`` and ``pr_number`` on success.
    """
    resolved = Path(path).resolve()

    try:
        # 1. Verify this is a git repo.
        check = run_git(["rev-parse", "--git-dir"], resolved)
        if check.returncode != 0:
            return not_a_repo_error(check.stderr, resolved)

        # 2. Check gh availability.
        if not gh_available():
            return ToolResult(
                success=False,
                error="gh CLI not available",
            )

        # 3. Create the PR.
        create_args = ["pr", "create", "--title", title, "--base", base]
        if body:
            create_args.extend(["--body", body])

        result = run_gh(create_args, resolved)
        if result.returncode != 0:
            return ToolResult(
                success=False,
                error=result.stderr.strip() or result.stdout.strip(),
            )

        pr_url = result.stdout.strip()
        pr_number = pr_url.rstrip("/").rsplit("/", maxsplit=1)[-1]

        # 4. Enable auto-merge if requested.
        if auto_merge:
            merge_result = run_gh(
                ["pr", "merge", pr_number, "--auto", "--squash"],
                resolved,
            )
            return ToolResult(
                success=True,
                data={
                    "pr_url": pr_url,
                    "pr_number": pr_number,
                    "auto_merge": merge_result.returncode == 0,
                },
            )
    except subprocess.TimeoutExpired as exc:
        return timeout_error_result(exc)

    return ToolResult(
        success=True,
        data={
            "pr_url": pr_url,
            "pr_number": pr_number,
            "auto_merge": False,
        },
    )