Skip to content

Fix mcp-server-git unit tests, update build instructions #2470

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion src/git/.python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
3.13
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we revert this version bump if its not really needed?

50 changes: 20 additions & 30 deletions src/git/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,13 +287,29 @@ help you debug any issues.

## Development

If you are doing local development, there are two ways to test your changes:
### Building

1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions.
[`uv`](https://docs.astral.sh/uv/) is used for development.

2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`:
Start by creating a fresh virtual environment:

### Docker
```bash
uv venv
source .venv/bin/activate
```
To run the tests, type `uv run pytest`, to run the server from source use `uv run src/mcp_server_git/`.

To build, type `uv build`. You can then now run `mcp-server-git` command directly. Open with the inspector using `npx @modelcontextprotocol/inspector@latest mcp-server-git`.

To specify the Python version type `uv python pin <version>` (useful if you want to use a more recent version than the default).

To create the Docker container use

```bash
docker build -t mcp/git .
```

An example showing how to run via the Docker container is below:

```json
{
Expand All @@ -314,32 +330,6 @@ If you are doing local development, there are two ways to test your changes:
}
```

### UVX
```json
{
"mcpServers": {
"git": {
"command": "uv",
"args": [
"--directory",
"/<path to mcp-servers>/mcp-servers/src/git",
"run",
"mcp-server-git"
]
}
}
}
```

## Build

Docker build:

```bash
cd src/git
docker build -t mcp/git .
```

## License

This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository.
10 changes: 5 additions & 5 deletions src/git/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "mcp-server-git"
version = "0.6.2"
description = "A Model Context Protocol server providing tools to read, search, and manipulate Git repositories programmatically via LLMs"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.13"
authors = [{ name = "Anthropic, PBC." }]
maintainers = [{ name = "David Soria Parra", email = "davidsp@anthropic.com" }]
keywords = ["git", "mcp", "llm", "automation"]
Expand All @@ -16,10 +16,10 @@ classifiers = [
"Programming Language :: Python :: 3.10",
]
dependencies = [
"click>=8.1.7",
"gitpython>=3.1.43",
"mcp>=1.0.0",
"pydantic>=2.0.0",
"click>=8.2.2",
"gitpython>=3.1.45",
"mcp>=1.12.3",
"pydantic>=2.11.7",
]

[project.scripts]
Expand Down
6 changes: 5 additions & 1 deletion src/git/src/mcp_server_git/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,11 @@ def git_show(repo: git.Repo, revision: str) -> str:
diff = commit.diff(git.NULL_TREE, create_patch=True)
for d in diff:
output.append(f"\n--- {d.a_path}\n+++ {d.b_path}\n")
output.append(d.diff.decode('utf-8'))
if d.diff is not None:
if isinstance(d.diff, bytes):
output.append(d.diff.decode('utf-8'))
else:
output.append(d.diff)
return "".join(output)

def git_branch(repo: git.Repo, branch_type: str, contains: str | None = None, not_contains: str | None = None) -> str:
Expand Down
14 changes: 10 additions & 4 deletions src/git/tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,34 @@ def test_git_branch_all(test_repository):
assert "new-branch-all" in result

def test_git_branch_contains(test_repository):
# Get the default branch name before creating new branches
default_branch = test_repository.active_branch.name

# Create a new branch and commit to it
test_repository.git.checkout("-b", "feature-branch")
Path(test_repository.working_dir / Path("feature.txt")).write_text("feature content")
test_repository.index.add(["feature.txt"])
commit = test_repository.index.commit("feature commit")
test_repository.git.checkout("master")
test_repository.git.checkout(default_branch)

result = git_branch(test_repository, "local", contains=commit.hexsha)
assert "feature-branch" in result
assert "master" not in result
assert default_branch not in result

def test_git_branch_not_contains(test_repository):
# Get the default branch name before creating new branches
default_branch = test_repository.active_branch.name

# Create a new branch and commit to it
test_repository.git.checkout("-b", "another-feature-branch")
Path(test_repository.working_dir / Path("another_feature.txt")).write_text("another feature content")
test_repository.index.add(["another_feature.txt"])
commit = test_repository.index.commit("another feature commit")
test_repository.git.checkout("master")
test_repository.git.checkout(default_branch)

result = git_branch(test_repository, "local", not_contains=commit.hexsha)
assert "another-feature-branch" not in result
assert "master" in result
assert default_branch in result

def test_git_add_all_files(test_repository):
file_path = Path(test_repository.working_dir) / "all_file.txt"
Expand Down
Loading