mergestorm-mcp 0.2.13 → 0.2.15
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 +3 -3
- package/dist/index.js +59 -21
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -13,14 +13,14 @@ Every tool declares MCP `annotations` for read-only access, destructive changes,
|
|
|
13
13
|
- **Authorization.** The API key's account must monitor the repository or own the PR's stack, and its linked GitHub account needs write access to the repository.
|
|
14
14
|
- **Refusals.** A moved head (`stale_head`), another review (`review_mismatch`, `review_not_found`), an id outside that review (`unknown_finding`), a thin `reason` (`invalid_input`) or a missing permission (`forbidden`) is refused, and nothing is written.
|
|
15
15
|
- **Audit and retries.** Each finding is stored with the actor's GitHub login, the reason, `evidence_url`, the scope and the time. A retry reports the earlier record under `already_dismissed`.
|
|
16
|
-
- **Gates.** `gate.seam.cleared` is true only when every finding of that integration review is dismissed and it is still the member's current seam verdict.
|
|
16
|
+
- **Gates.** `gate.seam.cleared` is true only when every finding of that integration review is dismissed and it is still the member's current seam verdict. `gate.vortex.cleared` is true once every Vortex Blocker (error finding) at the live head is dismissed (every Core review merged into that head) and no Vortex review of the head is running or incomplete; with a warning still open the head reads `comment`, which Auto land accepts; otherwise `gate.vortex.reason` and `message` say what still holds it: that head's Vortex verdict becomes approve for Auto land, the stack watch, the dashboard and Cyclone. A partial dismissal clears nothing. CI and Auto land policy are unchanged (`gate.other_gates: "unchanged"`). For a stack PR the result carries `watch` with the next `stack_wait` call.
|
|
17
17
|
- **No resurfacing.** Vortex does not raise a dismissed finding again on the same diff: the same head, or a restack whose diff is unchanged.
|
|
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}
|
|
@@ -292,6 +293,12 @@ function reviewDismissSummary(result) {
|
|
|
292
293
|
seam.cleared ? "Seam gate cleared at this head. CI, other reviews and Auto land policy are unchanged." : seam.blocking ? `Seam gate still blocking (seam_state=${seam.state}).` : `Seam gate not blocking (seam_state=${seam.state}).`
|
|
293
294
|
);
|
|
294
295
|
}
|
|
296
|
+
const vortex = result.gate.vortex;
|
|
297
|
+
if (vortex?.cleared) {
|
|
298
|
+
lines.push("Vortex gate cleared at this head: every Vortex Blocker (error finding) at this head is dismissed. CI and Auto land policy are unchanged.");
|
|
299
|
+
} else if (vortex?.message && vortex.reason !== "review_findings_open") {
|
|
300
|
+
lines.push(`Vortex gate not cleared: ${vortex.message}`);
|
|
301
|
+
}
|
|
295
302
|
return lines.join("\n");
|
|
296
303
|
}
|
|
297
304
|
async function reviewDismiss(input, cfg) {
|
|
@@ -755,10 +762,15 @@ import {
|
|
|
755
762
|
} from "mergestorm/client";
|
|
756
763
|
function settingsSummary(settings) {
|
|
757
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 ");
|
|
758
770
|
const cyclone = settings.cyclone_connected ? "Cyclone connected" : "Cyclone not connected";
|
|
759
|
-
if (typeof settings.stacks_ready !== "boolean") return
|
|
771
|
+
if (typeof settings.stacks_ready !== "boolean") return `${autoPatchLabel} \xB7 ${cyclone}`;
|
|
760
772
|
const stacks = settings.stacks_ready ? "stacks, merge queue and Auto land ready" : "stacks, merge queue and Auto land not ready (install Mergestorm Surge)";
|
|
761
|
-
return
|
|
773
|
+
return `${autoPatchLabel} \xB7 ${cyclone} (auto patch) \xB7 ${stacks}`;
|
|
762
774
|
}
|
|
763
775
|
async function settingsGet(cfg) {
|
|
764
776
|
const settings = await getSettings(cfg);
|
|
@@ -850,18 +862,22 @@ function stackSetPatch(input) {
|
|
|
850
862
|
if (typeof input.auto_land === "boolean") patch.autoEnqueueWhenReady = input.auto_land;
|
|
851
863
|
if (input.auto_review !== void 0) patch.autoReviewOverride = input.auto_review;
|
|
852
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;
|
|
853
869
|
return patch;
|
|
854
870
|
}
|
|
855
871
|
async function stackSet(stackId, input, cfg) {
|
|
856
872
|
const patch = stackSetPatch(input);
|
|
857
873
|
if (Object.keys(patch).length === 0) {
|
|
858
874
|
return {
|
|
859
|
-
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",
|
|
860
876
|
isError: true,
|
|
861
877
|
data: {
|
|
862
878
|
error: {
|
|
863
879
|
code: "invalid_input",
|
|
864
|
-
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.",
|
|
865
881
|
stack_id: stackId
|
|
866
882
|
}
|
|
867
883
|
}
|
|
@@ -878,6 +894,12 @@ async function stackSet(stackId, input, cfg) {
|
|
|
878
894
|
if (input.auto_patch !== void 0) {
|
|
879
895
|
parts.push(`auto-patch ${triWord(input.auto_patch)}`);
|
|
880
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
|
+
}
|
|
881
903
|
const watch = stackWatchObligation3({ stackId, terminal: null, unread: true, freshCursor: true });
|
|
882
904
|
return {
|
|
883
905
|
summary: withWatchText(watch, `${parts.join(", ")} for stack ${stackId}`),
|
|
@@ -886,6 +908,8 @@ async function stackSet(stackId, input, cfg) {
|
|
|
886
908
|
...typeof input.auto_land === "boolean" ? { auto_land: input.auto_land } : {},
|
|
887
909
|
...input.auto_review !== void 0 ? { auto_review: input.auto_review } : {},
|
|
888
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 } : {},
|
|
889
913
|
result,
|
|
890
914
|
watch
|
|
891
915
|
}
|
|
@@ -899,7 +923,9 @@ var stackAdoptSchema = {
|
|
|
899
923
|
pr_number: z2.number().int().min(1),
|
|
900
924
|
auto_land: z2.boolean().optional(),
|
|
901
925
|
auto_review: z2.boolean().nullable().optional(),
|
|
902
|
-
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()
|
|
903
929
|
};
|
|
904
930
|
var inputSchema = z2.object(stackAdoptSchema);
|
|
905
931
|
async function stackAdopt(input, cfg) {
|
|
@@ -966,6 +992,12 @@ function stackSummary(stack, entries = []) {
|
|
|
966
992
|
if (typeof stack.autoPatchOverride === "boolean") {
|
|
967
993
|
overrides.push(`auto-patch ${stack.autoPatchOverride ? "on" : "off"}`);
|
|
968
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
|
+
}
|
|
969
1001
|
if (stack.cycloneOwnerMatch) {
|
|
970
1002
|
overrides.push(`cyclone-owner ${stack.cycloneOwnerMatch}`);
|
|
971
1003
|
}
|
|
@@ -1076,7 +1108,7 @@ import {
|
|
|
1076
1108
|
loadConfig as loadConfig7,
|
|
1077
1109
|
resolveApiKey
|
|
1078
1110
|
} from "mergestorm/client";
|
|
1079
|
-
async function whoami(cfg) {
|
|
1111
|
+
async function whoami(cfg, serverVersion) {
|
|
1080
1112
|
const resolved = cfg ?? await loadConfig7();
|
|
1081
1113
|
const key = resolveApiKey(resolved);
|
|
1082
1114
|
if (!key) {
|
|
@@ -1097,11 +1129,12 @@ async function whoami(cfg) {
|
|
|
1097
1129
|
plan_label_key: me.plan_label_key ?? null,
|
|
1098
1130
|
api_base: apiBase(resolved),
|
|
1099
1131
|
config_path: configPath(),
|
|
1100
|
-
usage: me.usage ?? null
|
|
1132
|
+
usage: me.usage ?? null,
|
|
1133
|
+
mcp_server_version: serverVersion ?? null
|
|
1101
1134
|
};
|
|
1102
1135
|
const plan = data.plan_label_key ?? data.plan_key ?? "unknown plan";
|
|
1103
1136
|
return {
|
|
1104
|
-
summary: `${data.key_prefix} \xB7 ${plan}`,
|
|
1137
|
+
summary: `${data.key_prefix} \xB7 ${plan}${serverVersion ? ` \xB7 mergestorm-mcp ${serverVersion}` : ""}`,
|
|
1105
1138
|
data
|
|
1106
1139
|
};
|
|
1107
1140
|
}
|
|
@@ -1115,14 +1148,14 @@ var MCP_PR_LOOP_INSTRUCTIONS = [
|
|
|
1115
1148
|
"- Patch concrete bugs. A chat-only explanation is not a dismiss.",
|
|
1116
1149
|
`- If you skip a finding (not reproducible, policy fork, or needs a human), post a public GitHub PR comment before you stop. First line must be: ${MCP_FINDING_DISMISS_MARKER}. Then one line per skipped finding (path, severity, why).`,
|
|
1117
1150
|
"- Do not prefix that comment with cyclone-outcome: (reserved).",
|
|
1118
|
-
"- A finding you verified is wrong can be dismissed on the record with review_dismiss (or mg dismiss): pass the PR's live head_sha, the review_id, the finding_ids (preview: true lists them) and a reason. That is the only agent path that clears a seam gate, and only once every finding of that seam review is dismissed. The dismiss comment alone resumes the review but does not clear the seam gate.",
|
|
1151
|
+
"- A finding you verified is wrong can be dismissed on the record with review_dismiss (or mg dismiss): pass the PR's live head_sha, the review_id, the finding_ids (preview: true lists them) and a reason. That is the only agent path that clears a seam gate, and only once every finding of that seam review is dismissed. Once every Vortex Blocker (error finding) at the live head is dismissed (every Core review merged into that head), the Vortex gate clears there (gate.vortex.cleared); otherwise gate.vortex.message says what still holds it. The dismiss comment alone resumes the review but does not clear the seam gate.",
|
|
1119
1152
|
"- Never dismiss a finding you did not check, one a human must decide, or findings of a newer review."
|
|
1120
1153
|
].join("\n");
|
|
1121
1154
|
var MCP_STACK_DONE_INSTRUCTIONS = [
|
|
1122
1155
|
"When stack work is done:",
|
|
1123
1156
|
"- Stack work is done only when the stack is landed, or when the human takes it back (archives it or tells you to stop). A clean push, a submit, an adopt, or one merged layer is not done: merging a lower layer can break a layer above it.",
|
|
1124
1157
|
"- Every stack_wait, stack_status, stack_adopt, and stack_set result carries watch: {done, until, reason, next, message}. While watch.done is false, keep calling stack_wait with watch.next.args (the returned cursor), 45s at a time, or hand the waiting to the background watcher below, and do not end your task. Stop only when watch.done is true.",
|
|
1125
|
-
"- Only when your host has a confirmed notification that resumes this task, run `mg stack watch <stack-id>` as a background command with a notification on output matching `MS-WATCH (ATTENTION|LANDED)`, then end your turn. The watcher runs stack_wait against the Mergestorm API in slices of at most 300s, carries the cursor, stays silent while the stack is waiting or in_progress (busy[] holds and actAfter included), and costs no model tokens. It exits on attention (`MS-WATCH ATTENTION pr=<n> head=<sha> blocker=... repair=<kind>`, exit 3), on a read that failed twice (`MS-WATCH ATTENTION failed`, exit 3; tell the human the stack is no longer watched), on a closed, archived, or missing stack (`MS-WATCH ATTENTION stack=<id> reason=<reason>`, exit 3; verify missing stacks before reporting a landing), or on a confirmed landing (`MS-WATCH LANDED stack=<id> reason=landed`, exit 0). On an attention wake, read stack_status once, fix the blocker per mergestorm-bounce-watch, push, and start `mg stack watch <stack-id> --head <pushed-sha>` again. The command monitors the stack; it cannot wake an agent by itself. Without a confirmed notification, keep using stack_wait with watch.next.args, or report that automatic follow-up is unavailable before ending the turn. Ending your turn while the watcher runs is not ending the task. Do not subscribe to GitHub events to wait on a stack.",
|
|
1158
|
+
"- Only when your host has a confirmed notification that resumes this task, run `mg stack watch <stack-id>` as a background command with a notification on output matching `MS-WATCH (ATTENTION|LANDED)`, then end your turn. The watcher runs stack_wait against the Mergestorm API in slices of at most 300s, carries the cursor, stays silent while the stack is waiting or in_progress (busy[] holds and actAfter included), and costs no model tokens. It exits on attention (`MS-WATCH ATTENTION pr=<n> head=<sha> blocker=... repair=<kind>`, exit 3), on a read that failed twice (`MS-WATCH ATTENTION failed`, exit 3; tell the human the stack is no longer watched), on a closed, archived, or missing stack (`MS-WATCH ATTENTION stack=<id> reason=<reason>`, exit 3; verify missing stacks before reporting a landing), or on a confirmed landing (`MS-WATCH LANDED stack=<id> reason=landed`, exit 0). On an attention wake, read stack_status once, fix the blocker per mergestorm-bounce-watch, push, and start `mg stack watch <stack-id> --head <pushed-sha>` again. The command monitors the stack; it cannot wake an agent by itself. A confirmed notification is a host feature you can name that turns the command's exit or matching output into your next turn; a process left running, or output written to a log or terminal you do not read, is not one. Without a confirmed notification, keep using stack_wait with watch.next.args, or report that automatic follow-up is unavailable before ending the turn. Ending your turn while the watcher runs is not ending the task. Do not subscribe to GitHub events to wait on a stack.",
|
|
1126
1159
|
"- A layer PR shown as merged is merged into mg-stack-<n>, not main. The stack is landed only when the land PR (head mg-stack-<n>) merges into main or watch.done says landed. Never judge landing from GitHub PR state alone.",
|
|
1127
1160
|
"- attention means something for you to fix; repair, when present, names the concrete fix. A pending land gate (landGatePending: ci_pending) is a wait, not attention."
|
|
1128
1161
|
].join("\n");
|
|
@@ -1153,14 +1186,15 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
|
1153
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.`,
|
|
1154
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.',
|
|
1155
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.',
|
|
1156
|
-
"- 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.",
|
|
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>.",
|
|
1157
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).',
|
|
1158
1192
|
"- Use the mergestorm-bounce-watch skill for the fix-then-watch policy."
|
|
1159
1193
|
].join("\n");
|
|
1160
1194
|
|
|
1161
1195
|
// src/server.ts
|
|
1162
1196
|
var MCP_SERVER_NAME = "mergestorm";
|
|
1163
|
-
var MCP_SERVER_VERSION = "0.2.
|
|
1197
|
+
var MCP_SERVER_VERSION = "0.2.15";
|
|
1164
1198
|
var MCP_SERVER_INSTRUCTIONS = [
|
|
1165
1199
|
MCP_STACK_DONE_INSTRUCTIONS,
|
|
1166
1200
|
MCP_PR_LOOP_INSTRUCTIONS,
|
|
@@ -1212,12 +1246,12 @@ function createMergestormMcpServer() {
|
|
|
1212
1246
|
"whoami",
|
|
1213
1247
|
{
|
|
1214
1248
|
title: "Who am I",
|
|
1215
|
-
description: "Current Mergestorm API key prefix, plan, and
|
|
1249
|
+
description: "Current Mergestorm API key prefix, plan, API base, and the version of this running mergestorm-mcp server.",
|
|
1216
1250
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
1217
1251
|
},
|
|
1218
1252
|
async () => {
|
|
1219
1253
|
try {
|
|
1220
|
-
return ok(await whoami());
|
|
1254
|
+
return ok(await whoami(void 0, MCP_SERVER_VERSION));
|
|
1221
1255
|
} catch (err) {
|
|
1222
1256
|
return fail(err);
|
|
1223
1257
|
}
|
|
@@ -1342,7 +1376,7 @@ function createMergestormMcpServer() {
|
|
|
1342
1376
|
"review_dismiss",
|
|
1343
1377
|
{
|
|
1344
1378
|
title: "Dismiss Vortex findings",
|
|
1345
|
-
description: `Record an audited dismissal of Vortex findings you verified are wrong or not actionable on a GitHub PR. Identity is exact: head_sha must be the PR's live head, review_id a Vortex review (Core or seam) made at that head, and finding_ids the GitHub review comment ids of that review (offdiff-<n> for a body-only finding), or scope "review" with no finding_ids to dismiss every finding of that review. reason must say why (at least 20 characters); evidence_url is optional. Call with preview: true first to list the review's finding ids and the seam gate without writing. The caller's linked GitHub account needs write access to the repository. A moved head, another review, an unknown id or a missing permission is refused and nothing is written. Retries are idempotent. The seam gate clears only when every finding of that integration review is dismissed;
|
|
1379
|
+
description: `Record an audited dismissal of Vortex findings you verified are wrong or not actionable on a GitHub PR. Identity is exact: head_sha must be the PR's live head, review_id a Vortex review (Core or seam) made at that head, and finding_ids the GitHub review comment ids of that review (offdiff-<n> for a body-only finding), or scope "review" with no finding_ids to dismiss every finding of that review. reason must say why (at least 20 characters); evidence_url is optional. Call with preview: true first to list the review's finding ids and the seam gate without writing. The caller's linked GitHub account needs write access to the repository. A moved head, another review, an unknown id or a missing permission is refused and nothing is written. Retries are idempotent. The seam gate clears only when every finding of that integration review is dismissed; the Vortex gate at the head clears only once every Vortex Blocker (error finding) at that head is dismissed and no Vortex review of it is running (gate.vortex.cleared, else gate.vortex.message); CI and Auto land policy are unchanged. Vortex does not raise a dismissed finding again on the same diff. Never dismiss a finding you did not check.` + STACK_WATCH_RESULT_NOTE,
|
|
1346
1380
|
inputSchema: {
|
|
1347
1381
|
owner: z3.string().min(1),
|
|
1348
1382
|
repo: z3.string().min(1),
|
|
@@ -1369,7 +1403,7 @@ function createMergestormMcpServer() {
|
|
|
1369
1403
|
"stack_adopt",
|
|
1370
1404
|
{
|
|
1371
1405
|
title: "Adopt PR stack",
|
|
1372
|
-
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,
|
|
1373
1407
|
inputSchema: stackAdoptSchema,
|
|
1374
1408
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
|
|
1375
1409
|
},
|
|
@@ -1400,22 +1434,26 @@ function createMergestormMcpServer() {
|
|
|
1400
1434
|
"stack_set",
|
|
1401
1435
|
{
|
|
1402
1436
|
title: "Set stack policy",
|
|
1403
|
-
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,
|
|
1404
1438
|
inputSchema: {
|
|
1405
1439
|
stack_id: z3.string().min(1),
|
|
1406
1440
|
auto_land: z3.boolean().optional(),
|
|
1407
1441
|
auto_review: z3.boolean().nullable().optional(),
|
|
1408
|
-
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()
|
|
1409
1445
|
},
|
|
1410
1446
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: true }
|
|
1411
1447
|
},
|
|
1412
|
-
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 }) => {
|
|
1413
1449
|
try {
|
|
1414
1450
|
return ok(
|
|
1415
1451
|
await stackSet(stack_id, {
|
|
1416
1452
|
...auto_land !== void 0 ? { auto_land } : {},
|
|
1417
1453
|
...auto_review !== void 0 ? { auto_review } : {},
|
|
1418
|
-
...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 } : {}
|
|
1419
1457
|
})
|
|
1420
1458
|
);
|
|
1421
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.15",
|
|
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.44",
|
|
33
33
|
"zod": "^3.24.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|