diff --git a/src/git/README.md b/src/git/README.md index a922fdecc1..b9a861d70e 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -94,6 +94,15 @@ Please note that mcp-server-git is currently in early development. The functiona - `not_contains` (string, optional): The commit sha that branch should NOT contain. Do not pass anything to this param if no commit sha is specified - Returns: List of branches +13. `git_log_detail` + - Shows the commit logs with diffs + - Inputs: + - `repo_path` (string): Path to Git repository + - `max_count` (number, optional): Maximum number of commits to show (default: 10) + - `start_timestamp` (string, optional): Start timestamp for filtering commits. Accepts ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024') + - `end_timestamp` (string, optional): End timestamp for filtering commits. Accepts ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024') + - Returns: The git log output, including the diff for each commit + ## Installation ### Using uv (recommended) diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index 9950da66ea..7c7de34ef1 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -57,6 +57,18 @@ class GitLog(BaseModel): description="End timestamp for filtering commits. Accepts: ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024')" ) +class GitLogDetail(BaseModel): + repo_path: str + max_count: int = 10 + start_timestamp: Optional[str] = Field( + None, + description="Start timestamp for filtering commits. Accepts: ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024')" + ) + end_timestamp: Optional[str] = Field( + None, + description="End timestamp for filtering commits. Accepts: ISO 8601 format (e.g., '2024-01-15T14:30:25'), relative dates (e.g., '2 weeks ago', 'yesterday'), or absolute dates (e.g., '2024-01-15', 'Jan 15 2024')" + ) + class GitCreateBranch(BaseModel): repo_path: str branch_name: str @@ -103,6 +115,7 @@ class GitTools(str, Enum): CREATE_BRANCH = "git_create_branch" CHECKOUT = "git_checkout" SHOW = "git_show" + LOG_DETAIL = "git_log_detail" BRANCH = "git_branch" @@ -169,6 +182,15 @@ def git_log(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] ) return log +def git_log_detail(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] = None, end_timestamp: Optional[str] = None) -> str: + args = [f'--max-count={max_count}', '--patch-with-stat'] + if start_timestamp: + args.extend(['--since', start_timestamp]) + if end_timestamp: + args.extend(['--until', end_timestamp]) + + return repo.git.log(*args) + def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str: if base_branch: base = repo.references[base_branch] @@ -287,6 +309,11 @@ async def list_tools() -> list[Tool]: description="Shows the commit logs", inputSchema=GitLog.model_json_schema(), ), + Tool( + name=GitTools.LOG_DETAIL, + description="Shows the commit logs with diffs", + inputSchema=GitLogDetail.model_json_schema(), + ), Tool( name=GitTools.CREATE_BRANCH, description="Creates a new branch from an optional base branch", @@ -409,7 +436,19 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]: type="text", text="Commit history:\n" + "\n".join(log) )] - + + case GitTools.LOG_DETAIL: + log = git_log_detail( + repo, + arguments.get("max_count", 10), + arguments.get("start_timestamp"), + arguments.get("end_timestamp"), + ) + return [TextContent( + type="text", + text=f"Commit logs with diffs:\n{log}" + )] + case GitTools.CREATE_BRANCH: result = git_create_branch( repo, diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index 5949fd68d2..d2772b6fb3 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -1,7 +1,7 @@ import pytest from pathlib import Path import git -from mcp_server_git.server import git_checkout, git_branch, git_add, git_status +from mcp_server_git.server import git_checkout, git_branch, git_add, git_status, git_log_detail import shutil @pytest.fixture @@ -97,3 +97,13 @@ def test_git_status(test_repository): assert result is not None assert "On branch" in result or "branch" in result.lower() + +def test_git_log_detail(test_repository): + initial_commit = test_repository.head.commit + result = git_log_detail(test_repository, max_count=1) + + assert initial_commit.hexsha in result + assert "initial commit" in result + assert "test.txt" in result + assert "1 file changed, 1 insertion(+)" in result + assert "+test" in result