Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/git/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
41 changes: 40 additions & 1 deletion src/git/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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,
Expand Down
12 changes: 11 additions & 1 deletion src/git/tests/test_server.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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