Skip to main content
Glama
abhinav054

git-remote-mcp

by abhinav054
README.md
# git-remote-mcp

Node MCP server that exposes local git commands, uses the GitHub API for fetch/pull object transfer, and uses an HTTP API for custom push workflows.

## Install

```sh
npm install
```

## Run

```sh
npm start
```

## Test

```sh
npm test
```

Real GitHub integration tests are opt-in and run a destructive end-to-end workflow against the target branch:

```sh
scripts/test-integration.sh \
  --repo-url "https://github.com/owner/repo.git" \
  --auth-token "github-token" \
  --branch "main" \
  --push
```

The workflow pulls the real repo, edits `README.md`, commits through the MCP server's local git tools, then pushes the commit back to GitHub with the provided token.

The same values can be passed through environment variables:

```sh
GIT_MCP_INTEGRATION_REPO_URL="https://github.com/owner/repo.git" \
GIT_MCP_INTEGRATION_AUTH_TOKEN="github-token" \
GIT_MCP_INTEGRATION_BRANCH="main" \
GIT_MCP_INTEGRATION_PUSH="1" \
npm run test:integration
```

Do not commit real tokens. Use a disposable test repository or branch because the integration test intentionally writes and pushes a README commit.

HTTP API requests for `git_push` and `git_push_new_branch`:

```sh
remote_url="https://example.com/git/execute" git_jwt_auth="JWT_TOKEN" npm start
```

Read the remote URL from a local file instead of `remote_url`:

```sh
use_remote_url_file=true remote_url_file="/path/to/remote-url.txt" npm start
```

The file should contain the URL as plain text. `remote_url` is only required when using HTTP-backed push tools.

MCP client command:

```json
{
  "command": "node",
  "args": ["/absolute/path/to/git-remote-mcp/src/index.js"],
  "env": {
    "remote_url": "https://example.com/git/execute"
  }
}
```

Supported environment variables:

- `remote_url` or `REMOTE_URL`: HTTP API endpoint for push workflows.
- `use_remote_url_file` or `USE_REMOTE_URL_FILE`: set to `true`, `1`, `yes`, or `on` to read the URL from a file.
- `remote_url_file` or `REMOTE_URL_FILE`: local file containing the HTTP API endpoint.
- `git_jwt_auth` or `GIT_JWT_AUTH`: JWT token sent as `Authorization: Bearer <token>`.
- `github_token`, `GITHUB_TOKEN`, `GITHUB_PAT`, or `GH_TOKEN`: optional GitHub token for fetch/pull workflows.
- `github_api_url` or `GITHUB_API_URL`: optional GitHub API base URL, default `https://api.github.com`.
- `REQUEST_TIMEOUT_MS`: request timeout, default `30000`.

## Tools

- `git`: generic allowed git command runner. `git fetch` and `git pull` use the GitHub API flow below; `git push` is handled as the custom diff upload flow below.
- Read/inspect: `git_status`, `git_log`, `git_diff`, `git_show`, `git_branch`, `git_blame`, `git_grep`, `git_ls_files`.
- Working tree/index: `git_add`, `git_restore`, `git_reset`, `git_rm`, `git_mv`, `git_clean`.
- History: `git_commit`, `git_merge`, `git_rebase`, `git_cherry_pick`, `git_revert`.
- Refs/config: `git_checkout`, `git_switch`, `git_tag`, `git_stash`, `git_config`.
- Download: `git_fetch`, `git_pull`.
- Upload: `git_push`, `git_push_new_branch`.

Remote/network git actions are disabled before any local git network transport can run. Blocked commands include:

- `git clone`
- `git remote`
- `git request-pull`
- `git send-pack`
- `git receive-pack`
- `git upload-pack`
- `git upload-archive`
- `git ls-remote`
- `git submodule`

Remote-related options such as `--upload-pack`, `--receive-pack`, `--exec`, `--remote`, and `--recurse-submodules` are also blocked in the generic `git` tool.

## Fetch/pull GitHub API flow

`git_fetch`, `git_pull`, and generic `git` with `command: "fetch"` or `command: "pull"` do not run local `git fetch` or `git pull`.

Instead, the MCP server:

