generate_commit_message
Generate Conventional Commit messages from staged git changes. Analyzes diffs to create properly formatted commit messages following conventional commit standards.
Instructions
Prepare a structured analysis and instruction block for generating a Conventional Commit message from staged git changes only.
Behavior: - Validates the repository path and operates on the provided repo or CWD. - Collects staged diff, porcelain status, and a name-status summary. - Incorporates optional user preferences for commit_type and scope. - Returns a single formatted string that includes context plus strict output instructions for an LLM to produce a Conventional Commit.
Args: repo_path: Optional path to the target git repository. If not provided, uses the current working directory. commit_type: Optional commit type (feat, fix, docs, style, refactor, perf, build, ci, test, chore, revert) scope: Optional scope of the change
Returns: A formatted prompt containing git change context and clear output rules for generating a Conventional Commit message
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| repo_path | No | ||
| commit_type | No | ||
| scope | No |
Implementation Reference
- Core implementation of the generate_commit_message MCP tool handler. Validates git repo, retrieves staged changes (diff, status, name-status), incorporates optional type/scope, and returns a detailed LLM prompt enforcing Conventional Commit format with strict output rules.@mcp.tool() def generate_commit_message( repo_path: Optional[str] = None, commit_type: Optional[str] = None, scope: Optional[str] = None, ) -> str: """ Prepare a structured analysis and instruction block for generating a Conventional Commit message from staged git changes only. Behavior: - Validates the repository path and operates on the provided repo or CWD. - Collects staged diff, porcelain status, and a name-status summary. - Incorporates optional user preferences for commit_type and scope. - Returns a single formatted string that includes context plus strict output instructions for an LLM to produce a Conventional Commit. Args: repo_path: Optional path to the target git repository. If not provided, uses the current working directory. commit_type: Optional commit type (feat, fix, docs, style, refactor, perf, build, ci, test, chore, revert) scope: Optional scope of the change Returns: A formatted prompt containing git change context and clear output rules for generating a Conventional Commit message """ try: valid_repo_path = _get_valid_repo_path(repo_path) if not valid_repo_path: return f"Path '{repo_path or os.getcwd()}' is not a valid git repository." cwd = valid_repo_path # Get staged changes diff_result = subprocess.run( ["git", "diff", "--cached"], capture_output=True, text=True, check=True, cwd=cwd, ) if not diff_result.stdout.strip(): return "No staged changes found. Please stage your changes with 'git add' first." # Get git status for context status_result = subprocess.run( ["git", "status", "--porcelain"], capture_output=True, text=True, check=True, cwd=cwd, ) # Get list of changed files for better analysis files_result = subprocess.run( ["git", "diff", "--cached", "--name-status"], capture_output=True, text=True, check=True, cwd=cwd, ) diff_preview = diff_result.stdout[:1500] analysis = textwrap.dedent(f""" ## Git Change Analysis for Conventional Commit Message ### Changed Files: {files_result.stdout} ### File Status Summary: {status_result.stdout} ### Diff Preview (first 1500 chars): {diff_preview} ### User Preferences: - Requested commit type: {commit_type or "auto-detect based on changes"} - Requested scope: {scope or "auto-detect based on files changed"} ### Task Write a Conventional Commit message for the STAGED changes only. ### Output format (return ONLY this) First line: type(scope): subject Add blank line before body Body paragraphs, each line <= 72 chars; bullets in body starting with "- " Optional footers (each on its own line), e.g.: BREAKING CHANGE: description ### Example generated commit message feat(core): add new feature - Implement new feature in core module - Update documentation BREAKING CHANGE: this change removes the old API method ### Rules - If commit_type or scope is provided above, USE THEM as-is. - If not provided, infer an appropriate type and a concise scope (or omit scope if unclear). - Subject: use imperative mood, start lowercase, no trailing period, <= 50 chars. - Body: use imperative mood (e.g. Update, Add etc.); explain WHAT and WHY, wrap at 72 chars; omit if subject suffices. - Use domain-specific terms; avoid generic phrases. - Do NOT mention "staged", "diff", or counts of files/lines. - Do NOT include markdown headers, code fences, or extra commentary. - Prefer a broad scope if many files; derive scope from top-level dirs when clear. - If there is a breaking change (e.g., API removal/rename), add a BREAKING CHANGE footer. - Keep the response to ONLY the commit message in the format above. ### Common types feat, fix, docs, style, refactor, perf, build, ci, test, chore, revert """) return analysis.strip() except subprocess.CalledProcessError as e: error_msg = e.stderr or e.stdout or str(e) return f"Git command failed: {error_msg}" except FileNotFoundError: return "Git is not installed or not found in PATH" except OSError as e: return f"OS error occurred: {str(e)}"
- Input/output schema for the tool defined by function signature and comprehensive docstring describing parameters, behavior, and return value.def generate_commit_message( repo_path: Optional[str] = None, commit_type: Optional[str] = None, scope: Optional[str] = None, ) -> str: """ Prepare a structured analysis and instruction block for generating a Conventional Commit message from staged git changes only. Behavior: - Validates the repository path and operates on the provided repo or CWD. - Collects staged diff, porcelain status, and a name-status summary. - Incorporates optional user preferences for commit_type and scope. - Returns a single formatted string that includes context plus strict output instructions for an LLM to produce a Conventional Commit. Args: repo_path: Optional path to the target git repository. If not provided, uses the current working directory. commit_type: Optional commit type (feat, fix, docs, style, refactor, perf, build, ci, test, chore, revert) scope: Optional scope of the change Returns: A formatted prompt containing git change context and clear output rules for generating a Conventional Commit message """
- src/mcp_git_commit_generator/server.py:35-35 (registration)FastMCP decorator that registers generate_commit_message as an MCP tool on the mcp server instance.@mcp.tool()
- Utility function called by the handler to resolve and validate the git repository path, handling tilde expansion and checking for .git directory.def _get_valid_repo_path(repo_path: Optional[str]) -> Optional[str]: """ Resolve and validate the git repository path. Returns the valid repo path if valid, otherwise None. """ logger = logging.getLogger(__name__) # Resolve user tilde and symlinks to a canonical path resolved = ( os.path.realpath(os.path.expanduser(repo_path)) if repo_path else os.getcwd() ) logger.info("[get_valid_repo_path] Resolved repository path: %s", resolved) if not os.path.isdir(resolved) or not os.path.exists( os.path.join(resolved, ".git") ): return None return resolved