@rethunk/mcp-multi-root-git 2.8.0 → 2.8.1
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 +1 -1
- package/HUMANS.md +1 -1
- package/dist/server/batch-commit-tool.js +9 -14
- package/dist/server/git-branch-list-tool.js +2 -4
- package/dist/server/git-cherry-pick-tool.js +11 -21
- package/dist/server/git-diff-summary-tool.js +3 -4
- package/dist/server/git-diff-tool.js +8 -16
- package/dist/server/git-log-tool.js +8 -14
- package/dist/server/git-merge-tool.js +6 -10
- package/dist/server/git-reset-soft-tool.js +3 -6
- package/dist/server/git-stash-tool.js +3 -5
- package/dist/server/git-worktree-tool.js +6 -9
- package/dist/server/schemas.js +4 -4
- package/docs/mcp-tools.md +1 -1
- package/package.json +9 -12
- package/tool-parameters.schema.json +94 -94
package/AGENTS.md
CHANGED
|
@@ -54,7 +54,7 @@ IDEs injecting this as context: do not re-link from rules.
|
|
|
54
54
|
|
|
55
55
|
## Validate + CI
|
|
56
56
|
|
|
57
|
-
Local: `bun run build` | `bun run
|
|
57
|
+
Local: `bun run build` | `bun run lint` | `bun run schema:tools:check` | `bun run test`. CI ([`ci.yml`](.github/workflows/ci.yml)) runs same on PRs + `main` after `bun install --frozen-lockfile`, then `bun run test:coverage` + `bun run coverage:check`, and uploads prerelease `npm pack` artifact. Tag `v*.*.*` matching `package.json` version → [`release.yml`](.github/workflows/release.yml) publishes to GitHub Packages as `@rethunk-ai/mcp-multi-root-git` + cuts GitHub Release. npmjs publish is manual (see [HUMANS.md](HUMANS.md)).
|
|
58
58
|
|
|
59
59
|
Optional [`.githooks/`](.githooks): `bun run setup-hooks` once per clone. pre-commit=`check`; pre-push=frozen install + build + check + test.
|
|
60
60
|
|
package/HUMANS.md
CHANGED
|
@@ -205,7 +205,7 @@ It verifies the `package.json` version has a matching `CHANGELOG.md` section, bo
|
|
|
205
205
|
|
|
206
206
|
npmjs no longer fits an unattended CI publish flow for this org; **do not** rely on automation to [npmjs](https://www.npmjs.com/package/@rethunk/mcp-multi-root-git). To publish the **same** package name consumers already use (**`@rethunk/mcp-multi-root-git`**):
|
|
207
207
|
|
|
208
|
-
1. On a clean checkout at the release commit (usually **`main`** after bumping version), run **`bun run prepublishOnly`** (or `bun run build && bun run
|
|
208
|
+
1. On a clean checkout at the release commit (usually **`main`** after bumping version), run **`bun run prepublishOnly`** (or `bun run build && bun run lint && bun run test`).
|
|
209
209
|
2. Log in to the public registry once per machine: **`npm login`** (or `npm adduser`) so **`npm whoami`** shows the account that owns **`@rethunk`** on npmjs.
|
|
210
210
|
3. Ensure **`package.json`** still has **`"name": "@rethunk/mcp-multi-root-git"`** and **`publishConfig.access`** is **`"public"`** (no **`publishConfig.registry`** pointing at GitHub — leave default registry for npmjs).
|
|
211
211
|
4. Publish: **`npm publish --access public`** (runs **`prepublishOnly`** again unless you pass **`--ignore-scripts`** after you already verified locally).
|
|
@@ -24,23 +24,20 @@ const CommitEntrySchema = z.object({
|
|
|
24
24
|
files: z
|
|
25
25
|
.array(FileEntrySchema)
|
|
26
26
|
.min(1)
|
|
27
|
-
.describe("Paths to stage, relative to
|
|
28
|
-
"Deleted
|
|
29
|
-
"Combining { path, lines } with a deleted file is an error."),
|
|
27
|
+
.describe("Paths to stage, relative to git root. String or `{ path, lines }` for hunk-level staging. " +
|
|
28
|
+
"Deleted tracked files are staged via `git rm --cached`. Cannot combine `lines` with a deleted file."),
|
|
30
29
|
});
|
|
31
30
|
const PushModeSchema = z
|
|
32
31
|
.enum(["never", "after"])
|
|
33
32
|
.optional()
|
|
34
33
|
.default("never")
|
|
35
|
-
.describe("`never` (default): no push. `after`: push
|
|
36
|
-
"fails with `push_no_upstream` if
|
|
37
|
-
"Enum reserved for future modes such as `force-with-lease`.");
|
|
34
|
+
.describe("`never` (default): no push. `after`: push current branch to upstream after all commits succeed; " +
|
|
35
|
+
"fails with `push_no_upstream` if no upstream (commits are NOT rolled back).");
|
|
38
36
|
const DryRunSchema = z
|
|
39
37
|
.boolean()
|
|
40
38
|
.optional()
|
|
41
39
|
.default(false)
|
|
42
|
-
.describe("
|
|
43
|
-
"Unstages any files that were staged for the preview. Response indicates DRY RUN mode.");
|
|
40
|
+
.describe("Stage files and return a preview without writing commits; unstages afterwards. Response is marked DRY RUN.");
|
|
44
41
|
/**
|
|
45
42
|
* Parses a unified diff to extract hunks that overlap with a given line range.
|
|
46
43
|
* Returns a partial patch containing only the overlapping hunks, including header lines.
|
|
@@ -220,11 +217,9 @@ export async function runPushAfter(gitTop) {
|
|
|
220
217
|
export function registerBatchCommitTool(server) {
|
|
221
218
|
server.addTool({
|
|
222
219
|
name: "batch_commit",
|
|
223
|
-
description: "Create multiple sequential git commits in
|
|
224
|
-
"Each entry stages
|
|
225
|
-
'
|
|
226
|
-
"to its upstream once all commits succeed. " +
|
|
227
|
-
"Optional `dryRun: true` previews what would be staged/committed without writing commits.",
|
|
220
|
+
description: "Create multiple sequential git commits in one call. " +
|
|
221
|
+
"Each entry stages its files then commits. Stops on first failure. " +
|
|
222
|
+
'Optional `push: "after"` pushes after all commits succeed. `dryRun: true` previews without writing.',
|
|
228
223
|
annotations: {
|
|
229
224
|
readOnlyHint: false,
|
|
230
225
|
destructiveHint: false,
|
|
@@ -235,7 +230,7 @@ export function registerBatchCommitTool(server) {
|
|
|
235
230
|
.array(CommitEntrySchema)
|
|
236
231
|
.min(1)
|
|
237
232
|
.max(50)
|
|
238
|
-
.describe("
|
|
233
|
+
.describe("Ordered list of commits to create."),
|
|
239
234
|
push: PushModeSchema,
|
|
240
235
|
dryRun: DryRunSchema,
|
|
241
236
|
}),
|
|
@@ -100,9 +100,7 @@ function renderBranchListMarkdown(result) {
|
|
|
100
100
|
export function registerGitBranchListTool(server) {
|
|
101
101
|
server.addTool({
|
|
102
102
|
name: "git_branch_list",
|
|
103
|
-
description: "List local
|
|
104
|
-
"Returns `{ branches: [{ name, sha, current, upstream? }], remotes?: [{ name, sha }] }`. " +
|
|
105
|
-
"The current branch is marked with `current: true`. Remote branches are included when `includeRemotes: true`.",
|
|
103
|
+
description: "List local (and optionally remote-tracking) branches. Current branch marked `current: true`. Set `includeRemotes: true` for remotes.",
|
|
106
104
|
annotations: {
|
|
107
105
|
readOnlyHint: true,
|
|
108
106
|
},
|
|
@@ -117,7 +115,7 @@ export function registerGitBranchListTool(server) {
|
|
|
117
115
|
.boolean()
|
|
118
116
|
.optional()
|
|
119
117
|
.default(false)
|
|
120
|
-
.describe("
|
|
118
|
+
.describe("Include remote-tracking branches from refs/remotes (symbolic origin/HEAD excluded)."),
|
|
121
119
|
}),
|
|
122
120
|
execute: async (args) => {
|
|
123
121
|
const pre = requireSingleRepo(server, args);
|
|
@@ -94,14 +94,11 @@ async function filterAndDedupe(gitTop, onto, resolved) {
|
|
|
94
94
|
export function registerGitCherryPickTool(server) {
|
|
95
95
|
server.addTool({
|
|
96
96
|
name: "git_cherry_pick",
|
|
97
|
-
description: "
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
"
|
|
102
|
-
"(content-identical commits with different SHAs are treated as merged, which is the " +
|
|
103
|
-
"normal cherry-pick outcome). Pass `strictMergedRefEquality: true` for strict `git branch -d` " +
|
|
104
|
-
"ancestry semantics. Protected branch names always skipped.",
|
|
97
|
+
description: "Cherry-pick commits from one or more sources onto a destination. Sources: SHAs, `A..B` ranges, " +
|
|
98
|
+
"or branch names (expanded to `onto..<branch>`, oldest-first). Already-reachable commits skipped. " +
|
|
99
|
+
"Refuses on dirty tree; stops on first conflict. Optional flags delete source branches/worktrees " +
|
|
100
|
+
"after success using patch-id equivalence (set `strictMergedRefEquality: true` for strict ancestry). " +
|
|
101
|
+
"Protected names always skipped.",
|
|
105
102
|
annotations: {
|
|
106
103
|
readOnlyHint: false,
|
|
107
104
|
destructiveHint: false,
|
|
@@ -112,8 +109,7 @@ export function registerGitCherryPickTool(server) {
|
|
|
112
109
|
.array(z.string().min(1))
|
|
113
110
|
.min(1)
|
|
114
111
|
.max(50)
|
|
115
|
-
.describe("Sources
|
|
116
|
-
"resolve to `onto..<branch>` (only commits missing from destination)."),
|
|
112
|
+
.describe("Sources: SHA, `A..B` range, or branch name (resolves to `onto..<branch>`)."),
|
|
117
113
|
onto: z
|
|
118
114
|
.string()
|
|
119
115
|
.optional()
|
|
@@ -122,24 +118,18 @@ export function registerGitCherryPickTool(server) {
|
|
|
122
118
|
.boolean()
|
|
123
119
|
.optional()
|
|
124
120
|
.default(false)
|
|
125
|
-
.describe("
|
|
126
|
-
"(`git branch -d`) when it is fully merged into the destination. " +
|
|
127
|
-
"Protected names always skipped; never touches remote refs."),
|
|
121
|
+
.describe("Delete branch-kind sources locally after success. Protected names and remote refs unaffected."),
|
|
128
122
|
deleteMergedWorktrees: z
|
|
129
123
|
.boolean()
|
|
130
124
|
.optional()
|
|
131
125
|
.default(false)
|
|
132
|
-
.describe("
|
|
133
|
-
"(`git worktree remove`). Protected tails always skipped."),
|
|
126
|
+
.describe("Remove local worktrees on branch-kind sources after success. Protected tails skipped."),
|
|
134
127
|
strictMergedRefEquality: z
|
|
135
128
|
.boolean()
|
|
136
129
|
.optional()
|
|
137
130
|
.default(false)
|
|
138
|
-
.describe("
|
|
139
|
-
"
|
|
140
|
-
"destination (same diff, different SHA — the normal cherry-pick outcome). " +
|
|
141
|
-
"Set to true to require strict ref ancestry (`git branch -d` semantics), which " +
|
|
142
|
-
"will refuse deletion after a cherry-pick because the SHA differs."),
|
|
131
|
+
.describe("false (default): delete branch when every commit is content-equivalent on destination (patch-id, normal cherry-pick outcome). " +
|
|
132
|
+
"true: require strict ref ancestry (`git branch -d` semantics — will refuse after cherry-pick due to SHA mismatch)."),
|
|
143
133
|
}),
|
|
144
134
|
execute: async (args) => {
|
|
145
135
|
const pre = requireSingleRepo(server, args);
|
|
@@ -218,7 +208,7 @@ export function registerGitCherryPickTool(server) {
|
|
|
218
208
|
if (allOk) {
|
|
219
209
|
for (let i = 0; i < perSourceReport.length; i++) {
|
|
220
210
|
const src = perSourceReport[i];
|
|
221
|
-
if (
|
|
211
|
+
if (src?.kind !== "branch")
|
|
222
212
|
continue;
|
|
223
213
|
if (isProtectedBranch(src.raw))
|
|
224
214
|
continue;
|
|
@@ -179,9 +179,8 @@ function rangeLabel(range, diffArgs) {
|
|
|
179
179
|
export function registerGitDiffSummaryTool(server) {
|
|
180
180
|
server.addTool({
|
|
181
181
|
name: "git_diff_summary",
|
|
182
|
-
description: "Structured
|
|
183
|
-
"
|
|
184
|
-
"Use `range` to target staged, HEAD, or any revision range.",
|
|
182
|
+
description: "Structured diff viewer: per-file diffs with counts, truncated to configurable limits. " +
|
|
183
|
+
"Noise files (lock files, dist, etc.) excluded by default. Use `range` to target staged, HEAD, or a revision range.",
|
|
185
184
|
annotations: {
|
|
186
185
|
readOnlyHint: true,
|
|
187
186
|
},
|
|
@@ -214,7 +213,7 @@ export function registerGitDiffSummaryTool(server) {
|
|
|
214
213
|
excludePatterns: z
|
|
215
214
|
.array(z.string())
|
|
216
215
|
.optional()
|
|
217
|
-
.describe("Glob patterns to exclude.
|
|
216
|
+
.describe("Glob patterns to exclude. Default: lock files, dist, vendor, etc."),
|
|
218
217
|
}),
|
|
219
218
|
execute: async (args) => {
|
|
220
219
|
const pre = requireSingleRepo(server, args);
|
|
@@ -61,10 +61,8 @@ function rangeLabel(opts) {
|
|
|
61
61
|
export function registerGitDiffTool(server) {
|
|
62
62
|
server.addTool({
|
|
63
63
|
name: "git_diff",
|
|
64
|
-
description: "
|
|
65
|
-
"
|
|
66
|
-
"`path` to scope to a single file, `paths` to scope to multiple files, " +
|
|
67
|
-
"and `unified` to control the number of context lines.",
|
|
64
|
+
description: "Raw diff text for scoped file(s) or range. `staged: true` for staged changes, " +
|
|
65
|
+
"`base`/`head` for revision ranges, `path`/`paths` to scope, `unified` for context lines.",
|
|
68
66
|
annotations: {
|
|
69
67
|
readOnlyHint: true,
|
|
70
68
|
},
|
|
@@ -75,37 +73,31 @@ export function registerGitDiffTool(server) {
|
|
|
75
73
|
base: z
|
|
76
74
|
.string()
|
|
77
75
|
.optional()
|
|
78
|
-
.describe('Base ref (e.g. "main", "HEAD~3").
|
|
79
|
-
"If omitted and `staged: false`, shows unstaged changes."),
|
|
76
|
+
.describe('Base ref (e.g. "main", "HEAD~3"). Omit for unstaged changes.'),
|
|
80
77
|
head: z
|
|
81
78
|
.string()
|
|
82
79
|
.optional()
|
|
83
|
-
.describe('Head ref (e.g. "feature-branch").
|
|
84
|
-
"Only used if `base` is provided."),
|
|
80
|
+
.describe('Head ref (e.g. "feature-branch"). Defaults to HEAD. Used only when `base` is set.'),
|
|
85
81
|
path: z
|
|
86
82
|
.string()
|
|
87
83
|
.optional()
|
|
88
|
-
.describe(
|
|
89
|
-
"For multiple files, prefer `paths`. If both `path` and `paths` are given, they are unioned."),
|
|
84
|
+
.describe("Scope to a single file. Unioned with `paths` if both given."),
|
|
90
85
|
paths: z
|
|
91
86
|
.array(z.string())
|
|
92
87
|
.optional()
|
|
93
|
-
.describe(
|
|
94
|
-
"Each path is validated and must lie within the repository root. " +
|
|
95
|
-
"If both `path` and `paths` are given, they are unioned."),
|
|
88
|
+
.describe("Scope to multiple files (must be within repo root). Unioned with `path` if both given."),
|
|
96
89
|
staged: z
|
|
97
90
|
.boolean()
|
|
98
91
|
.optional()
|
|
99
92
|
.default(false)
|
|
100
|
-
.describe("
|
|
93
|
+
.describe("Show staged changes (`git diff --staged`). Ignored if `base` is set."),
|
|
101
94
|
unified: z
|
|
102
95
|
.number()
|
|
103
96
|
.int()
|
|
104
97
|
.min(0)
|
|
105
98
|
.max(100)
|
|
106
99
|
.optional()
|
|
107
|
-
.describe("
|
|
108
|
-
"Defaults to git's built-in default (3). Use 0 for no context."),
|
|
100
|
+
.describe("Context lines around each change (`-U<n>`). Default: 3. Use 0 for no context."),
|
|
109
101
|
}),
|
|
110
102
|
execute: async (args) => {
|
|
111
103
|
const pre = requireSingleRepo(server, args);
|
|
@@ -176,8 +176,7 @@ function renderLogMarkdown(group, filterSummary) {
|
|
|
176
176
|
export function registerGitLogTool(server) {
|
|
177
177
|
server.addTool({
|
|
178
178
|
name: "git_log",
|
|
179
|
-
description: "
|
|
180
|
-
"Returns structured commit history with author, date, subject, and optional diff stats.",
|
|
179
|
+
description: "Read-only `git log` across one or more roots. Returns author, date, subject, optional diff stats.",
|
|
181
180
|
annotations: {
|
|
182
181
|
readOnlyHint: true,
|
|
183
182
|
},
|
|
@@ -186,26 +185,21 @@ export function registerGitLogTool(server) {
|
|
|
186
185
|
.enum(["markdown", "json", "oneline"])
|
|
187
186
|
.optional()
|
|
188
187
|
.default("markdown")
|
|
189
|
-
.describe("`markdown` (default): headed sections per root. " +
|
|
190
|
-
"`
|
|
191
|
-
"`oneline`: `<sha7> <subject>` per line, no headers (single-root) or `### repo (branch)` separator per group (multi-root). Lowest-token option for post-commit verification."),
|
|
188
|
+
.describe("`markdown` (default): headed sections per root. `json`: groups array. " +
|
|
189
|
+
"`oneline`: `<sha7> <subject>` per line; lowest-token option for post-commit verification."),
|
|
192
190
|
since: z
|
|
193
191
|
.string()
|
|
194
192
|
.optional()
|
|
195
|
-
.describe("Passed to
|
|
196
|
-
"`48.hours` or `2.weeks.ago`. Default: `7.days`."),
|
|
193
|
+
.describe("Passed to `--since=`. ISO timestamp or git relative form (`48.hours`, `2.weeks.ago`). Default: `7.days`."),
|
|
197
194
|
paths: z
|
|
198
195
|
.array(z.string())
|
|
199
196
|
.optional()
|
|
200
|
-
.describe("Limit to commits touching these paths (
|
|
197
|
+
.describe("Limit to commits touching these paths (`-- <paths>`)."),
|
|
201
198
|
grep: z
|
|
202
199
|
.string()
|
|
203
200
|
.optional()
|
|
204
|
-
.describe("Filter
|
|
205
|
-
author: z
|
|
206
|
-
.string()
|
|
207
|
-
.optional()
|
|
208
|
-
.describe("Filter by author name or email (passed as `--author=`)."),
|
|
201
|
+
.describe("Filter by commit message regex (git `--grep`, case-insensitive)."),
|
|
202
|
+
author: z.string().optional().describe("Filter by author name or email (`--author=`)."),
|
|
209
203
|
maxCommits: z
|
|
210
204
|
.number()
|
|
211
205
|
.int()
|
|
@@ -213,7 +207,7 @@ export function registerGitLogTool(server) {
|
|
|
213
207
|
.max(MAX_COMMITS_HARD_CAP)
|
|
214
208
|
.optional()
|
|
215
209
|
.default(DEFAULT_MAX_COMMITS)
|
|
216
|
-
.describe(`
|
|
210
|
+
.describe(`Max commits per root (hard cap ${MAX_COMMITS_HARD_CAP}, default ${DEFAULT_MAX_COMMITS}).`),
|
|
217
211
|
branch: z.string().optional().describe("Ref/branch to log from. Default: HEAD."),
|
|
218
212
|
}),
|
|
219
213
|
execute: async (args) => {
|
|
@@ -207,12 +207,10 @@ async function maybeDeleteBranch(gitTop, source, enabled, into) {
|
|
|
207
207
|
export function registerGitMergeTool(server) {
|
|
208
208
|
server.addTool({
|
|
209
209
|
name: "git_merge",
|
|
210
|
-
description: "Merge one or more source branches into a destination.
|
|
211
|
-
"
|
|
212
|
-
"Refuses
|
|
213
|
-
"
|
|
214
|
-
"skipping protected names (main, master, dev, develop, stable, trunk, prod, " +
|
|
215
|
-
"production, release/*, hotfix/*).",
|
|
210
|
+
description: "Merge one or more source branches into a destination. `auto` cascades " +
|
|
211
|
+
"fast-forward → rebase → merge-commit, preferring linear history. " +
|
|
212
|
+
"Refuses on dirty tree; stops on first conflict. Optional flags delete merged branches/worktrees " +
|
|
213
|
+
"(protected names skipped: main, master, dev, develop, stable, trunk, prod, production, release/*, hotfix/*).",
|
|
216
214
|
annotations: {
|
|
217
215
|
readOnlyHint: false,
|
|
218
216
|
destructiveHint: false,
|
|
@@ -237,14 +235,12 @@ export function registerGitMergeTool(server) {
|
|
|
237
235
|
.boolean()
|
|
238
236
|
.optional()
|
|
239
237
|
.default(false)
|
|
240
|
-
.describe("
|
|
241
|
-
"Protected names always skipped. Never affects remote branches."),
|
|
238
|
+
.describe("Delete each source branch locally after clean merge (`git branch -d`). Protected names and remote refs unaffected."),
|
|
242
239
|
deleteMergedWorktrees: z
|
|
243
240
|
.boolean()
|
|
244
241
|
.optional()
|
|
245
242
|
.default(false)
|
|
246
|
-
.describe("
|
|
247
|
-
"on a source branch (`git worktree remove`). Protected tails always skipped."),
|
|
243
|
+
.describe("Remove local worktrees on source branches after clean merge (`git worktree remove`). Protected tails skipped."),
|
|
248
244
|
}),
|
|
249
245
|
execute: async (args) => {
|
|
250
246
|
const pre = requireSingleRepo(server, args);
|
|
@@ -8,10 +8,8 @@ import { WorkspacePickSchema } from "./schemas.js";
|
|
|
8
8
|
export function registerGitResetSoftTool(server) {
|
|
9
9
|
server.addTool({
|
|
10
10
|
name: "git_reset_soft",
|
|
11
|
-
description: "
|
|
12
|
-
"
|
|
13
|
-
"in the staging index — use this to re-split an already-committed chunk. " +
|
|
14
|
-
"Refuses when the working tree has any uncommitted or unstaged changes (run on a clean tree).",
|
|
11
|
+
description: "`git reset --soft <ref>`: moves HEAD back while keeping rewound changes staged. " +
|
|
12
|
+
"Use to re-split committed work. Refuses on a dirty tree.",
|
|
15
13
|
annotations: {
|
|
16
14
|
readOnlyHint: false,
|
|
17
15
|
destructiveHint: false,
|
|
@@ -21,8 +19,7 @@ export function registerGitResetSoftTool(server) {
|
|
|
21
19
|
ref: z
|
|
22
20
|
.string()
|
|
23
21
|
.min(1)
|
|
24
|
-
.describe("Commit to reset to
|
|
25
|
-
"branch names, or full SHAs."),
|
|
22
|
+
.describe("Commit to reset to: ancestor notation (`HEAD~1`, `HEAD~3`), branch name, or SHA."),
|
|
26
23
|
}),
|
|
27
24
|
execute: async (args) => {
|
|
28
25
|
const pre = requireSingleRepo(server, args);
|
|
@@ -10,7 +10,7 @@ import { WorkspacePickSchema } from "./schemas.js";
|
|
|
10
10
|
export function registerGitStashListTool(server) {
|
|
11
11
|
server.addTool({
|
|
12
12
|
name: "git_stash_list",
|
|
13
|
-
description: "List all git stashes.
|
|
13
|
+
description: "List all git stashes.",
|
|
14
14
|
annotations: {
|
|
15
15
|
readOnlyHint: true,
|
|
16
16
|
},
|
|
@@ -77,9 +77,7 @@ export function registerGitStashListTool(server) {
|
|
|
77
77
|
export function registerGitStashApplyTool(server) {
|
|
78
78
|
server.addTool({
|
|
79
79
|
name: "git_stash_apply",
|
|
80
|
-
description: "Apply or pop a git stash. `index` defaults to 0
|
|
81
|
-
"Set `pop: true` to run `git stash pop` instead of `git stash apply` (removes stash after applying). " +
|
|
82
|
-
"Returns `{ applied: boolean, stashIndex: number, popped: boolean, output: string }`.",
|
|
80
|
+
description: "Apply or pop a git stash. `index` defaults to 0. `pop: true` removes stash after applying.",
|
|
83
81
|
annotations: {
|
|
84
82
|
readOnlyHint: false,
|
|
85
83
|
destructiveHint: false,
|
|
@@ -103,7 +101,7 @@ export function registerGitStashApplyTool(server) {
|
|
|
103
101
|
.boolean()
|
|
104
102
|
.optional()
|
|
105
103
|
.default(false)
|
|
106
|
-
.describe("
|
|
104
|
+
.describe("Run `git stash pop` instead of `git stash apply` (removes stash after applying)."),
|
|
107
105
|
}),
|
|
108
106
|
execute: async (args) => {
|
|
109
107
|
const pre = requireSingleRepo(server, args);
|
|
@@ -49,8 +49,7 @@ export function registerGitWorktreeListTool(server) {
|
|
|
49
49
|
export function registerGitWorktreeAddTool(server) {
|
|
50
50
|
server.addTool({
|
|
51
51
|
name: "git_worktree_add",
|
|
52
|
-
description: "Add a new git worktree.
|
|
53
|
-
"(defaults to HEAD). Refuses to create on a protected branch name.",
|
|
52
|
+
description: "Add a new git worktree. Creates `branch` from `baseRef` (default: HEAD) if it doesn't exist. Refuses protected branch names.",
|
|
54
53
|
annotations: {
|
|
55
54
|
readOnlyHint: false,
|
|
56
55
|
destructiveHint: false,
|
|
@@ -60,15 +59,15 @@ export function registerGitWorktreeAddTool(server) {
|
|
|
60
59
|
path: z
|
|
61
60
|
.string()
|
|
62
61
|
.min(1)
|
|
63
|
-
.describe("Filesystem path for the new worktree
|
|
62
|
+
.describe("Filesystem path for the new worktree (relative paths resolved from git toplevel)."),
|
|
64
63
|
branch: z
|
|
65
64
|
.string()
|
|
66
65
|
.min(1)
|
|
67
|
-
.describe("Branch to check out
|
|
66
|
+
.describe("Branch to check out; created from `baseRef` if it doesn't exist."),
|
|
68
67
|
baseRef: z
|
|
69
68
|
.string()
|
|
70
69
|
.optional()
|
|
71
|
-
.describe("Commit-ish to base the new branch on
|
|
70
|
+
.describe("Commit-ish to base the new branch on. Default: HEAD."),
|
|
72
71
|
}),
|
|
73
72
|
execute: async (args) => {
|
|
74
73
|
const pre = requireSingleRepo(server, args);
|
|
@@ -132,9 +131,7 @@ export function registerGitWorktreeAddTool(server) {
|
|
|
132
131
|
export function registerGitWorktreeRemoveTool(server) {
|
|
133
132
|
server.addTool({
|
|
134
133
|
name: "git_worktree_remove",
|
|
135
|
-
description: "Remove a git worktree
|
|
136
|
-
"Pass `force: true` to remove a worktree with uncommitted changes. " +
|
|
137
|
-
"Refuses to remove the main worktree.",
|
|
134
|
+
description: "Remove a git worktree. Pass `force: true` to remove with uncommitted changes. Refuses to remove the main worktree.",
|
|
138
135
|
annotations: {
|
|
139
136
|
readOnlyHint: false,
|
|
140
137
|
destructiveHint: true,
|
|
@@ -149,7 +146,7 @@ export function registerGitWorktreeRemoveTool(server) {
|
|
|
149
146
|
.boolean()
|
|
150
147
|
.optional()
|
|
151
148
|
.default(false)
|
|
152
|
-
.describe("
|
|
149
|
+
.describe("Allow removal of worktrees with uncommitted changes (`--force`)."),
|
|
153
150
|
}),
|
|
154
151
|
execute: async (args) => {
|
|
155
152
|
const pre = requireSingleRepo(server, args);
|
package/dist/server/schemas.js
CHANGED
|
@@ -4,24 +4,24 @@ const FormatSchema = z.enum(["markdown", "json"]).optional().default("markdown")
|
|
|
4
4
|
/** Max paths in `absoluteGitRoots` (matches `git_inventory` `maxRoots` hard cap). */
|
|
5
5
|
export const MAX_ABSOLUTE_GIT_ROOTS = 256;
|
|
6
6
|
export const WorkspacePickSchema = z.object({
|
|
7
|
-
workspaceRoot: z.string().optional().describe("Highest-priority override."),
|
|
7
|
+
workspaceRoot: z.string().optional().describe("Highest-priority root override."),
|
|
8
8
|
rootIndex: z
|
|
9
9
|
.number()
|
|
10
10
|
.int()
|
|
11
11
|
.min(0)
|
|
12
12
|
.optional()
|
|
13
|
-
.describe("0-based index into
|
|
13
|
+
.describe("0-based index into MCP roots; ignored if workspaceRoot set."),
|
|
14
14
|
allWorkspaceRoots: z
|
|
15
15
|
.boolean()
|
|
16
16
|
.optional()
|
|
17
17
|
.default(false)
|
|
18
|
-
.describe("Fan out across all MCP
|
|
18
|
+
.describe("Fan out across all MCP roots."),
|
|
19
19
|
/** Independent git worktrees (sibling clones). Mutually exclusive with workspaceRoot, rootIndex, allWorkspaceRoots, and (git_inventory) preset/nestedRoots. */
|
|
20
20
|
absoluteGitRoots: z
|
|
21
21
|
.array(z.string())
|
|
22
22
|
.max(MAX_ABSOLUTE_GIT_ROOTS)
|
|
23
23
|
.optional()
|
|
24
|
-
.describe("Absolute paths to git repo roots
|
|
24
|
+
.describe("Absolute paths to git repo roots; use for sibling clones under a non-git parent."),
|
|
25
25
|
format: FormatSchema,
|
|
26
26
|
});
|
|
27
27
|
export { MAX_INVENTORY_ROOTS_DEFAULT };
|
package/docs/mcp-tools.md
CHANGED
|
@@ -666,7 +666,7 @@ Do NOT do this: make two separate calls hoping to stage files incrementally. Tha
|
|
|
666
666
|
| Parameter | Type | Notes |
|
|
667
667
|
|-----------|------|-------|
|
|
668
668
|
| `commits` | `{message: string, files: (string \| {path: string, lines: {from: number, to: number}})[]}[]` | Commits to create in order. 1–50 entries. Each `files` entry is either: (a) a path relative to the git root, staged with `git add`; (b) a `{path, lines: {from, to}}` object for hunk-level staging — only unified-diff hunks overlapping the given 1-indexed line range are staged; or (c) a path to a **deleted tracked file** (missing on disk but tracked in HEAD), which is staged as a removal via `git rm --cached` — combining `{path, lines}` with a deleted file is an error. All paths must stay within the git toplevel. |
|
|
669
|
-
| `push` | `"never"` \| `"after"` | Default `"never"`. `"after"` pushes the current branch to its upstream **once all commits succeed**. Never auto-sets upstream — branches without an upstream fail with `push_no_upstream`. Commits are **not** rolled back on push failure.
|
|
669
|
+
| `push` | `"never"` \| `"after"` | Default `"never"`. `"after"` pushes the current branch to its upstream **once all commits succeed**. Never auto-sets upstream — branches without an upstream fail with `push_no_upstream`. Commits are **not** rolled back on push failure. |
|
|
670
670
|
| `dryRun` | boolean | Default `false`. When `true`, stages each entry, reports what would be committed (`staged`, `diffStat`), then unstages everything without writing commits. |
|
|
671
671
|
| `workspaceRoot` | string | Explicit root; highest priority. |
|
|
672
672
|
| `rootIndex` | int | Pick one of several MCP roots (0-based). |
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rethunk/mcp-multi-root-git",
|
|
3
|
-
"version": "2.8.
|
|
3
|
+
"version": "2.8.1",
|
|
4
4
|
"description": "MCP stdio server: multi-root git status, inventory, and HEAD parity checks. Generic tools usable by any workspace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
7
|
-
"packageManager": "bun@1.3.
|
|
7
|
+
"packageManager": "bun@1.3.14",
|
|
8
8
|
"engines": {
|
|
9
9
|
"node": ">=22.0.0"
|
|
10
10
|
},
|
|
@@ -31,8 +31,6 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "rimraf dist && tsc",
|
|
34
|
-
"check": "biome check .",
|
|
35
|
-
"check:fix": "biome check --write .",
|
|
36
34
|
"coverage:check": "bun scripts/check-coverage.ts",
|
|
37
35
|
"schema:tools": "bun scripts/generate-tool-parameters-schema.ts",
|
|
38
36
|
"schema:tools:check": "bun scripts/generate-tool-parameters-schema.ts --check",
|
|
@@ -41,8 +39,12 @@
|
|
|
41
39
|
"publish:preflight": "bun scripts/publish-preflight.ts",
|
|
42
40
|
"test": "bun test src/",
|
|
43
41
|
"test:coverage": "bun test src/ --coverage",
|
|
44
|
-
"prepublishOnly": "bun run
|
|
45
|
-
"setup-hooks": "git config core.hooksPath .githooks"
|
|
42
|
+
"prepublishOnly": "bun run ci",
|
|
43
|
+
"setup-hooks": "git config core.hooksPath .githooks",
|
|
44
|
+
"lint": "biome check .",
|
|
45
|
+
"format": "biome check --write .",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"ci": "bun run schema:tools:check && bun run lint && bun run typecheck && bun run test && bun run build"
|
|
46
48
|
},
|
|
47
49
|
"keywords": [
|
|
48
50
|
"mcp",
|
|
@@ -77,11 +79,6 @@
|
|
|
77
79
|
"overrides": {
|
|
78
80
|
"@hono/node-server": "^1.19.14",
|
|
79
81
|
"hono": "^4.12.18",
|
|
80
|
-
"fast-uri": "^3.1.2"
|
|
81
|
-
"postcss": "^8.5.10",
|
|
82
|
-
"vite": "^7.3.2",
|
|
83
|
-
"ip-address": "^10.1.1",
|
|
84
|
-
"axios": "^1.15.2",
|
|
85
|
-
"follow-redirects": "^1.15.12"
|
|
82
|
+
"fast-uri": "^3.1.2"
|
|
86
83
|
}
|
|
87
84
|
}
|
|
@@ -9,22 +9,22 @@
|
|
|
9
9
|
"type": "object",
|
|
10
10
|
"properties": {
|
|
11
11
|
"workspaceRoot": {
|
|
12
|
-
"description": "Highest-priority override.",
|
|
12
|
+
"description": "Highest-priority root override.",
|
|
13
13
|
"type": "string"
|
|
14
14
|
},
|
|
15
15
|
"rootIndex": {
|
|
16
|
-
"description": "0-based index into
|
|
16
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
17
17
|
"type": "integer",
|
|
18
18
|
"minimum": 0,
|
|
19
19
|
"maximum": 9007199254740991
|
|
20
20
|
},
|
|
21
21
|
"allWorkspaceRoots": {
|
|
22
22
|
"default": false,
|
|
23
|
-
"description": "Fan out across all MCP
|
|
23
|
+
"description": "Fan out across all MCP roots.",
|
|
24
24
|
"type": "boolean"
|
|
25
25
|
},
|
|
26
26
|
"absoluteGitRoots": {
|
|
27
|
-
"description": "Absolute paths to git repo roots
|
|
27
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
28
28
|
"maxItems": 256,
|
|
29
29
|
"type": "array",
|
|
30
30
|
"items": {
|
|
@@ -56,22 +56,22 @@
|
|
|
56
56
|
"type": "object",
|
|
57
57
|
"properties": {
|
|
58
58
|
"workspaceRoot": {
|
|
59
|
-
"description": "Highest-priority override.",
|
|
59
|
+
"description": "Highest-priority root override.",
|
|
60
60
|
"type": "string"
|
|
61
61
|
},
|
|
62
62
|
"rootIndex": {
|
|
63
|
-
"description": "0-based index into
|
|
63
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
64
64
|
"type": "integer",
|
|
65
65
|
"minimum": 0,
|
|
66
66
|
"maximum": 9007199254740991
|
|
67
67
|
},
|
|
68
68
|
"allWorkspaceRoots": {
|
|
69
69
|
"default": false,
|
|
70
|
-
"description": "Fan out across all MCP
|
|
70
|
+
"description": "Fan out across all MCP roots.",
|
|
71
71
|
"type": "boolean"
|
|
72
72
|
},
|
|
73
73
|
"absoluteGitRoots": {
|
|
74
|
-
"description": "Absolute paths to git repo roots
|
|
74
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
75
75
|
"maxItems": 256,
|
|
76
76
|
"type": "array",
|
|
77
77
|
"items": {
|
|
@@ -128,22 +128,22 @@
|
|
|
128
128
|
"type": "object",
|
|
129
129
|
"properties": {
|
|
130
130
|
"workspaceRoot": {
|
|
131
|
-
"description": "Highest-priority override.",
|
|
131
|
+
"description": "Highest-priority root override.",
|
|
132
132
|
"type": "string"
|
|
133
133
|
},
|
|
134
134
|
"rootIndex": {
|
|
135
|
-
"description": "0-based index into
|
|
135
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
136
136
|
"type": "integer",
|
|
137
137
|
"minimum": 0,
|
|
138
138
|
"maximum": 9007199254740991
|
|
139
139
|
},
|
|
140
140
|
"allWorkspaceRoots": {
|
|
141
141
|
"default": false,
|
|
142
|
-
"description": "Fan out across all MCP
|
|
142
|
+
"description": "Fan out across all MCP roots.",
|
|
143
143
|
"type": "boolean"
|
|
144
144
|
},
|
|
145
145
|
"absoluteGitRoots": {
|
|
146
|
-
"description": "Absolute paths to git repo roots
|
|
146
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
147
147
|
"maxItems": 256,
|
|
148
148
|
"type": "array",
|
|
149
149
|
"items": {
|
|
@@ -200,22 +200,22 @@
|
|
|
200
200
|
"type": "object",
|
|
201
201
|
"properties": {
|
|
202
202
|
"workspaceRoot": {
|
|
203
|
-
"description": "Highest-priority override.",
|
|
203
|
+
"description": "Highest-priority root override.",
|
|
204
204
|
"type": "string"
|
|
205
205
|
},
|
|
206
206
|
"rootIndex": {
|
|
207
|
-
"description": "0-based index into
|
|
207
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
208
208
|
"type": "integer",
|
|
209
209
|
"minimum": 0,
|
|
210
210
|
"maximum": 9007199254740991
|
|
211
211
|
},
|
|
212
212
|
"allWorkspaceRoots": {
|
|
213
213
|
"default": false,
|
|
214
|
-
"description": "Fan out across all MCP
|
|
214
|
+
"description": "Fan out across all MCP roots.",
|
|
215
215
|
"type": "boolean"
|
|
216
216
|
},
|
|
217
217
|
"absoluteGitRoots": {
|
|
218
|
-
"description": "Absolute paths to git repo roots
|
|
218
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
219
219
|
"maxItems": 256,
|
|
220
220
|
"type": "array",
|
|
221
221
|
"items": {
|
|
@@ -242,22 +242,22 @@
|
|
|
242
242
|
"type": "object",
|
|
243
243
|
"properties": {
|
|
244
244
|
"workspaceRoot": {
|
|
245
|
-
"description": "Highest-priority override.",
|
|
245
|
+
"description": "Highest-priority root override.",
|
|
246
246
|
"type": "string"
|
|
247
247
|
},
|
|
248
248
|
"rootIndex": {
|
|
249
|
-
"description": "0-based index into
|
|
249
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
250
250
|
"type": "integer",
|
|
251
251
|
"minimum": 0,
|
|
252
252
|
"maximum": 9007199254740991
|
|
253
253
|
},
|
|
254
254
|
"allWorkspaceRoots": {
|
|
255
255
|
"default": false,
|
|
256
|
-
"description": "Fan out across all MCP
|
|
256
|
+
"description": "Fan out across all MCP roots.",
|
|
257
257
|
"type": "boolean"
|
|
258
258
|
},
|
|
259
259
|
"absoluteGitRoots": {
|
|
260
|
-
"description": "Absolute paths to git repo roots
|
|
260
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
261
261
|
"maxItems": 256,
|
|
262
262
|
"type": "array",
|
|
263
263
|
"items": {
|
|
@@ -266,7 +266,7 @@
|
|
|
266
266
|
},
|
|
267
267
|
"format": {
|
|
268
268
|
"default": "markdown",
|
|
269
|
-
"description": "`markdown` (default): headed sections per root. `json`:
|
|
269
|
+
"description": "`markdown` (default): headed sections per root. `json`: groups array. `oneline`: `<sha7> <subject>` per line; lowest-token option for post-commit verification.",
|
|
270
270
|
"type": "string",
|
|
271
271
|
"enum": [
|
|
272
272
|
"markdown",
|
|
@@ -275,27 +275,27 @@
|
|
|
275
275
|
]
|
|
276
276
|
},
|
|
277
277
|
"since": {
|
|
278
|
-
"description": "Passed to
|
|
278
|
+
"description": "Passed to `--since=`. ISO timestamp or git relative form (`48.hours`, `2.weeks.ago`). Default: `7.days`.",
|
|
279
279
|
"type": "string"
|
|
280
280
|
},
|
|
281
281
|
"paths": {
|
|
282
|
-
"description": "Limit to commits touching these paths (
|
|
282
|
+
"description": "Limit to commits touching these paths (`-- <paths>`).",
|
|
283
283
|
"type": "array",
|
|
284
284
|
"items": {
|
|
285
285
|
"type": "string"
|
|
286
286
|
}
|
|
287
287
|
},
|
|
288
288
|
"grep": {
|
|
289
|
-
"description": "Filter
|
|
289
|
+
"description": "Filter by commit message regex (git `--grep`, case-insensitive).",
|
|
290
290
|
"type": "string"
|
|
291
291
|
},
|
|
292
292
|
"author": {
|
|
293
|
-
"description": "Filter by author name or email (
|
|
293
|
+
"description": "Filter by author name or email (`--author=`).",
|
|
294
294
|
"type": "string"
|
|
295
295
|
},
|
|
296
296
|
"maxCommits": {
|
|
297
297
|
"default": 50,
|
|
298
|
-
"description": "
|
|
298
|
+
"description": "Max commits per root (hard cap 500, default 50).",
|
|
299
299
|
"type": "integer",
|
|
300
300
|
"minimum": 1,
|
|
301
301
|
"maximum": 500
|
|
@@ -317,17 +317,17 @@
|
|
|
317
317
|
"type": "object",
|
|
318
318
|
"properties": {
|
|
319
319
|
"workspaceRoot": {
|
|
320
|
-
"description": "Highest-priority override.",
|
|
320
|
+
"description": "Highest-priority root override.",
|
|
321
321
|
"type": "string"
|
|
322
322
|
},
|
|
323
323
|
"rootIndex": {
|
|
324
|
-
"description": "0-based index into
|
|
324
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
325
325
|
"type": "integer",
|
|
326
326
|
"minimum": 0,
|
|
327
327
|
"maximum": 9007199254740991
|
|
328
328
|
},
|
|
329
329
|
"absoluteGitRoots": {
|
|
330
|
-
"description": "Absolute paths to git repo roots
|
|
330
|
+
"description": "Absolute paths to git repo roots; use for sibling clones under a non-git parent.",
|
|
331
331
|
"maxItems": 256,
|
|
332
332
|
"type": "array",
|
|
333
333
|
"items": {
|
|
@@ -365,7 +365,7 @@
|
|
|
365
365
|
"maximum": 500
|
|
366
366
|
},
|
|
367
367
|
"excludePatterns": {
|
|
368
|
-
"description": "Glob patterns to exclude.
|
|
368
|
+
"description": "Glob patterns to exclude. Default: lock files, dist, vendor, etc.",
|
|
369
369
|
"type": "array",
|
|
370
370
|
"items": {
|
|
371
371
|
"type": "string"
|
|
@@ -384,11 +384,11 @@
|
|
|
384
384
|
"type": "object",
|
|
385
385
|
"properties": {
|
|
386
386
|
"workspaceRoot": {
|
|
387
|
-
"description": "Highest-priority override.",
|
|
387
|
+
"description": "Highest-priority root override.",
|
|
388
388
|
"type": "string"
|
|
389
389
|
},
|
|
390
390
|
"rootIndex": {
|
|
391
|
-
"description": "0-based index into
|
|
391
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
392
392
|
"type": "integer",
|
|
393
393
|
"minimum": 0,
|
|
394
394
|
"maximum": 9007199254740991
|
|
@@ -402,19 +402,19 @@
|
|
|
402
402
|
]
|
|
403
403
|
},
|
|
404
404
|
"base": {
|
|
405
|
-
"description": "Base ref (e.g. \"main\", \"HEAD~3\").
|
|
405
|
+
"description": "Base ref (e.g. \"main\", \"HEAD~3\"). Omit for unstaged changes.",
|
|
406
406
|
"type": "string"
|
|
407
407
|
},
|
|
408
408
|
"head": {
|
|
409
|
-
"description": "Head ref (e.g. \"feature-branch\").
|
|
409
|
+
"description": "Head ref (e.g. \"feature-branch\"). Defaults to HEAD. Used only when `base` is set.",
|
|
410
410
|
"type": "string"
|
|
411
411
|
},
|
|
412
412
|
"path": {
|
|
413
|
-
"description": "Scope
|
|
413
|
+
"description": "Scope to a single file. Unioned with `paths` if both given.",
|
|
414
414
|
"type": "string"
|
|
415
415
|
},
|
|
416
416
|
"paths": {
|
|
417
|
-
"description": "Scope
|
|
417
|
+
"description": "Scope to multiple files (must be within repo root). Unioned with `path` if both given.",
|
|
418
418
|
"type": "array",
|
|
419
419
|
"items": {
|
|
420
420
|
"type": "string"
|
|
@@ -422,11 +422,11 @@
|
|
|
422
422
|
},
|
|
423
423
|
"staged": {
|
|
424
424
|
"default": false,
|
|
425
|
-
"description": "
|
|
425
|
+
"description": "Show staged changes (`git diff --staged`). Ignored if `base` is set.",
|
|
426
426
|
"type": "boolean"
|
|
427
427
|
},
|
|
428
428
|
"unified": {
|
|
429
|
-
"description": "
|
|
429
|
+
"description": "Context lines around each change (`-U<n>`). Default: 3. Use 0 for no context.",
|
|
430
430
|
"type": "integer",
|
|
431
431
|
"minimum": 0,
|
|
432
432
|
"maximum": 100
|
|
@@ -443,11 +443,11 @@
|
|
|
443
443
|
"type": "object",
|
|
444
444
|
"properties": {
|
|
445
445
|
"workspaceRoot": {
|
|
446
|
-
"description": "Highest-priority override.",
|
|
446
|
+
"description": "Highest-priority root override.",
|
|
447
447
|
"type": "string"
|
|
448
448
|
},
|
|
449
449
|
"rootIndex": {
|
|
450
|
-
"description": "0-based index into
|
|
450
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
451
451
|
"type": "integer",
|
|
452
452
|
"minimum": 0,
|
|
453
453
|
"maximum": 9007199254740991
|
|
@@ -492,11 +492,11 @@
|
|
|
492
492
|
"type": "object",
|
|
493
493
|
"properties": {
|
|
494
494
|
"workspaceRoot": {
|
|
495
|
-
"description": "Highest-priority override.",
|
|
495
|
+
"description": "Highest-priority root override.",
|
|
496
496
|
"type": "string"
|
|
497
497
|
},
|
|
498
498
|
"rootIndex": {
|
|
499
|
-
"description": "0-based index into
|
|
499
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
500
500
|
"type": "integer",
|
|
501
501
|
"minimum": 0,
|
|
502
502
|
"maximum": 9007199254740991
|
|
@@ -520,11 +520,11 @@
|
|
|
520
520
|
"type": "object",
|
|
521
521
|
"properties": {
|
|
522
522
|
"workspaceRoot": {
|
|
523
|
-
"description": "Highest-priority override.",
|
|
523
|
+
"description": "Highest-priority root override.",
|
|
524
524
|
"type": "string"
|
|
525
525
|
},
|
|
526
526
|
"rootIndex": {
|
|
527
|
-
"description": "0-based index into
|
|
527
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
528
528
|
"type": "integer",
|
|
529
529
|
"minimum": 0,
|
|
530
530
|
"maximum": 9007199254740991
|
|
@@ -548,11 +548,11 @@
|
|
|
548
548
|
"type": "object",
|
|
549
549
|
"properties": {
|
|
550
550
|
"workspaceRoot": {
|
|
551
|
-
"description": "Highest-priority override.",
|
|
551
|
+
"description": "Highest-priority root override.",
|
|
552
552
|
"type": "string"
|
|
553
553
|
},
|
|
554
554
|
"rootIndex": {
|
|
555
|
-
"description": "0-based index into
|
|
555
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
556
556
|
"type": "integer",
|
|
557
557
|
"minimum": 0,
|
|
558
558
|
"maximum": 9007199254740991
|
|
@@ -598,11 +598,11 @@
|
|
|
598
598
|
"type": "object",
|
|
599
599
|
"properties": {
|
|
600
600
|
"workspaceRoot": {
|
|
601
|
-
"description": "Highest-priority override.",
|
|
601
|
+
"description": "Highest-priority root override.",
|
|
602
602
|
"type": "string"
|
|
603
603
|
},
|
|
604
604
|
"rootIndex": {
|
|
605
|
-
"description": "0-based index into
|
|
605
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
606
606
|
"type": "integer",
|
|
607
607
|
"minimum": 0,
|
|
608
608
|
"maximum": 9007199254740991
|
|
@@ -648,11 +648,11 @@
|
|
|
648
648
|
"type": "object",
|
|
649
649
|
"properties": {
|
|
650
650
|
"workspaceRoot": {
|
|
651
|
-
"description": "Highest-priority override.",
|
|
651
|
+
"description": "Highest-priority root override.",
|
|
652
652
|
"type": "string"
|
|
653
653
|
},
|
|
654
654
|
"rootIndex": {
|
|
655
|
-
"description": "0-based index into
|
|
655
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
656
656
|
"type": "integer",
|
|
657
657
|
"minimum": 0,
|
|
658
658
|
"maximum": 9007199254740991
|
|
@@ -667,7 +667,7 @@
|
|
|
667
667
|
},
|
|
668
668
|
"includeRemotes": {
|
|
669
669
|
"default": false,
|
|
670
|
-
"description": "
|
|
670
|
+
"description": "Include remote-tracking branches from refs/remotes (symbolic origin/HEAD excluded).",
|
|
671
671
|
"type": "boolean"
|
|
672
672
|
}
|
|
673
673
|
},
|
|
@@ -682,11 +682,11 @@
|
|
|
682
682
|
"type": "object",
|
|
683
683
|
"properties": {
|
|
684
684
|
"workspaceRoot": {
|
|
685
|
-
"description": "Highest-priority override.",
|
|
685
|
+
"description": "Highest-priority root override.",
|
|
686
686
|
"type": "string"
|
|
687
687
|
},
|
|
688
688
|
"rootIndex": {
|
|
689
|
-
"description": "0-based index into
|
|
689
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
690
690
|
"type": "integer",
|
|
691
691
|
"minimum": 0,
|
|
692
692
|
"maximum": 9007199254740991
|
|
@@ -724,18 +724,18 @@
|
|
|
724
724
|
"type": "object",
|
|
725
725
|
"properties": {
|
|
726
726
|
"workspaceRoot": {
|
|
727
|
-
"description": "Highest-priority override.",
|
|
727
|
+
"description": "Highest-priority root override.",
|
|
728
728
|
"type": "string"
|
|
729
729
|
},
|
|
730
730
|
"rootIndex": {
|
|
731
|
-
"description": "0-based index into
|
|
731
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
732
732
|
"type": "integer",
|
|
733
733
|
"minimum": 0,
|
|
734
734
|
"maximum": 9007199254740991
|
|
735
735
|
},
|
|
736
736
|
"allWorkspaceRoots": {
|
|
737
737
|
"default": false,
|
|
738
|
-
"description": "Fan out across all MCP
|
|
738
|
+
"description": "Fan out across all MCP roots.",
|
|
739
739
|
"type": "boolean"
|
|
740
740
|
},
|
|
741
741
|
"format": {
|
|
@@ -807,7 +807,7 @@
|
|
|
807
807
|
}
|
|
808
808
|
]
|
|
809
809
|
},
|
|
810
|
-
"description": "Paths to stage, relative to
|
|
810
|
+
"description": "Paths to stage, relative to git root. String or `{ path, lines }` for hunk-level staging. Deleted tracked files are staged via `git rm --cached`. Cannot combine `lines` with a deleted file."
|
|
811
811
|
}
|
|
812
812
|
},
|
|
813
813
|
"required": [
|
|
@@ -816,11 +816,11 @@
|
|
|
816
816
|
],
|
|
817
817
|
"additionalProperties": false
|
|
818
818
|
},
|
|
819
|
-
"description": "
|
|
819
|
+
"description": "Ordered list of commits to create."
|
|
820
820
|
},
|
|
821
821
|
"push": {
|
|
822
822
|
"default": "never",
|
|
823
|
-
"description": "`never` (default): no push. `after`: push
|
|
823
|
+
"description": "`never` (default): no push. `after`: push current branch to upstream after all commits succeed; fails with `push_no_upstream` if no upstream (commits are NOT rolled back).",
|
|
824
824
|
"type": "string",
|
|
825
825
|
"enum": [
|
|
826
826
|
"never",
|
|
@@ -829,7 +829,7 @@
|
|
|
829
829
|
},
|
|
830
830
|
"dryRun": {
|
|
831
831
|
"default": false,
|
|
832
|
-
"description": "
|
|
832
|
+
"description": "Stage files and return a preview without writing commits; unstages afterwards. Response is marked DRY RUN.",
|
|
833
833
|
"type": "boolean"
|
|
834
834
|
}
|
|
835
835
|
},
|
|
@@ -847,18 +847,18 @@
|
|
|
847
847
|
"type": "object",
|
|
848
848
|
"properties": {
|
|
849
849
|
"workspaceRoot": {
|
|
850
|
-
"description": "Highest-priority override.",
|
|
850
|
+
"description": "Highest-priority root override.",
|
|
851
851
|
"type": "string"
|
|
852
852
|
},
|
|
853
853
|
"rootIndex": {
|
|
854
|
-
"description": "0-based index into
|
|
854
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
855
855
|
"type": "integer",
|
|
856
856
|
"minimum": 0,
|
|
857
857
|
"maximum": 9007199254740991
|
|
858
858
|
},
|
|
859
859
|
"allWorkspaceRoots": {
|
|
860
860
|
"default": false,
|
|
861
|
-
"description": "Fan out across all MCP
|
|
861
|
+
"description": "Fan out across all MCP roots.",
|
|
862
862
|
"type": "boolean"
|
|
863
863
|
},
|
|
864
864
|
"format": {
|
|
@@ -895,18 +895,18 @@
|
|
|
895
895
|
"type": "object",
|
|
896
896
|
"properties": {
|
|
897
897
|
"workspaceRoot": {
|
|
898
|
-
"description": "Highest-priority override.",
|
|
898
|
+
"description": "Highest-priority root override.",
|
|
899
899
|
"type": "string"
|
|
900
900
|
},
|
|
901
901
|
"rootIndex": {
|
|
902
|
-
"description": "0-based index into
|
|
902
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
903
903
|
"type": "integer",
|
|
904
904
|
"minimum": 0,
|
|
905
905
|
"maximum": 9007199254740991
|
|
906
906
|
},
|
|
907
907
|
"allWorkspaceRoots": {
|
|
908
908
|
"default": false,
|
|
909
|
-
"description": "Fan out across all MCP
|
|
909
|
+
"description": "Fan out across all MCP roots.",
|
|
910
910
|
"type": "boolean"
|
|
911
911
|
},
|
|
912
912
|
"format": {
|
|
@@ -948,12 +948,12 @@
|
|
|
948
948
|
},
|
|
949
949
|
"deleteMergedBranches": {
|
|
950
950
|
"default": false,
|
|
951
|
-
"description": "
|
|
951
|
+
"description": "Delete each source branch locally after clean merge (`git branch -d`). Protected names and remote refs unaffected.",
|
|
952
952
|
"type": "boolean"
|
|
953
953
|
},
|
|
954
954
|
"deleteMergedWorktrees": {
|
|
955
955
|
"default": false,
|
|
956
|
-
"description": "
|
|
956
|
+
"description": "Remove local worktrees on source branches after clean merge (`git worktree remove`). Protected tails skipped.",
|
|
957
957
|
"type": "boolean"
|
|
958
958
|
}
|
|
959
959
|
},
|
|
@@ -972,18 +972,18 @@
|
|
|
972
972
|
"type": "object",
|
|
973
973
|
"properties": {
|
|
974
974
|
"workspaceRoot": {
|
|
975
|
-
"description": "Highest-priority override.",
|
|
975
|
+
"description": "Highest-priority root override.",
|
|
976
976
|
"type": "string"
|
|
977
977
|
},
|
|
978
978
|
"rootIndex": {
|
|
979
|
-
"description": "0-based index into
|
|
979
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
980
980
|
"type": "integer",
|
|
981
981
|
"minimum": 0,
|
|
982
982
|
"maximum": 9007199254740991
|
|
983
983
|
},
|
|
984
984
|
"allWorkspaceRoots": {
|
|
985
985
|
"default": false,
|
|
986
|
-
"description": "Fan out across all MCP
|
|
986
|
+
"description": "Fan out across all MCP roots.",
|
|
987
987
|
"type": "boolean"
|
|
988
988
|
},
|
|
989
989
|
"format": {
|
|
@@ -1002,7 +1002,7 @@
|
|
|
1002
1002
|
"type": "string",
|
|
1003
1003
|
"minLength": 1
|
|
1004
1004
|
},
|
|
1005
|
-
"description": "Sources
|
|
1005
|
+
"description": "Sources: SHA, `A..B` range, or branch name (resolves to `onto..<branch>`)."
|
|
1006
1006
|
},
|
|
1007
1007
|
"onto": {
|
|
1008
1008
|
"description": "Destination branch. Defaults to the currently checked-out branch.",
|
|
@@ -1010,17 +1010,17 @@
|
|
|
1010
1010
|
},
|
|
1011
1011
|
"deleteMergedBranches": {
|
|
1012
1012
|
"default": false,
|
|
1013
|
-
"description": "
|
|
1013
|
+
"description": "Delete branch-kind sources locally after success. Protected names and remote refs unaffected.",
|
|
1014
1014
|
"type": "boolean"
|
|
1015
1015
|
},
|
|
1016
1016
|
"deleteMergedWorktrees": {
|
|
1017
1017
|
"default": false,
|
|
1018
|
-
"description": "
|
|
1018
|
+
"description": "Remove local worktrees on branch-kind sources after success. Protected tails skipped.",
|
|
1019
1019
|
"type": "boolean"
|
|
1020
1020
|
},
|
|
1021
1021
|
"strictMergedRefEquality": {
|
|
1022
1022
|
"default": false,
|
|
1023
|
-
"description": "
|
|
1023
|
+
"description": "false (default): delete branch when every commit is content-equivalent on destination (patch-id, normal cherry-pick outcome). true: require strict ref ancestry (`git branch -d` semantics — will refuse after cherry-pick due to SHA mismatch).",
|
|
1024
1024
|
"type": "boolean"
|
|
1025
1025
|
}
|
|
1026
1026
|
},
|
|
@@ -1039,18 +1039,18 @@
|
|
|
1039
1039
|
"type": "object",
|
|
1040
1040
|
"properties": {
|
|
1041
1041
|
"workspaceRoot": {
|
|
1042
|
-
"description": "Highest-priority override.",
|
|
1042
|
+
"description": "Highest-priority root override.",
|
|
1043
1043
|
"type": "string"
|
|
1044
1044
|
},
|
|
1045
1045
|
"rootIndex": {
|
|
1046
|
-
"description": "0-based index into
|
|
1046
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
1047
1047
|
"type": "integer",
|
|
1048
1048
|
"minimum": 0,
|
|
1049
1049
|
"maximum": 9007199254740991
|
|
1050
1050
|
},
|
|
1051
1051
|
"allWorkspaceRoots": {
|
|
1052
1052
|
"default": false,
|
|
1053
|
-
"description": "Fan out across all MCP
|
|
1053
|
+
"description": "Fan out across all MCP roots.",
|
|
1054
1054
|
"type": "boolean"
|
|
1055
1055
|
},
|
|
1056
1056
|
"format": {
|
|
@@ -1064,7 +1064,7 @@
|
|
|
1064
1064
|
"ref": {
|
|
1065
1065
|
"type": "string",
|
|
1066
1066
|
"minLength": 1,
|
|
1067
|
-
"description": "Commit to reset to
|
|
1067
|
+
"description": "Commit to reset to: ancestor notation (`HEAD~1`, `HEAD~3`), branch name, or SHA."
|
|
1068
1068
|
}
|
|
1069
1069
|
},
|
|
1070
1070
|
"required": [
|
|
@@ -1079,11 +1079,11 @@
|
|
|
1079
1079
|
"type": "object",
|
|
1080
1080
|
"properties": {
|
|
1081
1081
|
"workspaceRoot": {
|
|
1082
|
-
"description": "Highest-priority override.",
|
|
1082
|
+
"description": "Highest-priority root override.",
|
|
1083
1083
|
"type": "string"
|
|
1084
1084
|
},
|
|
1085
1085
|
"rootIndex": {
|
|
1086
|
-
"description": "0-based index into
|
|
1086
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
1087
1087
|
"type": "integer",
|
|
1088
1088
|
"minimum": 0,
|
|
1089
1089
|
"maximum": 9007199254740991
|
|
@@ -1127,18 +1127,18 @@
|
|
|
1127
1127
|
"type": "object",
|
|
1128
1128
|
"properties": {
|
|
1129
1129
|
"workspaceRoot": {
|
|
1130
|
-
"description": "Highest-priority override.",
|
|
1130
|
+
"description": "Highest-priority root override.",
|
|
1131
1131
|
"type": "string"
|
|
1132
1132
|
},
|
|
1133
1133
|
"rootIndex": {
|
|
1134
|
-
"description": "0-based index into
|
|
1134
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
1135
1135
|
"type": "integer",
|
|
1136
1136
|
"minimum": 0,
|
|
1137
1137
|
"maximum": 9007199254740991
|
|
1138
1138
|
},
|
|
1139
1139
|
"allWorkspaceRoots": {
|
|
1140
1140
|
"default": false,
|
|
1141
|
-
"description": "Fan out across all MCP
|
|
1141
|
+
"description": "Fan out across all MCP roots.",
|
|
1142
1142
|
"type": "boolean"
|
|
1143
1143
|
},
|
|
1144
1144
|
"format": {
|
|
@@ -1152,15 +1152,15 @@
|
|
|
1152
1152
|
"path": {
|
|
1153
1153
|
"type": "string",
|
|
1154
1154
|
"minLength": 1,
|
|
1155
|
-
"description": "Filesystem path for the new worktree
|
|
1155
|
+
"description": "Filesystem path for the new worktree (relative paths resolved from git toplevel)."
|
|
1156
1156
|
},
|
|
1157
1157
|
"branch": {
|
|
1158
1158
|
"type": "string",
|
|
1159
1159
|
"minLength": 1,
|
|
1160
|
-
"description": "Branch to check out
|
|
1160
|
+
"description": "Branch to check out; created from `baseRef` if it doesn't exist."
|
|
1161
1161
|
},
|
|
1162
1162
|
"baseRef": {
|
|
1163
|
-
"description": "Commit-ish to base the new branch on
|
|
1163
|
+
"description": "Commit-ish to base the new branch on. Default: HEAD.",
|
|
1164
1164
|
"type": "string"
|
|
1165
1165
|
}
|
|
1166
1166
|
},
|
|
@@ -1177,18 +1177,18 @@
|
|
|
1177
1177
|
"type": "object",
|
|
1178
1178
|
"properties": {
|
|
1179
1179
|
"workspaceRoot": {
|
|
1180
|
-
"description": "Highest-priority override.",
|
|
1180
|
+
"description": "Highest-priority root override.",
|
|
1181
1181
|
"type": "string"
|
|
1182
1182
|
},
|
|
1183
1183
|
"rootIndex": {
|
|
1184
|
-
"description": "0-based index into
|
|
1184
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
1185
1185
|
"type": "integer",
|
|
1186
1186
|
"minimum": 0,
|
|
1187
1187
|
"maximum": 9007199254740991
|
|
1188
1188
|
},
|
|
1189
1189
|
"allWorkspaceRoots": {
|
|
1190
1190
|
"default": false,
|
|
1191
|
-
"description": "Fan out across all MCP
|
|
1191
|
+
"description": "Fan out across all MCP roots.",
|
|
1192
1192
|
"type": "boolean"
|
|
1193
1193
|
},
|
|
1194
1194
|
"format": {
|
|
@@ -1206,7 +1206,7 @@
|
|
|
1206
1206
|
},
|
|
1207
1207
|
"force": {
|
|
1208
1208
|
"default": false,
|
|
1209
|
-
"description": "
|
|
1209
|
+
"description": "Allow removal of worktrees with uncommitted changes (`--force`).",
|
|
1210
1210
|
"type": "boolean"
|
|
1211
1211
|
}
|
|
1212
1212
|
},
|
|
@@ -1223,11 +1223,11 @@
|
|
|
1223
1223
|
"type": "object",
|
|
1224
1224
|
"properties": {
|
|
1225
1225
|
"workspaceRoot": {
|
|
1226
|
-
"description": "Highest-priority override.",
|
|
1226
|
+
"description": "Highest-priority root override.",
|
|
1227
1227
|
"type": "string"
|
|
1228
1228
|
},
|
|
1229
1229
|
"rootIndex": {
|
|
1230
|
-
"description": "0-based index into
|
|
1230
|
+
"description": "0-based index into MCP roots; ignored if workspaceRoot set.",
|
|
1231
1231
|
"type": "integer",
|
|
1232
1232
|
"minimum": 0,
|
|
1233
1233
|
"maximum": 9007199254740991
|
|
@@ -1249,7 +1249,7 @@
|
|
|
1249
1249
|
},
|
|
1250
1250
|
"pop": {
|
|
1251
1251
|
"default": false,
|
|
1252
|
-
"description": "
|
|
1252
|
+
"description": "Run `git stash pop` instead of `git stash apply` (removes stash after applying).",
|
|
1253
1253
|
"type": "boolean"
|
|
1254
1254
|
}
|
|
1255
1255
|
},
|