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
6 changes: 3 additions & 3 deletions src/git/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,11 @@ Please note that mcp-server-git is currently in early development. The functiona
- `branch_name` (string): Name of branch to checkout
- Returns: Confirmation of branch switch
11. `git_show`
- Shows the contents of a commit
- Shows the contents of a commit, or of a file or directory at a revision
- Inputs:
- `repo_path` (string): Path to Git repository
- `revision` (string): The revision (commit hash, branch name, tag) to show
- Returns: Contents of the specified commit
- `revision` (string): The revision (commit hash, branch name, tag) or object spec (`HEAD:path/to/file`) to show
- Returns: Contents of the specified commit, file content, or directory listing

12. `git_branch`
- List Git branches
Expand Down
9 changes: 8 additions & 1 deletion src/git/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,13 @@ def git_show(repo: git.Repo, revision: str) -> str:
# even if a malicious ref with that name exists (e.g. via filesystem manipulation)
if revision.startswith("-"):
raise BadName(f"Invalid revision: '{revision}' - cannot start with '-'")
obj = repo.rev_parse(revision)
if isinstance(obj, git.Blob):
return obj.data_stream.read().decode("utf-8", errors="replace")
if isinstance(obj, git.Tree):
return "\n".join(
f"{item.name}/" if isinstance(item, git.Tree) else item.name for item in obj
)
commit = repo.commit(revision)
output = [
f"Commit: {commit.hexsha!r}\n"
Expand Down Expand Up @@ -416,7 +423,7 @@ async def list_tools() -> list[Tool]:
),
Tool(
name=GitTools.SHOW,
description="Shows the contents of a commit",
description="Shows the contents of a commit, or of a file or directory given as <revision>:<path>",
inputSchema=GitShow.model_json_schema(),
annotations=ToolAnnotations(
readOnlyHint=True,
Expand Down
22 changes: 22 additions & 0 deletions src/git/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,28 @@ def test_git_show_initial_commit(test_repository):
assert "initial commit" in result
assert "test.txt" in result

def test_git_show_blob_object_spec(test_repository):
file_path = Path(test_repository.working_dir) / "logic" / "infos.py"
file_path.parent.mkdir()
file_path.write_text("print('infos')\n")
test_repository.index.add(["logic/infos.py"])
test_repository.index.commit("add infos")

result = git_show(test_repository, "HEAD:logic/infos.py")

assert result == "print('infos')\n"

def test_git_show_tree_object_spec(test_repository):
file_path = Path(test_repository.working_dir) / "logic" / "infos.py"
file_path.parent.mkdir()
file_path.write_text("print('infos')\n")
test_repository.index.add(["logic/infos.py"])
test_repository.index.commit("add infos")

result = git_show(test_repository, "HEAD:")

assert result == "logic/\ntest.txt"


# Tests for validate_repo_path (repository scoping security fix)

Expand Down
Loading