mergestorm-mcp 0.2.8 → 0.2.10
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/dist/index.js +16 -13
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -221,7 +221,7 @@ function stackWaitSummary(envelope) {
|
|
|
221
221
|
return withWatchText(envelopeWatch(envelope), `${stackWaitStatusLine(envelope)}${repairSummary(envelope.repair)}`);
|
|
222
222
|
}
|
|
223
223
|
function stackWaitStatusLine(envelope) {
|
|
224
|
-
const base = `Stack ${envelope.stackId} \xB7 ${envelope.status}${stackBlockersSummary(envelope.blocker && envelope.prNumber != null ? { prNumber: envelope.prNumber, blocker: envelope.blocker } : null, envelope.issues, envelope.busy, envelope.landGatePending, envelope.actAfter ?? null)}${envelope.assessment === "unavailable" ? " \xB7 assessment unavailable" : ""}`;
|
|
224
|
+
const base = `Stack ${envelope.stackId} \xB7 ${envelope.status}${stackBlockersSummary(envelope.blocker && envelope.prNumber != null ? { prNumber: envelope.prNumber, blocker: envelope.blocker } : null, envelope.issues, envelope.busy, envelope.landGatePending, envelope.actAfter ?? null, envelope.queueWait ?? null)}${envelope.assessment === "unavailable" ? " \xB7 assessment unavailable" : ""}`;
|
|
225
225
|
if (envelopeWatch(envelope).done || envelope.status !== "waiting" && envelope.status !== "in_progress") return base;
|
|
226
226
|
const selectors = [
|
|
227
227
|
`stack_id ${JSON.stringify(envelope.cursor.stackId)}`,
|
|
@@ -791,10 +791,11 @@ function settingsPatchFromArgs(args) {
|
|
|
791
791
|
const value = args[key];
|
|
792
792
|
if (value === void 0) continue;
|
|
793
793
|
const row = BEARER_SETTINGS.find((row2) => row2.key === key);
|
|
794
|
-
if ("kind" in row && row.kind === "seconds") {
|
|
794
|
+
if ("kind" in row && (row.kind === "seconds" || row.kind === "count")) {
|
|
795
795
|
if (typeof value !== "number" || !Number.isInteger(value) || value < row.min || value > row.max) {
|
|
796
|
+
const unit = row.kind === "seconds" ? " of seconds" : "";
|
|
796
797
|
throw new CommandError8(
|
|
797
|
-
`${key} takes a whole number
|
|
798
|
+
`${key} takes a whole number${unit} from ${row.min} through ${row.max}.`,
|
|
798
799
|
2,
|
|
799
800
|
"usage"
|
|
800
801
|
);
|
|
@@ -962,8 +963,8 @@ function stackSummary(stack, entries = []) {
|
|
|
962
963
|
if (stack.cycloneOwnerMatch) {
|
|
963
964
|
overrides.push(`cyclone-owner ${stack.cycloneOwnerMatch}`);
|
|
964
965
|
}
|
|
965
|
-
const { attention, held, issues, busy, landGatePending } = stackBlockers(stack, entries);
|
|
966
|
-
return `${stack.owner}/${stack.repo} \xB7 ${layerLabel} \xB7 ${currentState} \xB7 auto-land ${stack.autoEnqueueWhenReady ? "on" : "off"}${overrides.map((label) => ` \xB7 ${label}`).join("")}${stackBlockersSummary2(attention ?? held, issues, busy, landGatePending, held?.actAfter ?? null)}`;
|
|
966
|
+
const { attention, held, issues, busy, landGatePending, queueWait } = stackBlockers(stack, entries);
|
|
967
|
+
return `${stack.owner}/${stack.repo} \xB7 ${layerLabel} \xB7 ${currentState} \xB7 auto-land ${stack.autoEnqueueWhenReady ? "on" : "off"}${overrides.map((label) => ` \xB7 ${label}`).join("")}${stackBlockersSummary2(attention ?? held, issues, busy, landGatePending, held?.actAfter ?? null, queueWait)}`;
|
|
967
968
|
}
|
|
968
969
|
|
|
969
970
|
// src/tools/stack-list.ts
|
|
@@ -1022,7 +1023,7 @@ async function stackStatus(stackId, cfg) {
|
|
|
1022
1023
|
};
|
|
1023
1024
|
}
|
|
1024
1025
|
const entries = await listMergeQueueEntries2(cfg, { stackId: stack.id });
|
|
1025
|
-
const { attention, held, issues, currentCandidate, busy, agents, repair, landGatePending } = stackBlockers2(stack, entries);
|
|
1026
|
+
const { attention, held, issues, currentCandidate, busy, agents, repair, landGatePending, queueWait } = stackBlockers2(stack, entries);
|
|
1026
1027
|
const watch = stackWatchObligation5({
|
|
1027
1028
|
stackId: stack.id,
|
|
1028
1029
|
terminal: stackTerminalReason(stack),
|
|
@@ -1032,7 +1033,7 @@ async function stackStatus(stackId, cfg) {
|
|
|
1032
1033
|
});
|
|
1033
1034
|
return {
|
|
1034
1035
|
summary: withWatchText(watch, `${stackSummary(stack, entries)}${repairSummary(repair)}`),
|
|
1035
|
-
data: { stack, attention, held, issues, currentCandidate, busy, agents, repair, landGatePending, watch }
|
|
1036
|
+
data: { stack, attention, held, issues, currentCandidate, busy, agents, repair, landGatePending, queueWait, watch }
|
|
1036
1037
|
};
|
|
1037
1038
|
} catch (err) {
|
|
1038
1039
|
if (isCommandErrorCode5(err, "rate_limited")) {
|
|
@@ -1141,15 +1142,17 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
|
1141
1142
|
"- merge_failed, gh_error, and ci_timeout bounces turn Auto land off, and stack autoLandOff then reads reason bounced with that queue entry's id; any other autoLandOff reason (user, archive, watcher, cancelled, landed) is not a bounce to undo. The watching agent turns Auto land back on with stack_set auto_land: true once it has handled that bounce, at most once per bounce and 3 times per watch; mergestorm-bounce-watch has the conditions.",
|
|
1142
1143
|
'- While stack autoLandOff reads reason bounced, the watch returns attention: blocker "Auto land off after <kind> bounce", the bounce in issues[], repair kind auto_land_off.',
|
|
1143
1144
|
'- A stack whose review unit was abandoned (a human moved its bottom PR off mg-stack-N) returns attention: blocker "Review unit abandoned: based on <base>", repair kind unit_abandoned. Do not patch or retarget; ask the human whether to re-root it. If at least two PRs remain open, tell them that mg stack adopt owner/repo#<bottom PR> re-roots it on a new review unit. With only one open PR, re-adopting will not create a review unit, so tell them to close and resubmit it to create a fresh stack.',
|
|
1144
|
-
|
|
1145
|
+
`- Auto land records why it is waiting (stack autoLandWait: reason, prNumber, headSha, since). The watch returns attention on that PR when the wait cannot clear on its own: a failing check Auto land reads live on GitHub, even while the ledger shows CI green (blocker "CI failed \u2014 Auto land reads a failing check on GitHub at this head", repair kind ci_failure); a check pending for 45 minutes (repair kind ci_pending); no approving Vortex review for 30 minutes with no Vortex run working (repair kind vortex_not_green); and a promote GitHub refused 3 times with merge_failed, after which Auto land stops retrying that head (repair kind promote_failed). It also returns attention when GitHub refuses to let Mergestorm read the head's check runs or commit statuses (blocker "Mergestorm cannot read ... on this head", repair kind ci_unreadable: do not patch or push; tell the human to grant the Mergestorm GitHub App the permission the repair names), and when any other wait reason has held for 45 minutes, a land gate left pending or running on the land PR included (blocker "Auto land has waited <N>m: <reason in plain words>", repair kind auto_land_waiting: read stack_status, fix what a commit on the named branch can fix, otherwise tell the human what Auto land waits for and since when). A more specific blocker on that PR is named first. A new head clears the wait.`,
|
|
1146
|
+
`- 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.`,
|
|
1147
|
+
'- 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.',
|
|
1145
1148
|
'- 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.',
|
|
1146
|
-
"- Tempest never patches. Cyclone patches a land PR when auto-patch is on for that stack (its override, else the account setting); otherwise the watching agent fixes tempest_findings on the land PR, and repair kind tempest_findings names it.",
|
|
1149
|
+
"- Tempest never patches. Cyclone patches a land PR when auto-patch is on for that stack (its override, else the account setting); otherwise the watching agent fixes tempest_findings on the land PR, and repair kind tempest_findings names it. A Tempest run that breaks without a result is re-run by Mergestorm at the same head a few times; after that the land gate reads tempest_failed with repair kind tempest_rerun: there is nothing to patch, so re-run Tempest with the comment the repair names. tempest_stopped (a person stopped the review) also carries repair kind tempest_rerun: ask the human before re-running it.",
|
|
1147
1150
|
"- Use the mergestorm-bounce-watch skill for the fix-then-watch policy."
|
|
1148
1151
|
].join("\n");
|
|
1149
1152
|
|
|
1150
1153
|
// src/server.ts
|
|
1151
1154
|
var MCP_SERVER_NAME = "mergestorm";
|
|
1152
|
-
var MCP_SERVER_VERSION = "0.2.
|
|
1155
|
+
var MCP_SERVER_VERSION = "0.2.10";
|
|
1153
1156
|
var MCP_SERVER_INSTRUCTIONS = [
|
|
1154
1157
|
MCP_STACK_DONE_INSTRUCTIONS,
|
|
1155
1158
|
MCP_PR_LOOP_INSTRUCTIONS,
|
|
@@ -1468,7 +1471,7 @@ function createMergestormMcpServer() {
|
|
|
1468
1471
|
"settings_get",
|
|
1469
1472
|
{
|
|
1470
1473
|
title: "Get settings",
|
|
1471
|
-
description: "Read the Bearer /api/v1/settings toggles, including auto_patch_enabled, auto_land_settle_seconds (how long Auto land waits before queueing), and cyclone_connected.",
|
|
1474
|
+
description: "Read the Bearer /api/v1/settings toggles, including auto_patch_enabled, auto_land_settle_seconds (how long Auto land waits before queueing), merge_queue_batch_enabled and merge_queue_batch_size (whether the merge queue tests several pull requests on one CI run, and how many), and cyclone_connected.",
|
|
1472
1475
|
annotations: { readOnlyHint: true }
|
|
1473
1476
|
},
|
|
1474
1477
|
async () => {
|
|
@@ -1483,12 +1486,12 @@ function createMergestormMcpServer() {
|
|
|
1483
1486
|
"settings_set",
|
|
1484
1487
|
{
|
|
1485
1488
|
title: "Update settings",
|
|
1486
|
-
description: "Update writable Bearer /api/v1/settings values and return the stored result. At least one key is required. auto_land_settle_seconds is a whole number of seconds from 15 through 300; it applies to settle clocks that start after the write. cyclone_connected and github_connected are read-only and cannot be set.",
|
|
1489
|
+
description: "Update writable Bearer /api/v1/settings values and return the stored result. At least one key is required. auto_land_settle_seconds is a whole number of seconds from 15 through 300; it applies to settle clocks that start after the write. merge_queue_batch_enabled turns merge queue batching on or off for the account, and merge_queue_batch_size is a whole number from 2 through 8. cyclone_connected and github_connected are read-only and cannot be set.",
|
|
1487
1490
|
inputSchema: {
|
|
1488
1491
|
...Object.fromEntries(
|
|
1489
1492
|
BEARER_SETTINGS2.map((row) => [
|
|
1490
1493
|
row.key,
|
|
1491
|
-
("kind" in row ? row.kind === "logins" ? z3.array(z3.string()) : row.kind === "seconds" ? z3.number().int().min(row.min).max(row.max) : z3.enum(row.values) : z3.boolean()).optional()
|
|
1494
|
+
("kind" in row ? row.kind === "logins" ? z3.array(z3.string()) : row.kind === "seconds" || row.kind === "count" ? z3.number().int().min(row.min).max(row.max) : z3.enum(row.values) : z3.boolean()).optional()
|
|
1492
1495
|
])
|
|
1493
1496
|
),
|
|
1494
1497
|
// Preserve these args so the handler rejects them even alongside a writable key.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mergestorm-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.10",
|
|
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.38",
|
|
33
33
|
"zod": "^3.24.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|