1. Ensures `cwd` is a git repository, running `git init` first when needed and `repoUrl` is supplied.
2. Reads the configured GitHub `remote.<name>.url`, or runs `git remote add <name> <repoUrl>` when `repoUrl` is supplied and the remote is missing.
3. Uses `GitApiClient.fetchRef()` to resolve the remote branch.
4. Uses `fetchCommitGraph()` to find commits missing locally.
5. Uses `fetchTree()` and `fetchBlob()` to download tree entries and blobs.
6. Writes local objects with `git hash-object`, `git mktree`, and `git commit-tree`.
7. Updates `refs/remotes/<remote>/<branch>` with `git update-ref`.
8. For pull only, runs local `git merge refs/remotes/<remote>/<branch>`.

The remote URL must be a GitHub HTTPS or SSH URL. `git_fetch` and `git_pull` accept optional `repoUrl` and `authToken` parameters; generic `git fetch` and `git pull` accept `--repo-url=<url>` or a third positional URL after remote and branch, plus `--auth-token=<token>`. The branch defaults to the current upstream branch, then the configured `refs/remotes/<remote>/HEAD` branch. Signed commits may not be reproducible through `commit-tree`; in that case the fetch fails rather than updating refs to a mismatched commit.

## Push upload flow

`git_push` and generic `git` with `command: "push"` do not run `git push`.

Instead, the MCP server:

1. Runs local `git diff <base> --binary`.
2. Writes the returned diff to a local temporary `.patch` file.
3. Calls `remote_url` again with a JSON payload containing the patch path.

The upload request looks like:

```json
{
  "action": "push",
  "command": "push",
  "diffPath": "/tmp/git-remote-mcp-xYz/123.patch",
  "cwd": "/repo/path",
  "base": "HEAD",
  "args": [],
  "message": "optional message"
}
```

The API should read `diffPath` and handle the upload/apply operation. Any `args` are forwarded as metadata only; they are not executed as `git push` by this MCP server.

## New branch push flow

`git_push_new_branch` asks the API to publish a branch to a remote. If `createLocal` is true, the MCP server first runs local `git switch -c <branch> [startPoint]`, then sends:

```json
{
  "action": "push_new_branch",
  "command": "push",
  "cwd": "/repo/path",
  "branch": "feature/example",
  "remote": "origin",
  "startPoint": "main",
  "setUpstream": true,
  "args": ["origin", "feature/example"]
}
```

The API should perform the actual remote branch publish, for example equivalent to `git push -u origin feature/example` when `setUpstream` is true.

## Local git contract

All non-push tools run local git with:

```sh
git <command> ...args
```

The optional `cwd` parameter controls the local repository path.

## HTTP contract

The server sends `POST` requests to `remote_url` only for push workflows. Diff upload requests look like:

```json
{
  "action": "push",
  "command": "push",
  "diffPath": "/tmp/git-remote-mcp-xYz/123.patch",
  "cwd": "/repo/path",
  "base": "HEAD",
  "args": [],
  "message": "optional message"
}
```

and return JSON:

```json
{
  "stdout": "main\n",
  "stderr": "",
  "exitCode": 0
}
```

Any non-2xx HTTP response is treated as an MCP tool error. A JSON response with `ok: false` or non-zero `exitCode` is returned to the MCP client as an error result.

`REQUEST_TIMEOUT_MS` can be set to change the default 30 second remote call timeout.

TDQS

C2.5/5.0

Scored across 27 tools

Disambiguation2/5

The generic `git` tool overlaps with nearly every specific git_* tool, so agents must guess whether to use the catch-all or a dedicated command. `git_checkout`, `git_switch`, and `git_restore` also have overlapping semantics, and `git_push` vs `git_push_new_branch` require careful reading to distinguish.

Naming Consistency4/5

All tools use a consistent git_ prefix and snake_case naming, making the set highly predictable. The lone exception is the generic `git` tool, which lacks a subcommand suffix and slightly breaks the pattern.

Tool Count2/5

27 tools is heavy for this domain, and many duplicate functionality already exposed by the generic `git` tool. The set feels bloated rather than well-scoped, with several niche subcommands included while other essential ones are missing.

Completeness2/5

For a server named git-remote-mcp, critical remote operations like fetch, pull, clone, and remote management are absent. Local coverage is broad, but the remote lifecycle is severely incomplete and will cause agent failures for common workflows.

Maintenance

ActivityMaintained
ResponsivenessNo issues