mergestorm-mcp 0.2.14 → 0.2.16
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/README.md +2 -2
- package/dist/index.js +44 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -18,9 +18,9 @@ Every tool declares MCP `annotations` for read-only access, destructive changes,
|
|
|
18
18
|
|
|
19
19
|
The stack tools expose reads plus one scoped policy write:
|
|
20
20
|
|
|
21
|
-
- `stack_adopt({ owner, repo, pr_number, auto_land?, auto_review?, auto_patch? })` adopts an open PR chain with optional per-stack policy. Omitted policy does not force Cyclone off. `auto_review` and `
|
|
21
|
+
- `stack_adopt({ owner, repo, pr_number, auto_land?, auto_review?, auto_patch?, auto_resolve_conflicts?, auto_fix_ci? })` adopts an open PR chain with optional per-stack policy. Omitted policy does not force Cyclone off. `auto_review`, `auto_patch`, `auto_resolve_conflicts`, and `auto_fix_ci` accept `true`, `false`, or `null`; `null` clears the override. Read `stack_status` with the returned `result.stack.id` to verify policy and Cyclone ownership. Adoption needs the Mergestorm Surge GitHub App on the repository (Cyclone is the auto-patch App). A refusal keeps the code `cyclone_not_connected` or `cyclone_not_installed`; its message, and `error.reason` starting with `surge_` when Surge is the one to install, say which App is missing.
|
|
22
22
|
- `stack_list` returns the current API key owner's registered stacks.
|
|
23
|
-
- `stack_set({ stack_id, auto_land?, auto_review?, auto_patch? })` sets per-stack policy on one owned stack. `auto_land` flips Auto land. `auto_review` and `
|
|
23
|
+
- `stack_set({ stack_id, auto_land?, auto_review?, auto_patch?, auto_resolve_conflicts?, auto_fix_ci? })` sets per-stack policy on one owned stack. `auto_land` flips Auto land. `auto_review`, `auto_patch`, `auto_resolve_conflicts`, and `auto_fix_ci` pin Vortex auto-review, Cyclone auto-patch, Auto-resolve merge conflicts, or Auto-fix failing CI for that stack in either direction (`true` or `false`); `null` clears the pin so the stack follows the account setting. Pass at least one key. Account settings are never changed here.
|
|
24
24
|
- `stack_status({ stack_id })` returns one owned stack with enriched checks and agent state, plus `attention`, `issues`, and `currentCandidate` from the same blocker rules as `stack_wait`, read against that stack's own merge queue. It returns a structured `stack_not_found` or `rate_limited` error.
|
|
25
25
|
- `stack_wait({ stack_id, timeout_s?, enrolled_head_sha?, after_finished_at?, bounce_id? })` waits for a stack or queue state change and returns the latest snapshots. `timeout_s: 0` returns one snapshot; a positive timeout after a snapshot with no attention returns the current `waiting` or `in_progress` status with selectors to use for the next call. An unread deadline returns `failed`. While Cyclone or Vortex is still working on the blocked PR, `stack_wait` and `stack_status` return `in_progress` instead of `attention`, with `busy[]` naming the PR, blocker, and agent, and `agents` carrying that PR's `vortexStatus`, `cycloneStatus`, `vortexReview`, and busy flags. A nonempty `busy[]` means wait. A queued Vortex run holds for at most 15 minutes, `seam_pending` alone does not hold, and reviewing or patching holds until the run finishes or its lease or check run is cleared. A blocker no agent run clears (a merge conflict vs the live parent, a restack `Conflict` or `Restack failed`, a Draft PR, a seam review pending with no review running, "Seam review stuck in reviewing, no review running", "Seam re-review pending, no review running", "Seam verdict is for an older head, no review running", or a review skipped for review quota) is still named during that `in_progress`, in `blocker`, `prNumber`, `headSha`, and `issues[]`, with `actAfter: "agents_idle"` and `waitingOn` listing the busy agents; act when a snapshot after the agents finish returns `attention`, re-reading the blocker then. For the three stuck-seam blockers, `repair` has kind `seam_review_stuck`: do not patch or push; tell the human to click Continue, which re-queues the seam review at the live head. `repair` is included when another concrete repair hint is available. Blockers the agents can change keep `blocker` and `actAfter` null. If a hold looks stuck, refresh `stack_status` and tell the human.
|
|
26
26
|
|
package/dist/index.js
CHANGED
|
@@ -201,8 +201,9 @@ var stackWaitSchema = {
|
|
|
201
201
|
function repairSummary(repair) {
|
|
202
202
|
if (!repair) return "";
|
|
203
203
|
const files = "files" in repair && repair.files.length ? ` Files: ${repair.files.join(", ")}.` : "";
|
|
204
|
+
const note = "note" in repair && repair.note ? ` ${repair.note}` : "";
|
|
204
205
|
return `
|
|
205
|
-
Repair #${repair.prNumber} (${repair.kind}).${files} ${repair.steps}`;
|
|
206
|
+
Repair #${repair.prNumber} (${repair.kind}).${files} ${repair.steps}${note}`;
|
|
206
207
|
}
|
|
207
208
|
function withWatchText(watch, body) {
|
|
208
209
|
return `${watch.message}
|
|
@@ -761,10 +762,15 @@ import {
|
|
|
761
762
|
} from "mergestorm/client";
|
|
762
763
|
function settingsSummary(settings) {
|
|
763
764
|
const autoPatch = settings.auto_patch_enabled ? "on" : "off";
|
|
765
|
+
const automations = [
|
|
766
|
+
settings.auto_resolve_conflicts_enabled ? "auto_resolve_conflicts on" : null,
|
|
767
|
+
settings.auto_fix_ci_enabled ? "auto_fix_ci on" : null
|
|
768
|
+
].filter((label) => label !== null);
|
|
769
|
+
const autoPatchLabel = [`auto_patch ${autoPatch}`, ...automations].join(" \xB7 ");
|
|
764
770
|
const cyclone = settings.cyclone_connected ? "Cyclone connected" : "Cyclone not connected";
|
|
765
|
-
if (typeof settings.stacks_ready !== "boolean") return
|
|
771
|
+
if (typeof settings.stacks_ready !== "boolean") return `${autoPatchLabel} \xB7 ${cyclone}`;
|
|
766
772
|
const stacks = settings.stacks_ready ? "stacks, merge queue and Auto land ready" : "stacks, merge queue and Auto land not ready (install Mergestorm Surge)";
|
|
767
|
-
return
|
|
773
|
+
return `${autoPatchLabel} \xB7 ${cyclone} (auto patch) \xB7 ${stacks}`;
|
|
768
774
|
}
|
|
769
775
|
async function settingsGet(cfg) {
|
|
770
776
|
const settings = await getSettings(cfg);
|
|
@@ -856,18 +862,22 @@ function stackSetPatch(input) {
|
|
|
856
862
|
if (typeof input.auto_land === "boolean") patch.autoEnqueueWhenReady = input.auto_land;
|
|
857
863
|
if (input.auto_review !== void 0) patch.autoReviewOverride = input.auto_review;
|
|
858
864
|
if (input.auto_patch !== void 0) patch.autoPatchOverride = input.auto_patch;
|
|
865
|
+
if (input.auto_resolve_conflicts !== void 0) {
|
|
866
|
+
patch.autoResolveConflictsOverride = input.auto_resolve_conflicts;
|
|
867
|
+
}
|
|
868
|
+
if (input.auto_fix_ci !== void 0) patch.autoFixCiOverride = input.auto_fix_ci;
|
|
859
869
|
return patch;
|
|
860
870
|
}
|
|
861
871
|
async function stackSet(stackId, input, cfg) {
|
|
862
872
|
const patch = stackSetPatch(input);
|
|
863
873
|
if (Object.keys(patch).length === 0) {
|
|
864
874
|
return {
|
|
865
|
-
summary: "stack_set needs at least one of auto_land, auto_review, auto_patch",
|
|
875
|
+
summary: "stack_set needs at least one of auto_land, auto_review, auto_patch, auto_resolve_conflicts, auto_fix_ci",
|
|
866
876
|
isError: true,
|
|
867
877
|
data: {
|
|
868
878
|
error: {
|
|
869
879
|
code: "invalid_input",
|
|
870
|
-
message: "Pass at least one of auto_land, auto_review, auto_patch.",
|
|
880
|
+
message: "Pass at least one of auto_land, auto_review, auto_patch, auto_resolve_conflicts, auto_fix_ci.",
|
|
871
881
|
stack_id: stackId
|
|
872
882
|
}
|
|
873
883
|
}
|
|
@@ -884,6 +894,12 @@ async function stackSet(stackId, input, cfg) {
|
|
|
884
894
|
if (input.auto_patch !== void 0) {
|
|
885
895
|
parts.push(`auto-patch ${triWord(input.auto_patch)}`);
|
|
886
896
|
}
|
|
897
|
+
if (input.auto_resolve_conflicts !== void 0) {
|
|
898
|
+
parts.push(`auto-resolve-conflicts ${triWord(input.auto_resolve_conflicts)}`);
|
|
899
|
+
}
|
|
900
|
+
if (input.auto_fix_ci !== void 0) {
|
|
901
|
+
parts.push(`auto-fix-ci ${triWord(input.auto_fix_ci)}`);
|
|
902
|
+
}
|
|
887
903
|
const watch = stackWatchObligation3({ stackId, terminal: null, unread: true, freshCursor: true });
|
|
888
904
|
return {
|
|
889
905
|
summary: withWatchText(watch, `${parts.join(", ")} for stack ${stackId}`),
|
|
@@ -892,6 +908,8 @@ async function stackSet(stackId, input, cfg) {
|
|
|
892
908
|
...typeof input.auto_land === "boolean" ? { auto_land: input.auto_land } : {},
|
|
893
909
|
...input.auto_review !== void 0 ? { auto_review: input.auto_review } : {},
|
|
894
910
|
...input.auto_patch !== void 0 ? { auto_patch: input.auto_patch } : {},
|
|
911
|
+
...input.auto_resolve_conflicts !== void 0 ? { auto_resolve_conflicts: input.auto_resolve_conflicts } : {},
|
|
912
|
+
...input.auto_fix_ci !== void 0 ? { auto_fix_ci: input.auto_fix_ci } : {},
|
|
895
913
|
result,
|
|
896
914
|
watch
|
|
897
915
|
}
|
|
@@ -905,7 +923,9 @@ var stackAdoptSchema = {
|
|
|
905
923
|
pr_number: z2.number().int().min(1),
|
|
906
924
|
auto_land: z2.boolean().optional(),
|
|
907
925
|
auto_review: z2.boolean().nullable().optional(),
|
|
908
|
-
auto_patch: z2.boolean().nullable().optional()
|
|
926
|
+
auto_patch: z2.boolean().nullable().optional(),
|
|
927
|
+
auto_resolve_conflicts: z2.boolean().nullable().optional(),
|
|
928
|
+
auto_fix_ci: z2.boolean().nullable().optional()
|
|
909
929
|
};
|
|
910
930
|
var inputSchema = z2.object(stackAdoptSchema);
|
|
911
931
|
async function stackAdopt(input, cfg) {
|
|
@@ -972,6 +992,12 @@ function stackSummary(stack, entries = []) {
|
|
|
972
992
|
if (typeof stack.autoPatchOverride === "boolean") {
|
|
973
993
|
overrides.push(`auto-patch ${stack.autoPatchOverride ? "on" : "off"}`);
|
|
974
994
|
}
|
|
995
|
+
if (typeof stack.autoResolveConflictsOverride === "boolean") {
|
|
996
|
+
overrides.push(`auto-resolve-conflicts ${stack.autoResolveConflictsOverride ? "on" : "off"}`);
|
|
997
|
+
}
|
|
998
|
+
if (typeof stack.autoFixCiOverride === "boolean") {
|
|
999
|
+
overrides.push(`auto-fix-ci ${stack.autoFixCiOverride ? "on" : "off"}`);
|
|
1000
|
+
}
|
|
975
1001
|
if (stack.cycloneOwnerMatch) {
|
|
976
1002
|
overrides.push(`cyclone-owner ${stack.cycloneOwnerMatch}`);
|
|
977
1003
|
}
|
|
@@ -1160,14 +1186,15 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
|
1160
1186
|
`- While the stack has a live merge queue entry, stack_wait carries queueWait (the entry's wait reason, how long it has been held, and the stack queued ahead of it) and the status line names it. The watch returns attention, blocker "Merge queue stuck: ..." and repair kind queue_stalled, when the entry (or the entry ahead of it) has been held for 45 minutes without landing or bouncing, or has sat queued for 45 minutes with nothing working on it or ahead of it.`,
|
|
1161
1187
|
'- When no Vortex run works on the head and its review was skipped because auto-review is off (blocker "Vortex auto-review is off, so this head was not reviewed") or because billing could not be confirmed ("Vortex skipped this head: it could not confirm billing"), or it covered only part of the PR ("Vortex reviewed only part of this PR"), the watch returns attention at once with repair kind vortex_skipped. Do not patch for it; the repair names the mention or setting that gets the head reviewed.',
|
|
1162
1188
|
'- A live-head Vortex request_changes handoff returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify the review and inline findings against the live head before repair.',
|
|
1163
|
-
"- Cyclone patches
|
|
1189
|
+
"- Cyclone, with auto-patch on, patches only Vortex review findings (Core and seam, on any layer, the land PR included). It does not fix merge conflicts, restack conflicts, failing CI, or any other landing blocker by itself; the watching agent fixes those, whatever the auto-patch setting, and does not turn auto-patch off to do it. With auto-resolve conflicts on for the stack, Cyclone resolves a layer conflict itself (never the land PR's conflict with main): while busy[] shows Cyclone, wait, and fix the conflict only after its handoff, when the watch returns attention. With auto-fix CI on for the stack, Cyclone fixes a settled red check on a layer itself (never the land PR), or asks Surge for one re-run of a flaky one: while busy[] shows Cyclone, wait, and fix the failure only after its handoff, when the watch returns attention.",
|
|
1190
|
+
"- Cyclone patches Vortex findings on a land PR when auto-patch is on for that stack (its override, else the account setting); every other land PR blocker, a conflict with main or failing CI included, is fixed by the watching agent on mg-stack-<n>.",
|
|
1164
1191
|
'- More states the watch names: a Vortex review skipped because the PR author is on the ignored authors list or because reviews are turned off for the repository is attention at once with repair kind vortex_skipped; a Vortex retry that is scheduled ("Vortex hit a temporary error on this head and will retry by itself") is a wait listed in issues[], never attention; "Review failed" carries repair kind vortex_failed (comment @mergestorm-vortex review or push a new commit; if it fails again tell the human); a PR open on mg-stack-N that is not a layer of the stack is attention at once, blocker "The land PR cannot be queued: ...", repair kind members_remaining (do not patch or push; close, retarget or adopt that PR).',
|
|
1165
1192
|
"- Use the mergestorm-bounce-watch skill for the fix-then-watch policy."
|
|
1166
1193
|
].join("\n");
|
|
1167
1194
|
|
|
1168
1195
|
// src/server.ts
|
|
1169
1196
|
var MCP_SERVER_NAME = "mergestorm";
|
|
1170
|
-
var MCP_SERVER_VERSION = "0.2.
|
|
1197
|
+
var MCP_SERVER_VERSION = "0.2.16";
|
|
1171
1198
|
var MCP_SERVER_INSTRUCTIONS = [
|
|
1172
1199
|
MCP_STACK_DONE_INSTRUCTIONS,
|
|
1173
1200
|
MCP_PR_LOOP_INSTRUCTIONS,
|
|
@@ -1376,7 +1403,7 @@ function createMergestormMcpServer() {
|
|
|
1376
1403
|
"stack_adopt",
|
|
1377
1404
|
{
|
|
1378
1405
|
title: "Adopt PR stack",
|
|
1379
|
-
description: "Adopt an open GitHub PR chain into a Mergestorm stack. auto_land is boolean; auto_review and
|
|
1406
|
+
description: "Adopt an open GitHub PR chain into a Mergestorm stack. auto_land is boolean; auto_review, auto_patch, auto_resolve_conflicts, and auto_fix_ci accept true, false, or null, where null clears the override. Omitted auto_land seeds from auto_land_default; omitted overrides are not seeded. Never changes account settings. Adoption needs the Mergestorm Surge GitHub App on the repository. Stacks, the merge queue and Auto land run through that App; Cyclone is the auto-patch App. Without it the API returns cyclone_not_connected or cyclone_not_installed; the message, and error.reason starting with surge_ when Surge is the one to install, say which App is missing \u2014 do not retry, tell the human what the message says. Read stack_status with result.stack.id afterward to verify policy and Cyclone ownership. With 2+ PRs, adopt moves the bottom PR's GitHub base to mg-stack-<n> and parks PR3+ on an mg-park-* freeze; a 1-PR stack stays on main. Leave those bases. Never retarget the bottom back to main." + STACK_WATCH_RESULT_NOTE,
|
|
1380
1407
|
inputSchema: stackAdoptSchema,
|
|
1381
1408
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
|
|
1382
1409
|
},
|
|
@@ -1407,22 +1434,26 @@ function createMergestormMcpServer() {
|
|
|
1407
1434
|
"stack_set",
|
|
1408
1435
|
{
|
|
1409
1436
|
title: "Set stack policy",
|
|
1410
|
-
description: "Set per-stack automation on one owned Mergestorm stack: auto_land arms or disarms Auto land; auto_review and
|
|
1437
|
+
description: "Set per-stack automation on one owned Mergestorm stack: auto_land arms or disarms Auto land; auto_review, auto_patch, auto_resolve_conflicts, and auto_fix_ci pin Vortex auto-review, Cyclone auto-patch, Auto-resolve merge conflicts, or Auto-fix failing CI for this stack only (true or false), and null clears the pin so the stack follows the account setting again. Pass at least one key. Never changes account settings." + STACK_WATCH_RESULT_NOTE,
|
|
1411
1438
|
inputSchema: {
|
|
1412
1439
|
stack_id: z3.string().min(1),
|
|
1413
1440
|
auto_land: z3.boolean().optional(),
|
|
1414
1441
|
auto_review: z3.boolean().nullable().optional(),
|
|
1415
|
-
auto_patch: z3.boolean().nullable().optional()
|
|
1442
|
+
auto_patch: z3.boolean().nullable().optional(),
|
|
1443
|
+
auto_resolve_conflicts: z3.boolean().nullable().optional(),
|
|
1444
|
+
auto_fix_ci: z3.boolean().nullable().optional()
|
|
1416
1445
|
},
|
|
1417
1446
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }
|
|
1418
1447
|
},
|
|
1419
|
-
async ({ stack_id, auto_land, auto_review, auto_patch }) => {
|
|
1448
|
+
async ({ stack_id, auto_land, auto_review, auto_patch, auto_resolve_conflicts, auto_fix_ci }) => {
|
|
1420
1449
|
try {
|
|
1421
1450
|
return ok(
|
|
1422
1451
|
await stackSet(stack_id, {
|
|
1423
1452
|
...auto_land !== void 0 ? { auto_land } : {},
|
|
1424
1453
|
...auto_review !== void 0 ? { auto_review } : {},
|
|
1425
|
-
...auto_patch !== void 0 ? { auto_patch } : {}
|
|
1454
|
+
...auto_patch !== void 0 ? { auto_patch } : {},
|
|
1455
|
+
...auto_resolve_conflicts !== void 0 ? { auto_resolve_conflicts } : {},
|
|
1456
|
+
...auto_fix_ci !== void 0 ? { auto_fix_ci } : {}
|
|
1426
1457
|
})
|
|
1427
1458
|
);
|
|
1428
1459
|
} catch (err) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mergestorm-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.16",
|
|
4
4
|
"description": "Mergestorm MCP server — identity, review, and read-only stack tools over stdio",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
32
|
-
"mergestorm": "0.3.
|
|
32
|
+
"mergestorm": "0.3.45",
|
|
33
33
|
"zod": "^3.24.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|