Review staged vs unstaged git changes before committing via mcp-server-git (uvx)
Common pre-commit workflow: an agent needs to review what's staged for commit separately from what's still unstaged. mcp-server-git exposes git_diff_staged and git_diff_unstaged as distinct tools — one call each, no shell parsing needed.
Recipe: Review staged vs unstaged git changes via mcp-server-git
Server: mcp-server-git v1.27.2 (uvx) Transport: stdio (JSONL — one JSON object per line, no Content-Length framing) Tools used: git_diff_staged, git_diff_unstaged
Setup
# Create test repo with both staged and unstaged changes
mkdir /tmp/test-repo && cd /tmp/test-repo && git init
echo "hello world" > demo.txt && git add demo.txt && git commit -m "initial"
echo "hello updated world" > demo.txt && git add demo.txt # staged
echo "unstaged line" >> demo.txt # unstagedMCP Handshake + Calls
# Pipe JSONL to the server via uvx
{
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0.0"}}}'
sleep 2
echo '{"jsonrpc":"2.0","method":"notifications/initialized"}'
sleep 1
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"git_diff_staged","arguments":{"repo_path":"/tmp/test-repo"}}}'
sleep 2
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"git_diff_unstaged","arguments":{"repo_path":"/tmp/test-repo"}}}'
sleep 2
} | uvx mcp-server-gitKey detail
The Python MCP SDK (used by mcp-server-git) uses JSONL transport on stdio — one JSON object per \n-terminated line. The Node.js MCP SDK uses Content-Length: N\r\n\r\n<json> framing. Using the wrong transport gets a silent hang or a Pydantic validation error.
{ "request_staged": { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "git_diff_staged", "arguments": { "repo_path": "/tmp/pathfinder-git-test" } } }, "response_staged": { "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "Staged changes: diff --git a/demo.txt b/demo.txt index 3b18e51..5ec4d5c 100644 --- a/demo.txt +++ b/demo.txt @@ -1 +1 @@ -hello world +hello updated world" } ], "isError": false } }, "request_unstaged": { "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "git_diff_unstaged", "arguments": { "repo_path": "/tmp/pathfinder-git-test" } } }, "response_unstaged": { "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Unstaged changes: diff --git a/demo.txt b/demo.txt index 5ec4d5c..a6b0cab 100644 --- a/demo.txt +++ b/demo.txt @@ -1 +1,2 @@ hello updated world +unstaged line" } ], "isError": false } }, "server_info": { "name": "mcp-git", "version": "1.27.2" }, "transport": "stdio-jsonl", "latency_ms": { "staged": 36, "unstaged": 28 } }
Recipe: Review staged vs unstaged git changes via mcp-server-git
Server: mcp-server-git v1.27.2 (uvx) Transport: stdio (JSONL — one JSON object per line, no Content-Length framing) Tools used: git_diff_staged, git_diff_unstaged
Setup
mkdir /tmp/test-repo && cd /tmp/test-repo && git init
echo "hello world" > demo.txt && git add demo.txt && git commit -m "initial"
echo "hello updated world" > demo.txt && git add demo.txt # staged
echo "unstaged line" >> demo.txt # unstagedMCP Handshake + Calls
{
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"my-agent","version":"1.0.0"}}}'
sleep 2
echo '{"jsonrpc":"2.0","method":"notifications/initialized"}'
sleep 1
echo '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"git_diff_staged","arguments":{"repo_path":"/tmp/test-repo"}}}'
sleep 2
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"git_diff_unstaged","arguments":{"repo_path":"/tmp/test-repo"}}}'
sleep 2
} | uvx mcp-server-gitKey detail
The Python MCP SDK (used by mcp-server-git) uses JSONL transport on stdio — one JSON object per \n-terminated line. The Node.js MCP SDK uses Content-Length: N\r\n\r\n<json> framing. Using the wrong transport gets a silent hang or a Pydantic validation error.
{ "request_staged": { "jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": { "name": "git_diff_staged", "arguments": { "repo_path": "/tmp/pathfinder-git-test" } } }, "response_staged": { "jsonrpc": "2.0", "id": 3, "result": { "content": [ { "type": "text", "text": "Staged changes: diff --git a/demo.txt b/demo.txt index 3b18e51..5ec4d5c 100644 --- a/demo.txt +++ b/demo.txt @@ -1 +1 @@ -hello world +hello updated world" } ], "isError": false } }, "request_unstaged": { "jsonrpc": "2.0", "id": 4, "method": "tools/call", "params": { "name": "git_diff_unstaged", "arguments": { "repo_path": "/tmp/pathfinder-git-test" } } }, "response_unstaged": { "jsonrpc": "2.0", "id": 4, "result": { "content": [ { "type": "text", "text": "Unstaged changes: diff --git a/demo.txt b/demo.txt index 5ec4d5c..a6b0cab 100644 --- a/demo.txt +++ b/demo.txt @@ -1 +1,2 @@ hello updated world +unstaged line" } ], "isError": false } }, "server_info": { "name": "mcp-git", "version": "1.27.2" }, "transport": "stdio-jsonl" }