@rethunk/mcp-multi-root-git 2.9.1 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +23 -19
- package/CHANGELOG.md +145 -39
- package/HUMANS.md +23 -42
- package/README.md +30 -13
- package/dist/repo-paths.js +57 -13
- package/dist/server/batch-commit-tool.js +203 -53
- package/dist/server/error-codes.js +31 -16
- package/dist/server/git-blame-tool.js +66 -19
- package/dist/server/git-branch-tool.js +151 -0
- package/dist/server/git-cherry-pick-tool.js +221 -12
- package/dist/server/git-conflicts-tool.js +230 -0
- package/dist/server/git-diff-summary-tool.js +39 -28
- package/dist/server/git-diff-tool.js +56 -31
- package/dist/server/git-grep-tool.js +188 -0
- package/dist/server/git-inventory-tool.js +30 -10
- package/dist/server/git-log-tool.js +37 -6
- package/dist/server/git-merge-tool.js +71 -13
- package/dist/server/git-parity-tool.js +15 -6
- package/dist/server/git-push-tool.js +4 -2
- package/dist/server/git-refs.js +48 -17
- package/dist/server/git-reset-soft-tool.js +1 -1
- package/dist/server/git-revert-tool.js +160 -0
- package/dist/server/git-show-tool.js +5 -10
- package/dist/server/git-stash-tool.js +112 -78
- package/dist/server/git-status-tool.js +2 -2
- package/dist/server/git-tag-tool.js +8 -13
- package/dist/server/git-worktree-tool.js +67 -59
- package/dist/server/git.js +116 -24
- package/dist/server/inventory.js +90 -32
- package/dist/server/list-presets-tool.js +2 -8
- package/dist/server/presets-resource.js +37 -20
- package/dist/server/presets.js +87 -15
- package/dist/server/roots.js +52 -79
- package/dist/server/schemas.js +18 -19
- package/dist/server/test-harness.js +11 -4
- package/dist/server/tool-parameter-schemas.js +47 -58
- package/dist/server/tools.js +36 -17
- package/dist/server.js +1 -1
- package/docs/install.md +52 -5
- package/docs/mcp-tools.md +472 -284
- package/package.json +6 -6
- package/schemas/batch_commit.json +5 -17
- package/schemas/git_blame.json +13 -11
- package/schemas/git_branch.json +54 -0
- package/schemas/git_cherry_pick.json +13 -15
- package/schemas/git_cherry_pick_continue.json +34 -0
- package/schemas/git_conflicts.json +38 -0
- package/schemas/git_diff.json +12 -10
- package/schemas/git_diff_summary.json +1 -15
- package/schemas/git_grep.json +85 -0
- package/schemas/git_inventory.json +32 -23
- package/schemas/git_log.json +20 -24
- package/schemas/git_merge.json +3 -15
- package/schemas/git_parity.json +13 -23
- package/schemas/git_push.json +1 -13
- package/schemas/git_reset_soft.json +1 -13
- package/schemas/git_revert.json +47 -0
- package/schemas/git_show.json +2 -8
- package/schemas/git_stash_apply.json +2 -8
- package/schemas/git_stash_push.json +47 -0
- package/schemas/git_status.json +13 -23
- package/schemas/git_tag.json +1 -7
- package/schemas/git_worktree_add.json +2 -14
- package/schemas/git_worktree_remove.json +2 -14
- package/schemas/index.json +28 -23
- package/schemas/list_presets.json +13 -23
- package/tool-parameters.schema.json +407 -423
- package/dist/server/git-branch-list-tool.js +0 -138
- package/dist/server/git-fetch-tool.js +0 -266
- package/dist/server/git-reflog-tool.js +0 -126
- package/schemas/git_branch_list.json +0 -36
- package/schemas/git_fetch.json +0 -52
- package/schemas/git_reflog.json +0 -44
- package/schemas/git_stash_list.json +0 -30
- package/schemas/git_worktree_list.json +0 -30
package/dist/server/tools.js
CHANGED
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
import { registerBatchCommitTool } from "./batch-commit-tool.js";
|
|
2
2
|
import { registerGitBlameTool } from "./git-blame-tool.js";
|
|
3
|
-
import {
|
|
4
|
-
import { registerGitCherryPickTool } from "./git-cherry-pick-tool.js";
|
|
3
|
+
import { registerGitBranchTool } from "./git-branch-tool.js";
|
|
4
|
+
import { registerGitCherryPickContinueTool, registerGitCherryPickTool, } from "./git-cherry-pick-tool.js";
|
|
5
|
+
import { registerGitConflictsTool } from "./git-conflicts-tool.js";
|
|
5
6
|
import { registerGitDiffSummaryTool } from "./git-diff-summary-tool.js";
|
|
6
7
|
import { registerGitDiffTool } from "./git-diff-tool.js";
|
|
7
|
-
import {
|
|
8
|
+
import { registerGitGrepTool } from "./git-grep-tool.js";
|
|
8
9
|
import { registerGitInventoryTool } from "./git-inventory-tool.js";
|
|
9
10
|
import { registerGitLogTool } from "./git-log-tool.js";
|
|
10
11
|
import { registerGitMergeTool } from "./git-merge-tool.js";
|
|
11
12
|
import { registerGitParityTool } from "./git-parity-tool.js";
|
|
12
13
|
import { registerGitPushTool } from "./git-push-tool.js";
|
|
13
|
-
import { registerGitReflogTool } from "./git-reflog-tool.js";
|
|
14
14
|
import { registerGitResetSoftTool } from "./git-reset-soft-tool.js";
|
|
15
|
+
import { registerGitRevertTool } from "./git-revert-tool.js";
|
|
15
16
|
import { registerGitShowTool } from "./git-show-tool.js";
|
|
16
|
-
import { registerGitStashApplyTool,
|
|
17
|
+
import { registerGitStashApplyTool, registerGitStashPushTool } from "./git-stash-tool.js";
|
|
17
18
|
import { registerGitStatusTool } from "./git-status-tool.js";
|
|
18
19
|
import { registerGitTagTool } from "./git-tag-tool.js";
|
|
19
|
-
import { registerGitWorktreeAddTool,
|
|
20
|
+
import { registerGitWorktreeAddTool, registerGitWorktreeRemoveTool } from "./git-worktree-tool.js";
|
|
20
21
|
import { registerListPresetsTool } from "./list-presets-tool.js";
|
|
21
22
|
import { registerPresetsResource } from "./presets-resource.js";
|
|
22
23
|
/**
|
|
23
|
-
* Ordered registry of all
|
|
24
|
+
* Ordered registry of all 24 MCP tools. Registration order is preserved for
|
|
24
25
|
* both full and filtered (RETHUNK_GIT_TOOLS) subsets.
|
|
25
26
|
*/
|
|
26
27
|
const TOOL_REGISTRARS = [
|
|
@@ -30,30 +31,36 @@ const TOOL_REGISTRARS = [
|
|
|
30
31
|
{ name: "git_parity", register: registerGitParityTool },
|
|
31
32
|
{ name: "list_presets", register: registerListPresetsTool },
|
|
32
33
|
{ name: "git_log", register: registerGitLogTool },
|
|
34
|
+
{ name: "git_grep", register: registerGitGrepTool },
|
|
33
35
|
{ name: "git_diff_summary", register: registerGitDiffSummaryTool },
|
|
34
36
|
{ name: "git_diff", register: registerGitDiffTool },
|
|
35
37
|
{ name: "git_show", register: registerGitShowTool },
|
|
36
|
-
{ name: "
|
|
37
|
-
{ name: "git_stash_list", register: registerGitStashListTool },
|
|
38
|
-
{ name: "git_fetch", register: registerGitFetchTool },
|
|
38
|
+
{ name: "git_conflicts", register: registerGitConflictsTool },
|
|
39
39
|
{ name: "git_blame", register: registerGitBlameTool },
|
|
40
|
-
{ name: "git_branch_list", register: registerGitBranchListTool },
|
|
41
|
-
{ name: "git_reflog", register: registerGitReflogTool },
|
|
42
40
|
// Mutating tools
|
|
43
41
|
{ name: "batch_commit", register: registerBatchCommitTool },
|
|
44
42
|
{ name: "git_push", register: registerGitPushTool },
|
|
45
43
|
{ name: "git_merge", register: registerGitMergeTool },
|
|
46
44
|
{ name: "git_cherry_pick", register: registerGitCherryPickTool },
|
|
45
|
+
{ name: "git_cherry_pick_continue", register: registerGitCherryPickContinueTool },
|
|
47
46
|
{ name: "git_reset_soft", register: registerGitResetSoftTool },
|
|
47
|
+
{ name: "git_revert", register: registerGitRevertTool },
|
|
48
48
|
{ name: "git_tag", register: registerGitTagTool },
|
|
49
|
+
{ name: "git_branch", register: registerGitBranchTool },
|
|
49
50
|
{ name: "git_worktree_add", register: registerGitWorktreeAddTool },
|
|
50
51
|
{ name: "git_worktree_remove", register: registerGitWorktreeRemoveTool },
|
|
51
52
|
{ name: "git_stash_apply", register: registerGitStashApplyTool },
|
|
53
|
+
{ name: "git_stash_push", register: registerGitStashPushTool },
|
|
52
54
|
];
|
|
53
55
|
/**
|
|
54
56
|
* Parse the RETHUNK_GIT_TOOLS env var and return the matching subset of
|
|
55
57
|
* registrars plus any unrecognized token names.
|
|
56
58
|
*
|
|
59
|
+
* Semantics:
|
|
60
|
+
* - unset / empty / whitespace-only → all tools
|
|
61
|
+
* - bare `*` (sole non-empty token) → all tools (all-tools sentinel; not an empty selection)
|
|
62
|
+
* - otherwise → exact name match (case-sensitive), canonical order, duplicates ignored
|
|
63
|
+
*
|
|
57
64
|
* @param envValue Raw value of process.env.RETHUNK_GIT_TOOLS (may be undefined).
|
|
58
65
|
* @param registrars Full ordered registrar list (injectable for tests).
|
|
59
66
|
*/
|
|
@@ -62,13 +69,25 @@ export function selectToolRegistrars(envValue, registrars) {
|
|
|
62
69
|
.split(",")
|
|
63
70
|
.map((t) => t.trim())
|
|
64
71
|
.filter((t) => t.length > 0);
|
|
65
|
-
// Unset, empty,
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
// Unset, empty, whitespace-only, or bare "*" → register all tools.
|
|
73
|
+
// Bare "*" is an intentional all-tools sentinel (operators used to root="*"
|
|
74
|
+
// fan-out may set RETHUNK_GIT_TOOLS=* expecting the full surface — treating
|
|
75
|
+
// it as an unrecognized name that empties the allowlist is a footgun).
|
|
76
|
+
if (tokens.length === 0 || (tokens.length === 1 && tokens[0] === "*")) {
|
|
77
|
+
// Shallow copy so callers cannot mutate the shared TOOL_REGISTRARS array.
|
|
78
|
+
return { selected: [...registrars], unknown: [] };
|
|
68
79
|
}
|
|
69
80
|
const knownNames = new Set(registrars.map((r) => r.name));
|
|
70
81
|
const requested = new Set(tokens);
|
|
71
|
-
|
|
82
|
+
// Deduplicate unknown tokens while preserving first-seen order.
|
|
83
|
+
const unknownSeen = new Set();
|
|
84
|
+
const unknown = [];
|
|
85
|
+
for (const t of tokens) {
|
|
86
|
+
if (!knownNames.has(t) && !unknownSeen.has(t)) {
|
|
87
|
+
unknownSeen.add(t);
|
|
88
|
+
unknown.push(t);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
72
91
|
// Preserve canonical order; deduplicate duplicate tokens automatically.
|
|
73
92
|
const selected = registrars.filter((r) => requested.has(r.name));
|
|
74
93
|
return { selected, unknown };
|
|
@@ -81,7 +100,7 @@ export function registerRethunkGitTools(server) {
|
|
|
81
100
|
}
|
|
82
101
|
if (selected.length === 0 && (env ?? "").trim().length > 0) {
|
|
83
102
|
process.stderr.write(`[rethunk-git] RETHUNK_GIT_TOOLS: every listed name was unrecognized — registering NO tools. ` +
|
|
84
|
-
`Set RETHUNK_GIT_TOOLS to a comma-separated list of valid tool names, or unset it to register all tools.\n`);
|
|
103
|
+
`Set RETHUNK_GIT_TOOLS to a comma-separated list of valid tool names, bare "*" for all tools, or unset it to register all tools.\n`);
|
|
85
104
|
}
|
|
86
105
|
for (const { register } of selected) {
|
|
87
106
|
register(server);
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,7 @@ import { registerRethunkGitTools } from "./server/tools.js";
|
|
|
7
7
|
* (renamed/nested/omitted fields). Surfaced via the FastMCP `instructions`
|
|
8
8
|
* field below, so it is discoverable in the MCP `initialize` response.
|
|
9
9
|
*/
|
|
10
|
-
export const MCP_JSON_FORMAT_VERSION = "
|
|
10
|
+
export const MCP_JSON_FORMAT_VERSION = "6";
|
|
11
11
|
const server = new FastMCP({
|
|
12
12
|
name: "rethunk-git",
|
|
13
13
|
version: readMcpServerVersion(),
|
package/docs/install.md
CHANGED
|
@@ -91,11 +91,30 @@ Omit any `cwd` / `workingDirectory` field unless your client requires it for unr
|
|
|
91
91
|
|
|
92
92
|
| Variable | Default | Purpose |
|
|
93
93
|
|----------|---------|---------|
|
|
94
|
-
| `GIT_SUBPROCESS_PARALLELISM` | `4` |
|
|
95
|
-
| `
|
|
94
|
+
| `GIT_SUBPROCESS_PARALLELISM` | `4` | Max concurrent git subprocesses for `git_inventory` rows, `git_status` submodule rows, and multi-root fan-out in `git_log` and `git_grep`. Valid range: 1 to 2×CPU count (auto-clamped). Increase on high-core machines to accelerate large fleet scans; decrease if system resources are constrained. |
|
|
95
|
+
| `GIT_SUBPROCESS_TIMEOUT_MS` | `120000` | Per-subprocess timeout in milliseconds for async git calls. On expiry the child receives SIGTERM and the call fails. Set `0` (or negative) to disable timeout for intentionally unbounded operations. |
|
|
96
|
+
| `RETHUNK_GIT_TOOLS` | _(unset)_ | Comma-separated list of tool names to register. When unset or empty, all 24 tools are registered (default). When set, only the listed tools are exposed — unknown names are warned and ignored. If every name is unknown, **zero** tools are registered and a loud warning is emitted (the restriction is honored literally). The presets resource (`rethunk-git://presets`) is always registered regardless of this setting. Example: `RETHUNK_GIT_TOOLS=git_status,git_diff_summary,git_diff,git_log,batch_commit,git_push`. Full tool-name list: `git_status`, `git_inventory`, `git_parity`, `list_presets`, `git_log`, `git_grep`, `git_diff_summary`, `git_diff`, `git_show`, `git_conflicts`, `git_blame`, `batch_commit`, `git_push`, `git_merge`, `git_cherry_pick`, `git_cherry_pick_continue`, `git_reset_soft`, `git_revert`, `git_tag`, `git_branch`, `git_worktree_add`, `git_worktree_remove`, `git_stash_apply`, `git_stash_push`. |
|
|
96
97
|
|
|
97
98
|
Set these in the environment where the MCP client launches the server (e.g. in your shell, in the MCP client config as `env`, or in a startup script).
|
|
98
99
|
|
|
100
|
+
**MCP client `env` block** (Cursor / Claude Desktop `mcpServers`; VS Code adds `"env"` beside `"command"` / `"args"`):
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"mcpServers": {
|
|
105
|
+
"rethunk-git": {
|
|
106
|
+
"command": "npx",
|
|
107
|
+
"args": ["-y", "@rethunk/mcp-multi-root-git"],
|
|
108
|
+
"env": {
|
|
109
|
+
"GIT_SUBPROCESS_PARALLELISM": "8",
|
|
110
|
+
"GIT_SUBPROCESS_TIMEOUT_MS": "120000",
|
|
111
|
+
"RETHUNK_GIT_TOOLS": "git_status,git_log,batch_commit,git_push"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
99
118
|
Example: Running the server with 8 parallel git processes on a 4-core machine:
|
|
100
119
|
|
|
101
120
|
```bash
|
|
@@ -200,12 +219,40 @@ Official protocol overview: [modelcontextprotocol.io](https://modelcontextprotoc
|
|
|
200
219
|
|
|
201
220
|
For contributors working inside a clone of [mcp-multi-root-git](https://github.com/Rethunk-AI/mcp-multi-root-git):
|
|
202
221
|
|
|
203
|
-
1. **Dependencies, build, and CI parity:**
|
|
222
|
+
1. **Dependencies, build, and CI parity:** [CONTRIBUTING.md](../CONTRIBUTING.md) — *Development setup* (`bun install`, `bun run build`, `bun run ci`).
|
|
204
223
|
2. **Run the dev server** (no `dist/` required): from the repo root, **`bun src/server.ts`** (stdio MCP).
|
|
205
224
|
|
|
206
|
-
**MCP registration for a local checkout
|
|
225
|
+
**MCP registration for a local checkout** — set `cwd` to the repository root (exception to the no-`cwd` rule for published packages) so relative `args` resolve, or pass absolute paths in `args`. Open the workspace at the clone root in your client.
|
|
226
|
+
|
|
227
|
+
**Bun dev server** (no `dist/` build):
|
|
228
|
+
|
|
229
|
+
```json
|
|
230
|
+
{
|
|
231
|
+
"mcpServers": {
|
|
232
|
+
"rethunk-git": {
|
|
233
|
+
"command": "bun",
|
|
234
|
+
"args": ["src/server.ts"],
|
|
235
|
+
"cwd": "/path/to/mcp-multi-root-git"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Built entrypoint** (after `bun run build`):
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"mcpServers": {
|
|
246
|
+
"rethunk-git": {
|
|
247
|
+
"command": "node",
|
|
248
|
+
"args": ["dist/server.js"],
|
|
249
|
+
"cwd": "/path/to/mcp-multi-root-git"
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
```
|
|
207
254
|
|
|
208
|
-
**Reload** the MCP connection after changing server code.
|
|
255
|
+
**Cursor:** add either block to user-scope (`~/.cursor/mcp.json`) or project-scope (`.cursor/mcp.json`). **Reload** the MCP connection after changing server code.
|
|
209
256
|
|
|
210
257
|
## Troubleshooting
|
|
211
258
|
|