# MCP Git Tools Git tools implementation for the Model Context Protocol (MCP). [中文文档](README_CN.md) ## Features This library provides a set of Git operations that can be called through the Model Context Protocol: - `git_status` - Get the status of a repository - `git_branches` - List branch information - `git_log` - Get commit history with flexible filtering options (by time, author, branch, count) - `git_commit` - Create a new commit - `git_pull` - Pull changes from remote - `git_push` - Push changes to remote - `git_diff` - View file differences - `git_add` - Add file contents to the staging area - `git_reset` - Reset the staging area or working tree to a specified state - `git_worktree_list` - List all worktrees - `git_worktree_add` - Create a new worktree - `git_worktree_remove` - Remove a worktree - `git_worktree_prune` - Prune expired worktree files ## Installation ```bash # Clone the repository git clone https://gitcode.com/lileeei/mcp-git-tools.git # Navigate to the directory cd mcp-git-tools # Build cargo build --release ``` ## Usage ### Run as a standalone server ```bash cargo run --release --bin mcp-git-server ``` This starts an MCP server that interacts with clients through standard input/output. ### Test with MCP Inspector 1. Build the server: ```bash cargo build --release ``` 2. Start the server: ```bash ./target/release/mcp-git-server ``` 3. Use MCP Inspector to test the tools: - Download MCP Inspector: https://github.com/modelcontextprotocol/inspector - Click "Add a server" - Enter: `/path/to/mcp-git-server/target/release/mcp-git-server` - Click "Add" - Test each tool using the Inspector interface ## Architecture This project uses the modern RMCP SDK (v0.14.0) with a clean architecture: ### Core Components **GitToolsHandler** - Central handler struct for all Git operations - Implements `ServerHandler` trait from RMCP SDK - Contains methods for each Git operation **ServerHandler Implementation** - `get_info()` - Provides server metadata and capabilities - `list_tools()` - Lists all available tools with their schemas - `call_tool()` - Routes tool calls to appropriate handler methods ### Tool Implementation Pattern Each tool is implemented as a method on `GitToolsHandler`: ```rust impl GitToolsHandler { #[tool(description = "Get the status of a git repository")] pub async fn git_status( &self, repo_path: String, ) -> Result { // Implementation } } ``` ### Parameter Handling All tool parameters use derive macros for automatic schema generation: ```rust #[derive(serde::Deserialize, schemars::JsonSchema)] struct GitStatusParams { repo_path: String, } ``` This provides: - Automatic JSON schema generation - Type-safe parameter parsing - No manual serialization/deserialization code ### Transport Uses RMCP's `stdio()` transport for standard input/output communication. ## Tool Details ### git_status Get the status of a repository. **Parameters:** - `repo_path` - Path to the Git repository **Returns:** ```json { "status": ["M file1.txt", "?? file2.txt"], "is_clean": false } ``` ### git_branches List all branches. **Parameters:** - `repo_path` - Path to the Git repository **Returns:** ```json { "branches": ["* main", "develop", "feature/new-feature"], "current": "main" } ``` ### git_log Get commit history with flexible filtering options. **Parameters:** - `repo_path` - Path to Git repository - `max_count` - (optional) Maximum number of commits to return - `branch` - (optional) Branch name - `since` - (optional) Start date (e.g., "2023-01-01", "1 week ago", "yesterday") - `until` - (optional) End date (e.g., "2023-01-31", "today") - `author` - (optional) Filter by specific author (matches name or email) **Returns:** ```json { "commits": [ { "hash": "abcd1234", "author": "User Name", "author_date": "Mon Aug 1 10:00:00 2023 +0800", "message_title": "Initial commit" } ] } ``` **Examples:** - Get recent 10 commits: `{"repo_path": ".", "max_count": 10}` - Get commits from last week: `{"repo_path": ".", "since": "1 week ago"}` - Get commits by author: `{"repo_path": ".", "author": "John"}` - Get commits from a time range: `{"repo_path": ".", "since": "2023-01-01", "until": "2023-12-31"}` ### git_commit Create a new commit. **Parameters:** - `repo_path` - Path to the Git repository - `message` - Commit message - `all` - (optional) Whether to automatically stage modified files **Returns:** ```json { "success": true, "hash": "abcd1234", "message": "feat: Add new feature", "output": "[main abcd1234] feat: Add new feature\n 1 file changed, 10 insertions(+), 2 deletions(-)" } ``` ### git_pull Pull changes from remote. **Parameters:** - `repo_path` - Path to the Git repository - `remote` - (optional) Remote name, defaults to "origin" - `branch` - (optional) Branch name **Returns:** ```json { "success": true, "remote": "origin", "output": "Updating abcd1234..efgh5678\nFast-forward\n file1.txt | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)" } ``` ### git_push Push changes to remote. **Parameters:** - `repo_path` - Path to the Git repository - `remote` - (optional) Remote name, defaults to "origin" - `branch` - (optional) Branch name - `force` - (optional) Whether to force push **Returns:** ```json { "success": true, "remote": "origin", "output": "To github.com:user/repo.git\n abcd1234..efgh5678 main -> main" } ``` ### git_diff View file differences. **Parameters:** - `repo_path` - Path to the Git repository - `path` - (optional) Path to file or directory - `staged` - (optional) Whether to show staged changes - `commit` - (optional) Commit to compare against **Returns:** ```json { "changes": "diff --git a/file.txt b/file.txt\nindex 1234567..abcdefg 100644\n--- a/file.txt\n+++ b/file.txt\n@@ -1,3 +1,4 @@\n Line 1\nLine 2\nLine 3\n+New line\nLine 4" } ``` ### git_add Add file contents to the staging area. **Parameters:** - `repo_path` - Path to the Git repository - `path` - Path(s) to add, or patterns to match. Use '.' for all files. - `update` - (optional) Whether to update, rather than add - `all` - (optional) Whether to add all changes, including untracked files **Returns:** ```json { "success": true, "message": "Files staged successfully", "status": ["M file1.txt", "A file2.txt"] } ``` ### git_reset Reset the staging area or working tree to a specified state. **Parameters:** - `repo_path` - Path to the Git repository - `path` - Path(s) to reset, or patterns to match. Use '.' for all files. - `hard` - (optional) Whether to perform a hard reset (WARNING: discards all local changes) - `target` - (optional) The commit or branch to reset to (defaults to HEAD) **Returns:** ```json { "success": true, "message": "Files unstaged successfully", "status": ["?? file1.txt", "?? file2.txt"] } ``` ### git_worktree_list List all worktrees in a repository. **Parameters:** - `repo_path` - Path to the Git repository **Returns:** ```json { "worktrees": [ { "id": "worktree-name", "path": "/path/to/worktree", "locked": false, "lock_reason": null } ] } ``` ### git_worktree_add Create a new worktree. **Parameters:** - `repo_path` - Path to the Git repository - `path` - Path for the new worktree - `branch` - (optional) Branch name to create - `commit_ref` - (optional) Commit reference to check out - `checkout` - (optional) Whether to check out files, defaults to true **Returns:** ```json { "success": true, "path": "/path/to/new/worktree", "branch": "feature-branch", "output": "Preparing worktree (checking out 'feature-branch')" } ``` ### git_worktree_remove Remove a worktree. **Parameters:** - `repo_path` - Path to the Git repository - `path` - Path to the worktree to remove - `force` - (optional) Force removal even if worktree is dirty **Returns:** ```json { "success": true, "path": "/path/to/worktree", "force": false, "output": "Removing worktrees/feature-branch" } ``` ### git_worktree_prune Prune working tree files in $GIT_DIR/worktrees. **Parameters:** - `repo_path` - Path to the Git repository - `verbose` - (optional) Report all removals - `dry_run` - (optional) Do not remove, show only **Returns:** ```json { "success": true, "verbose": false, "dry_run": false, "output": "Pruning worktrees/feature-branch" } ``` ## Development ### Project Structure ``` mcp-git-tools/ ├── Cargo.toml # Dependencies and project configuration ├── src/ │ ├── lib.rs # Core library with GitToolsHandler │ └── bin/ │ └── server.rs # Server entry point ├── tests/ │ └── lib_tests.rs # Unit tests ``` ### Building ```bash # Debug build cargo build # Release build cargo build --release # Run tests cargo test # Run server cargo run --release --bin mcp-git-server ``` ### Adding New Tools To add a new Git tool: 1. Add the parameter struct in `src/lib.rs`: ```rust #[derive(serde::Deserialize, schemars::JsonSchema)] struct GitMyToolParams { repo_path: String, // other parameters... } ``` 2. Add the method in the `GitToolsHandler` impl block: ```rust #[tool(description = "Description of your tool")] pub async fn git_my_tool( &self, repo_path: String, // other parameters... ) -> Result { // Implementation } ``` 3. Update the `list_tools()` method to include your new tool in the returned list ## Dependencies - `rmcp` v0.14.0 - The official RMCP SDK - `tokio` - Async runtime - `serde` - Serialization framework - `serde_json` - JSON implementation - `anyhow` - Error handling - `tracing` - Logging framework - `tempfile` - Testing utilities ## License MIT License