From 6135c62c699fa39f71e4d33c8c226c57128dc1c3 Mon Sep 17 00:00:00 2001 From: Mike Gehard Date: Sat, 30 Nov 2024 19:22:13 -0500 Subject: [PATCH 1/5] Add git branch creation functionality --- src/git/src/mcp_server_git/server.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index fe1e3f59..85f48e0e 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -39,6 +39,11 @@ class GitLog(BaseModel): repo_path: str max_count: int = 10 +class GitCreateBranch(BaseModel): + repo_path: str + branch_name: str + base_branch: str | None = None + class GitTools(str, Enum): STATUS = "git_status" DIFF_UNSTAGED = "git_diff_unstaged" @@ -47,6 +52,7 @@ class GitTools(str, Enum): ADD = "git_add" RESET = "git_reset" LOG = "git_log" + CREATE_BRANCH = "git_create_branch" def git_status(repo: git.Repo) -> str: return repo.git.status() @@ -81,6 +87,15 @@ def git_log(repo: git.Repo, max_count: int = 10) -> list[str]: ) return log +def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None = None) -> str: + if base_branch: + base = repo.refs[base_branch] + else: + base = repo.active_branch + + repo.create_head(branch_name, base) + return f"Created branch '{branch_name}' from {base.name}" + async def serve(repository: Path | None) -> None: logger = logging.getLogger(__name__) @@ -132,6 +147,11 @@ async def list_tools() -> list[Tool]: description="Shows the commit logs", inputSchema=GitLog.schema(), ), + Tool( + name=GitTools.CREATE_BRANCH, + description="Creates a new branch from an optional base branch", + inputSchema=GitCreateBranch.schema(), + ), ] async def list_repos() -> Sequence[str]: @@ -218,6 +238,17 @@ async def call_tool(name: str, arguments: dict) -> list[TextContent]: text="Commit history:\n" + "\n".join(log) )] + case GitTools.CREATE_BRANCH: + result = git_create_branch( + repo, + arguments["branch_name"], + arguments.get("base_branch") + ) + return [TextContent( + type="text", + text=result + )] + case _: raise ValueError(f"Unknown tool: {name}") From cc4a68608878f63a64ea873124204f060d0b997f Mon Sep 17 00:00:00 2001 From: Mike Gehard Date: Sun, 1 Dec 2024 08:12:12 -0500 Subject: [PATCH 2/5] Add extra debugging/development instructions. This should help people unfamilar with ux get the right commands to test in the Claude app. --- src/git/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/git/README.md b/src/git/README.md index c94ca7ea..113e9e16 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -156,6 +156,29 @@ cd path/to/servers/src/git npx @modelcontextprotocol/inspector uv run mcp-server-git ``` +Running `tail -n 20 -f ~/Library/Logs/Claude/mcp*.log` will show the logs from the server and may +help you debug any issues. + +## Development + +If you are doing local development, there are two ways to test your changes: + +1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions. + +2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: + +```json +"git": { + "command": "uv", + "args": [ + "--directory", + "//mcp-servers/src/git", + "run", + "mcp-server-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. From dc70c024035fe8d580ee7f19d1f4e6681c1817b7 Mon Sep 17 00:00:00 2001 From: Mike Gehard Date: Sun, 1 Dec 2024 17:14:28 -0500 Subject: [PATCH 3/5] README change --- src/git/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/git/README.md b/src/git/README.md index 113e9e16..f4a82c9a 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -53,6 +53,13 @@ Please note that mcp-server-git is currently in early development. The functiona - `max_count` (number, optional): Maximum number of commits to show (default: 10) - Returns: Array of commit entries with hash, author, date, and message +8. `git_branch` + - Creates a new branch + - Inputs: + - `repo_path` (string): Path to Git repository + - `branch_name` (string): Name of the new branch + - `start_point` (string, optional): Starting point for the new branch + - Returns: Confirmation of branch creation ## Installation From 3192bf66df9bd3974cde6d334fab3a39065e9938 Mon Sep 17 00:00:00 2001 From: Mike Gehard Date: Tue, 3 Dec 2024 11:19:13 -0500 Subject: [PATCH 4/5] Update src/git/README.md Co-authored-by: Justin Spahr-Summers --- src/git/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git/README.md b/src/git/README.md index f4a82c9a..caf01294 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -53,7 +53,7 @@ Please note that mcp-server-git is currently in early development. The functiona - `max_count` (number, optional): Maximum number of commits to show (default: 10) - Returns: Array of commit entries with hash, author, date, and message -8. `git_branch` +8. `git_create_branch` - Creates a new branch - Inputs: - `repo_path` (string): Path to Git repository From c0a1cb7eac4b730972841158eaf61522a8ef77b1 Mon Sep 17 00:00:00 2001 From: Mike Gehard Date: Tue, 3 Dec 2024 11:19:22 -0500 Subject: [PATCH 5/5] Update src/git/src/mcp_server_git/server.py Co-authored-by: Justin Spahr-Summers --- src/git/src/mcp_server_git/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/git/src/mcp_server_git/server.py b/src/git/src/mcp_server_git/server.py index 85f48e0e..02fae584 100644 --- a/src/git/src/mcp_server_git/server.py +++ b/src/git/src/mcp_server_git/server.py @@ -94,7 +94,7 @@ def git_create_branch(repo: git.Repo, branch_name: str, base_branch: str | None base = repo.active_branch repo.create_head(branch_name, base) - return f"Created branch '{branch_name}' from {base.name}" + return f"Created branch '{branch_name}' from '{base.name}'" async def serve(repository: Path | None) -> None: logger = logging.getLogger(__name__)