mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-21 21:35:15 +02:00
feat(git): add date-based commit log retrieval functions (#2057)
Co-authored-by: adam jones <domdomegg+git@gmail.com>
This commit is contained in:
committed by
GitHub
parent
338d8af7a6
commit
09adff0b29
@@ -57,10 +57,12 @@ Please note that mcp-server-git is currently in early development. The functiona
|
|||||||
- Returns: Confirmation of reset operation
|
- Returns: Confirmation of reset operation
|
||||||
|
|
||||||
8. `git_log`
|
8. `git_log`
|
||||||
- Shows the commit logs
|
- Shows the commit logs with optional date filtering
|
||||||
- Inputs:
|
- Inputs:
|
||||||
- `repo_path` (string): Path to Git repository
|
- `repo_path` (string): Path to Git repository
|
||||||
- `max_count` (number, optional): Maximum number of commits to show (default: 10)
|
- `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: Array of commit entries with hash, author, date, and message
|
- Returns: Array of commit entries with hash, author, date, and message
|
||||||
|
|
||||||
9. `git_create_branch`
|
9. `git_create_branch`
|
||||||
|
|||||||
@@ -48,6 +48,14 @@ class GitReset(BaseModel):
|
|||||||
class GitLog(BaseModel):
|
class GitLog(BaseModel):
|
||||||
repo_path: str
|
repo_path: str
|
||||||
max_count: int = 10
|
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):
|
class GitCreateBranch(BaseModel):
|
||||||
repo_path: str
|
repo_path: str
|
||||||
@@ -83,6 +91,7 @@ class GitBranch(BaseModel):
|
|||||||
description="The commit sha that branch should NOT contain. Do not pass anything to this param if no commit sha is specified",
|
description="The commit sha that branch should NOT contain. Do not pass anything to this param if no commit sha is specified",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class GitTools(str, Enum):
|
class GitTools(str, Enum):
|
||||||
STATUS = "git_status"
|
STATUS = "git_status"
|
||||||
DIFF_UNSTAGED = "git_diff_unstaged"
|
DIFF_UNSTAGED = "git_diff_unstaged"
|
||||||
@@ -125,17 +134,41 @@ def git_reset(repo: git.Repo) -> str:
|
|||||||
repo.index.reset()
|
repo.index.reset()
|
||||||
return "All staged changes reset"
|
return "All staged changes reset"
|
||||||
|
|
||||||
def git_log(repo: git.Repo, max_count: int = 10) -> list[str]:
|
def git_log(repo: git.Repo, max_count: int = 10, start_timestamp: Optional[str] = None, end_timestamp: Optional[str] = None) -> list[str]:
|
||||||
commits = list(repo.iter_commits(max_count=max_count))
|
if start_timestamp or end_timestamp:
|
||||||
log = []
|
# Use git log command with date filtering
|
||||||
for commit in commits:
|
args = []
|
||||||
log.append(
|
if start_timestamp:
|
||||||
f"Commit: {commit.hexsha!r}\n"
|
args.extend(['--since', start_timestamp])
|
||||||
f"Author: {commit.author!r}\n"
|
if end_timestamp:
|
||||||
f"Date: {commit.authored_datetime}\n"
|
args.extend(['--until', end_timestamp])
|
||||||
f"Message: {commit.message!r}\n"
|
args.extend(['--format=%H%n%an%n%ad%n%s%n'])
|
||||||
)
|
|
||||||
return log
|
log_output = repo.git.log(*args).split('\n')
|
||||||
|
|
||||||
|
log = []
|
||||||
|
# Process commits in groups of 4 (hash, author, date, message)
|
||||||
|
for i in range(0, len(log_output), 4):
|
||||||
|
if i + 3 < len(log_output) and len(log) < max_count:
|
||||||
|
log.append(
|
||||||
|
f"Commit: {log_output[i]}\n"
|
||||||
|
f"Author: {log_output[i+1]}\n"
|
||||||
|
f"Date: {log_output[i+2]}\n"
|
||||||
|
f"Message: {log_output[i+3]}\n"
|
||||||
|
)
|
||||||
|
return log
|
||||||
|
else:
|
||||||
|
# Use existing logic for simple log without date filtering
|
||||||
|
commits = list(repo.iter_commits(max_count=max_count))
|
||||||
|
log = []
|
||||||
|
for commit in commits:
|
||||||
|
log.append(
|
||||||
|
f"Commit: {commit.hexsha!r}\n"
|
||||||
|
f"Author: {commit.author!r}\n"
|
||||||
|
f"Date: {commit.authored_datetime}\n"
|
||||||
|
f"Message: {commit.message!r}\n"
|
||||||
|
)
|
||||||
|
return log
|
||||||
|
|
||||||
def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str:
|
def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str:
|
||||||
if base_branch:
|
if base_branch:
|
||||||
@@ -203,6 +236,7 @@ def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, no
|
|||||||
|
|
||||||
return branch_info
|
return branch_info
|
||||||
|
|
||||||
|
|
||||||
async def serve(repository: Path | None) -> None:
|
async def serve(repository: Path | None) -> None:
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -283,6 +317,7 @@ async def serve(repository: Path | None) -> None:
|
|||||||
name=GitTools.BRANCH,
|
name=GitTools.BRANCH,
|
||||||
description="List Git branches",
|
description="List Git branches",
|
||||||
inputSchema=GitBranch.model_json_schema(),
|
inputSchema=GitBranch.model_json_schema(),
|
||||||
|
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -380,8 +415,14 @@ async def serve(repository: Path | None) -> None:
|
|||||||
text=result
|
text=result
|
||||||
)]
|
)]
|
||||||
|
|
||||||
|
# Update the LOG case:
|
||||||
case GitTools.LOG:
|
case GitTools.LOG:
|
||||||
log = git_log(repo, arguments.get("max_count", 10))
|
log = git_log(
|
||||||
|
repo,
|
||||||
|
arguments.get("max_count", 10),
|
||||||
|
arguments.get("start_timestamp"),
|
||||||
|
arguments.get("end_timestamp")
|
||||||
|
)
|
||||||
return [TextContent(
|
return [TextContent(
|
||||||
type="text",
|
type="text",
|
||||||
text="Commit history:\n" + "\n".join(log)
|
text="Commit history:\n" + "\n".join(log)
|
||||||
|
|||||||
Reference in New Issue
Block a user