mergestorm-mcp 0.1.8 → 0.1.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 +40 -9
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -592,6 +592,17 @@ function settingsPatchFromArgs(args) {
|
|
|
592
592
|
const value = args[key];
|
|
593
593
|
if (value === void 0) continue;
|
|
594
594
|
const row = BEARER_SETTINGS.find((row2) => row2.key === key);
|
|
595
|
+
if ("kind" in row && row.kind === "seconds") {
|
|
596
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < row.min || value > row.max) {
|
|
597
|
+
throw new CommandError8(
|
|
598
|
+
`${key} takes a whole number of seconds from ${row.min} through ${row.max}.`,
|
|
599
|
+
2,
|
|
600
|
+
"usage"
|
|
601
|
+
);
|
|
602
|
+
}
|
|
603
|
+
Object.assign(patch, { [key]: value });
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
595
606
|
if ("kind" in row) {
|
|
596
607
|
const valid = row.kind === "logins" ? Array.isArray(value) && value.every((login) => typeof login === "string") : typeof value === "string" && row.values.includes(value);
|
|
597
608
|
if (!valid) throw new CommandError8(`Invalid value for ${key}.`, 2, "usage");
|
|
@@ -791,6 +802,17 @@ var stackWaitSchema = {
|
|
|
791
802
|
after_finished_at: z2.string().nullable().optional(),
|
|
792
803
|
bounce_id: z2.string().nullable().optional()
|
|
793
804
|
};
|
|
805
|
+
function stackWaitSummary(envelope) {
|
|
806
|
+
const base = `Stack ${envelope.stackId} \xB7 ${envelope.status}${stackBlockersSummary2(envelope.blocker && envelope.prNumber != null ? { prNumber: envelope.prNumber, blocker: envelope.blocker } : null, envelope.issues)}${envelope.assessment === "unavailable" ? " \xB7 assessment unavailable" : ""}`;
|
|
807
|
+
if (envelope.status !== "waiting" && envelope.status !== "in_progress") return base;
|
|
808
|
+
const selectors = [
|
|
809
|
+
`stack_id ${JSON.stringify(envelope.cursor.stackId)}`,
|
|
810
|
+
`enrolled_head_sha ${JSON.stringify(envelope.cursor.enrolledHeadSha)}`,
|
|
811
|
+
...envelope.cursor.afterFinishedAt !== void 0 ? [`after_finished_at ${JSON.stringify(envelope.cursor.afterFinishedAt)}`] : [],
|
|
812
|
+
...envelope.cursor.bounceId !== void 0 ? [`bounce_id ${JSON.stringify(envelope.cursor.bounceId)}`] : []
|
|
813
|
+
];
|
|
814
|
+
return `${base} \xB7 watch not finished: call stack_wait again with timeout_s 45 and the same cursor: ${selectors.join(", ")}`;
|
|
815
|
+
}
|
|
794
816
|
async function stackWait(input, cfg, deps = {}) {
|
|
795
817
|
const args = z2.object(stackWaitSchema).parse(input);
|
|
796
818
|
const cursor = args.enrolled_head_sha !== void 0 || args.after_finished_at !== void 0 || args.bounce_id !== void 0 ? {
|
|
@@ -809,7 +831,7 @@ async function stackWait(input, cfg, deps = {}) {
|
|
|
809
831
|
} catch (err) {
|
|
810
832
|
if (err instanceof StackWatchError) {
|
|
811
833
|
return {
|
|
812
|
-
summary:
|
|
834
|
+
summary: stackWaitSummary(err.lastEnvelope),
|
|
813
835
|
data: {
|
|
814
836
|
...err.lastEnvelope,
|
|
815
837
|
...err.retryAfterSeconds !== void 0 ? { retry_after_seconds: err.retryAfterSeconds } : {}
|
|
@@ -821,7 +843,7 @@ async function stackWait(input, cfg, deps = {}) {
|
|
|
821
843
|
envelope = err.lastEnvelope;
|
|
822
844
|
}
|
|
823
845
|
return {
|
|
824
|
-
summary:
|
|
846
|
+
summary: stackWaitSummary(envelope),
|
|
825
847
|
data: envelope
|
|
826
848
|
};
|
|
827
849
|
}
|
|
@@ -923,6 +945,13 @@ var MCP_PR_LOOP_INSTRUCTIONS = [
|
|
|
923
945
|
`- 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).`,
|
|
924
946
|
"- Do not prefix that comment with cyclone-outcome: (reserved)."
|
|
925
947
|
].join("\n");
|
|
948
|
+
var MCP_STACK_BASE_INSTRUCTIONS = [
|
|
949
|
+
"Stack PR bases (Mergestorm sets these; leave them):",
|
|
950
|
+
"- Stack of 2+ PRs: after adopt (stack_adopt, mg stack adopt, or mg stack submit) the bottom PR's GitHub base is the owned trunk mg-stack-<n>, not main. That is correct. Layer 2 is based on layer 1; layer 3+ on the mg-park-* freeze; the git parent of layer 2+ is still the layer below. A 1-PR stack stays on main and gets no mg-stack-<n>.",
|
|
951
|
+
"- Never retarget a stack PR's GitHub base (gh pr edit --base, a REST base change, or the UI). Moving the bottom to main makes Mergestorm abandon the stack's review unit; setting mg-stack-<n> again does not restore it. If a base was already moved, stop and tell the human; do not run stack land or re-adopt to repair it.",
|
|
952
|
+
"- mg-stack-<n> is the bottom PR's live parent: merging it into the bottom branch is that PR's conflict repair (bounce-watch rules). Never push to mg-stack-<n>, and never rebase or merge layer 2+ onto it or onto main. mg-park-* is never a merge or rebase target.",
|
|
953
|
+
"- mg stack submit prints the base each PR opened with; the bottom moves to mg-stack-<n> right after. stack_status trunkBranch is the current trunk."
|
|
954
|
+
].join("\n");
|
|
926
955
|
var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
927
956
|
"Stack-watch facts (mergestorm.stack_watch/v1):",
|
|
928
957
|
"- waiting with nonempty issues[] is not idle; in_progress can also carry issues[].",
|
|
@@ -936,7 +965,7 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
|
936
965
|
|
|
937
966
|
// src/server.ts
|
|
938
967
|
var MCP_SERVER_NAME = "mergestorm";
|
|
939
|
-
var MCP_SERVER_VERSION = "0.1.
|
|
968
|
+
var MCP_SERVER_VERSION = "0.1.10";
|
|
940
969
|
function stripNulls(value) {
|
|
941
970
|
if (Array.isArray(value)) {
|
|
942
971
|
return value.map((item) => stripNulls(item));
|
|
@@ -972,6 +1001,8 @@ function createMergestormMcpServer() {
|
|
|
972
1001
|
},
|
|
973
1002
|
{ instructions: `${MCP_PR_LOOP_INSTRUCTIONS}
|
|
974
1003
|
|
|
1004
|
+
${MCP_STACK_BASE_INSTRUCTIONS}
|
|
1005
|
+
|
|
975
1006
|
${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
976
1007
|
);
|
|
977
1008
|
const addTool = server2.registerTool.bind(server2);
|
|
@@ -1148,7 +1179,7 @@ ${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
|
1148
1179
|
"stack_adopt",
|
|
1149
1180
|
{
|
|
1150
1181
|
title: "Adopt PR stack",
|
|
1151
|
-
description: "Adopt an open GitHub PR chain into a Mergestorm stack. auto_land is boolean; auto_review and auto_patch accept true, false, or null, where null clears the override. Omitted auto_land seeds from auto_land_default; omitted auto_review and auto_patch overrides are not seeded. Never changes account settings. Adoption requires a Cyclone GitHub App install; without it the API returns cyclone_not_connected \u2014 do not retry, tell the human. Read stack_status with result.stack.id afterward to verify policy and Cyclone ownership.",
|
|
1182
|
+
description: "Adopt an open GitHub PR chain into a Mergestorm stack. auto_land is boolean; auto_review and auto_patch accept true, false, or null, where null clears the override. Omitted auto_land seeds from auto_land_default; omitted auto_review and auto_patch overrides are not seeded. Never changes account settings. Adoption requires a Cyclone GitHub App install; without it the API returns cyclone_not_connected \u2014 do not retry, tell the human. 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.",
|
|
1152
1183
|
inputSchema: stackAdoptSchema
|
|
1153
1184
|
},
|
|
1154
1185
|
async (args) => {
|
|
@@ -1203,7 +1234,7 @@ ${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
|
1203
1234
|
"stack_status",
|
|
1204
1235
|
{
|
|
1205
1236
|
title: "Get stack status",
|
|
1206
|
-
description: "Fetch one owned Mergestorm 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. This tool is read-only.",
|
|
1237
|
+
description: "Fetch one owned Mergestorm 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. This tool is read-only. trunkBranch is mg-stack-<n> for an adopted 2+ PR stack and matches the bottom open PR's GitHub base; an mg-park-* parentBranch is a freeze. Neither is drift to fix.",
|
|
1207
1238
|
inputSchema: {
|
|
1208
1239
|
stack_id: z3.string().min(1)
|
|
1209
1240
|
}
|
|
@@ -1220,7 +1251,7 @@ ${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
|
1220
1251
|
"stack_wait",
|
|
1221
1252
|
{
|
|
1222
1253
|
title: "Wait for stack attention",
|
|
1223
|
-
description: "Wait for a stack to need attention. Returns a mergestorm.stack_watch/v1 envelope; timeout_s: 0 returns one snapshot and timeout_s: 1-45 waits up to that many seconds, returning the current status (waiting or in_progress) if a snapshot was read and no attention is found. A timeout with either of those statuses is not a failure. A timeout of failed means no assessment was produced. This tool is read-only.",
|
|
1254
|
+
description: "Wait for a stack to need attention. Returns a mergestorm.stack_watch/v1 envelope; timeout_s: 0 returns one snapshot and timeout_s: 1-45 waits up to that many seconds, returning the current status (waiting or in_progress) if a snapshot was read and no attention is found. A timeout with either of those statuses is not a failure; waiting and in_progress end this slice, and the next call is stack_wait again with the same cursor. A timeout of failed means no assessment was produced. This tool is read-only. Attention never calls for changing a PR's GitHub base.",
|
|
1224
1255
|
inputSchema: stackWaitSchema
|
|
1225
1256
|
},
|
|
1226
1257
|
async (args, extra) => {
|
|
@@ -1253,7 +1284,7 @@ ${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
|
1253
1284
|
"settings_get",
|
|
1254
1285
|
{
|
|
1255
1286
|
title: "Get settings",
|
|
1256
|
-
description: "Read the Bearer /api/v1/settings toggles, including auto_patch_enabled and cyclone_connected. This tool is read-only."
|
|
1287
|
+
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. This tool is read-only."
|
|
1257
1288
|
},
|
|
1258
1289
|
async () => {
|
|
1259
1290
|
try {
|
|
@@ -1267,12 +1298,12 @@ ${MCP_STACK_WATCH_INSTRUCTIONS}` }
|
|
|
1267
1298
|
"settings_set",
|
|
1268
1299
|
{
|
|
1269
1300
|
title: "Update settings",
|
|
1270
|
-
description: "Update writable Bearer /api/v1/settings values and return the stored result. At least one key is required. cyclone_connected and github_connected are read-only and cannot be set.",
|
|
1301
|
+
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.",
|
|
1271
1302
|
inputSchema: {
|
|
1272
1303
|
...Object.fromEntries(
|
|
1273
1304
|
BEARER_SETTINGS2.map((row) => [
|
|
1274
1305
|
row.key,
|
|
1275
|
-
("kind" in row ? row.kind === "logins" ? z3.array(z3.string()) : z3.enum(row.values) : z3.boolean()).optional()
|
|
1306
|
+
("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()
|
|
1276
1307
|
])
|
|
1277
1308
|
),
|
|
1278
1309
|
// 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.1.
|
|
3
|
+
"version": "0.1.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.24",
|
|
33
33
|
"zod": "^3.24.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|