Skip to content

Commit 09adff0

Browse files
Berg-itdomdomegg
andauthored
feat(git): add date-based commit log retrieval functions (#2057)
Co-authored-by: adam jones <domdomegg+git@gmail.com>
1 parent 338d8af commit 09adff0

2 files changed

Lines changed: 58 additions & 15 deletions

File tree

src/git/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ Please note that mcp-server-git is currently in early development. The functiona
5757
- Returns: Confirmation of reset operation
5858

5959
8. `git_log`
60-
- Shows the commit logs
60+
- Shows the commit logs with optional date filtering
6161
- Inputs:
6262
- `repo_path` (string): Path to Git repository
6363
- `max_count` (number, optional): Maximum number of commits to show (default: 10)
64+
- `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')
65+
- `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')
6466
- Returns: Array of commit entries with hash, author, date, and message
6567

6668
9. `git_create_branch`

src/git/src/mcp_server_git/server.py

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ class GitReset(BaseModel):
4848
class GitLog(BaseModel):
4949
repo_path: str
5050
max_count: int = 10
51+
start_timestamp: Optional[str] = Field(
52+
None,
53+
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')"
54+
)
55+
end_timestamp: Optional[str] = Field(
56+
None,
57+
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')"
58+
)
5159

5260
class GitCreateBranch(BaseModel):
5361
repo_path: str
@@ -83,6 +91,7 @@ class GitBranch(BaseModel):
8391
description="The commit sha that branch should NOT contain. Do not pass anything to this param if no commit sha is specified",
8492
)
8593

94+
8695
class GitTools(str, Enum):
8796
STATUS = "git_status"
8897
DIFF_UNSTAGED = "git_diff_unstaged"
@@ -125,17 +134,41 @@ def git_reset(repo: git.Repo) -> str:
125134
repo.index.reset()
126135
return "All staged changes reset"
127136

128-
def git_log(repo: git.Repo, max_count: int = 10) -> list[str]:
129-
commits = list(repo.iter_commits(max_count=max_count))
130-
log = []
131-
for commit in commits:
132-
log.append(
133-
f"Commit: {commit.hexsha!r}\n"
134-
f"Author: {commit.author!r}\n"
135-
f"Date: {commit.authored_datetime}\n"
136-
f"Message: {commit.message!r}\n"
137-
)
138-
return log
137+
def git_log(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] = None, end_timestamp: Optional[str] = None) -> list[str]:
138+
if start_timestamp or end_timestamp:
139+
# Use git log command with date filtering
140+
args = []
141+
if start_timestamp:
142+
args.extend(['--since', start_timestamp])
143+
if end_timestamp:
144+
args.extend(['--until', end_timestamp])
145+
args.extend(['--format=%H%n%an%n%ad%n%s%n'])
146+
147+
log_output = repo.git.log(*args).split('\n')
148+
149+
log = []
150+
# Process commits in groups of 4 (hash, author, date, message)
151+
for i in range(0, len(log_output), 4):
152+
if i + 3 < len(log_output) and len(log) < max_count:
153+
log.append(
154+
f"Commit: {log_output[i]}\n"
155+
f"Author: {log_output[i+1]}\n"
156+
f"Date: {log_output[i+2]}\n"
157+
f"Message: {log_output[i+3]}\n"
158+
)
159+
return log
160+
else:
161+
# Use existing logic for simple log without date filtering
162+
commits = list(repo.iter_commits(max_count=max_count))
163+
log = []
164+
for commit in commits:
165+
log.append(
166+
f"Commit: {commit.hexsha!r}\n"
167+
f"Author: {commit.author!r}\n"
168+
f"Date: {commit.authored_datetime}\n"
169+
f"Message: {commit.message!r}\n"
170+
)
171+
return log
139172

140173
def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str:
141174
if base_branch:
@@ -203,6 +236,7 @@ def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, no
203236

204237
return branch_info
205238

239+
206240
async def serve(repository: Path | None) -> None:
207241
logger = logging.getLogger(__name__)
208242

@@ -283,6 +317,7 @@ async def list_tools() -> list[Tool]:
283317
name=GitTools.BRANCH,
284318
description="List Git branches",
285319
inputSchema=GitBranch.model_json_schema(),
320+
286321
)
287322
]
288323

@@ -380,13 +415,19 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
380415
text=result
381416
)]
382417

418+
# Update the LOG case:
383419
case GitTools.LOG:
384-
log = git_log(repo, arguments.get("max_count", 10))
420+
log = git_log(
421+
repo,
422+
arguments.get("max_count", 10),
423+
arguments.get("start_timestamp"),
424+
arguments.get("end_timestamp")
425+
)
385426
return [TextContent(
386427
type="text",
387428
text="Commit history:\n" + "\n".join(log)
388429
)]
389-
430+
390431
case GitTools.CREATE_BRANCH:
391432
result = git_create_branch(
392433
repo,
@@ -423,7 +464,7 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]:
423464
type="text",
424465
text=result
425466
)]
426-
467+
427468
case _:
428469
raise ValueError(f"Unknown tool: {name}")
429470

0 commit comments

Comments
 (0)