mergestorm-mcp 0.2.21 → 0.2.22
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 +1 -1
- package/dist/index.js +114 -15
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# mergestorm-mcp
|
|
2
2
|
|
|
3
|
-
Stdio MCP server for Mergestorm. Tools: `whoami`, `credits`, `review_list`, `review_submit`, `review_wait`, `review_wait_pr`, `review_dismiss`, `issue_create`, `stack_adopt`, `stack_list`, `stack_publish`, `stack_publish_status`, `stack_set`, `stack_status`, `stack_wait`, `queue_status`, `settings_get`, `settings_set`.
|
|
3
|
+
Stdio MCP server for Mergestorm. Tools: `whoami`, `credits`, `review_list`, `review_submit`, `review_wait`, `review_wait_pr`, `review_dismiss`, `issue_create`, `stack_adopt`, `stack_list`, `stack_publish`, `stack_publish_status`, `stack_set`, `stack_status`, `stack_wait`, `queue_status`, `settings_get`, `settings_set`, `repo_settings_get`, `repo_settings_set`.
|
|
4
4
|
|
|
5
5
|
Every tool declares MCP `annotations` for read-only access, destructive changes, idempotence, and external systems. Reads are read-only; submission, adoption, dismissal, and policy changes are writes. Tools that can change existing policy, topology, or review gates are marked potentially destructive even when some inputs only preview or read. Annotations describe effects; the client still controls approval and authorization.
|
|
6
6
|
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
|
6
6
|
// src/server.ts
|
|
7
7
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
8
|
import { z as z5 } from "zod";
|
|
9
|
-
import { CommandError as
|
|
9
|
+
import { CommandError as CommandError14, BEARER_SETTINGS as BEARER_SETTINGS2 } from "mergestorm/client";
|
|
10
10
|
|
|
11
11
|
// src/brand-icons.ts
|
|
12
12
|
var MARK_RECTS = [
|
|
@@ -897,8 +897,70 @@ async function settingsSet(args, cfg) {
|
|
|
897
897
|
};
|
|
898
898
|
}
|
|
899
899
|
|
|
900
|
+
// src/tools/repo-settings.ts
|
|
901
|
+
import {
|
|
902
|
+
CommandError as CommandError10,
|
|
903
|
+
REPO_SETTINGS_KEYS,
|
|
904
|
+
listRepoSettings,
|
|
905
|
+
patchRepoSettings
|
|
906
|
+
} from "mergestorm/client";
|
|
907
|
+
var ARG_BY_KEY = {
|
|
908
|
+
auto_patch_enabled: "auto_patch",
|
|
909
|
+
auto_review_enabled: "auto_review",
|
|
910
|
+
auto_land_default: "auto_land"
|
|
911
|
+
};
|
|
912
|
+
function parseRepo(raw) {
|
|
913
|
+
const match = typeof raw === "string" ? /^([A-Za-z0-9_.-]+)\/([A-Za-z0-9_.-]+)$/.exec(raw.trim()) : null;
|
|
914
|
+
if (!match) throw new CommandError10("repo takes <owner>/<repo>.", 2, "usage");
|
|
915
|
+
return { owner: match[1], repo: match[2] };
|
|
916
|
+
}
|
|
917
|
+
function words(value) {
|
|
918
|
+
return value === null ? "inherit" : value ? "on" : "off";
|
|
919
|
+
}
|
|
920
|
+
function repoSettingsSummary(entry) {
|
|
921
|
+
return `${entry.owner}/${entry.repo}: ${REPO_SETTINGS_KEYS.map((key) => `${ARG_BY_KEY[key]} ${words(entry[key])}`).join(" \xB7 ")}`;
|
|
922
|
+
}
|
|
923
|
+
function repoSettingsPatchFromArgs(args) {
|
|
924
|
+
const patch = {};
|
|
925
|
+
for (const key of REPO_SETTINGS_KEYS) {
|
|
926
|
+
const value = args[ARG_BY_KEY[key]];
|
|
927
|
+
if (value === void 0) continue;
|
|
928
|
+
if (value !== null && typeof value !== "boolean") {
|
|
929
|
+
throw new CommandError10(`${ARG_BY_KEY[key]} takes true, false, or null.`, 2, "usage");
|
|
930
|
+
}
|
|
931
|
+
patch[key] = value;
|
|
932
|
+
}
|
|
933
|
+
if (Object.keys(patch).length === 0) {
|
|
934
|
+
throw new CommandError10(
|
|
935
|
+
`At least one of ${Object.values(ARG_BY_KEY).join(", ")} is required.`,
|
|
936
|
+
2,
|
|
937
|
+
"usage"
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
return patch;
|
|
941
|
+
}
|
|
942
|
+
async function repoSettingsGet(args, cfg) {
|
|
943
|
+
const wanted = args.repo === void 0 ? null : parseRepo(args.repo);
|
|
944
|
+
const all = await listRepoSettings(cfg);
|
|
945
|
+
if (!wanted) {
|
|
946
|
+
return {
|
|
947
|
+
summary: all.length === 0 ? "No repositories are connected to this account." : all.map(repoSettingsSummary).join("\n"),
|
|
948
|
+
data: { repos: all }
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
const slug = `${wanted.owner}/${wanted.repo}`.toLowerCase();
|
|
952
|
+
const entry = all.find((candidate) => `${candidate.owner}/${candidate.repo}`.toLowerCase() === slug);
|
|
953
|
+
if (!entry) throw new CommandError10(`${wanted.owner}/${wanted.repo} is not connected to this account.`);
|
|
954
|
+
return { summary: repoSettingsSummary(entry), data: { ...entry } };
|
|
955
|
+
}
|
|
956
|
+
async function repoSettingsSet(args, cfg) {
|
|
957
|
+
const { owner, repo } = parseRepo(args.repo);
|
|
958
|
+
const entry = await patchRepoSettings(owner, repo, repoSettingsPatchFromArgs(args), cfg);
|
|
959
|
+
return { summary: repoSettingsSummary(entry), data: { ...entry } };
|
|
960
|
+
}
|
|
961
|
+
|
|
900
962
|
// src/tools/stack-adopt.ts
|
|
901
|
-
import { adoptStack, CommandError as
|
|
963
|
+
import { adoptStack, CommandError as CommandError11, stackWatchObligation as stackWatchObligation4 } from "mergestorm/client";
|
|
902
964
|
import { z as z3 } from "zod";
|
|
903
965
|
|
|
904
966
|
// src/tools/stack-set.ts
|
|
@@ -1008,11 +1070,11 @@ async function stackAdopt(input, cfg) {
|
|
|
1008
1070
|
summary: message,
|
|
1009
1071
|
data: {
|
|
1010
1072
|
error: {
|
|
1011
|
-
code: err instanceof
|
|
1073
|
+
code: err instanceof CommandError11 ? err.code ?? "stack_adopt_failed" : "stack_adopt_failed",
|
|
1012
1074
|
message,
|
|
1013
|
-
...err instanceof
|
|
1014
|
-
...err instanceof
|
|
1015
|
-
...err instanceof
|
|
1075
|
+
...err instanceof CommandError11 ? { exit_code: err.exitCode } : {},
|
|
1076
|
+
...err instanceof CommandError11 && err.reason !== void 0 ? { reason: err.reason } : {},
|
|
1077
|
+
...err instanceof CommandError11 && err.retryAfterSeconds !== void 0 ? { retry_after_seconds: err.retryAfterSeconds } : {}
|
|
1016
1078
|
}
|
|
1017
1079
|
},
|
|
1018
1080
|
isError: true
|
|
@@ -1083,7 +1145,7 @@ async function stackList(cfg) {
|
|
|
1083
1145
|
|
|
1084
1146
|
// src/tools/stack-publish.ts
|
|
1085
1147
|
import {
|
|
1086
|
-
CommandError as
|
|
1148
|
+
CommandError as CommandError12,
|
|
1087
1149
|
publishWorkingBranch,
|
|
1088
1150
|
stackWatchObligation as stackWatchObligation5,
|
|
1089
1151
|
workingBranchPublication
|
|
@@ -1112,9 +1174,9 @@ function failure(err, fallback) {
|
|
|
1112
1174
|
summary: message,
|
|
1113
1175
|
data: {
|
|
1114
1176
|
error: {
|
|
1115
|
-
code: err instanceof
|
|
1177
|
+
code: err instanceof CommandError12 ? err.code ?? fallback : fallback,
|
|
1116
1178
|
message,
|
|
1117
|
-
...err instanceof
|
|
1179
|
+
...err instanceof CommandError12 && err.retryAfterSeconds !== void 0 ? { retry_after_seconds: err.retryAfterSeconds } : {}
|
|
1118
1180
|
}
|
|
1119
1181
|
},
|
|
1120
1182
|
isError: true
|
|
@@ -1246,7 +1308,7 @@ async function stackStatus(stackId, cfg) {
|
|
|
1246
1308
|
|
|
1247
1309
|
// src/tools/whoami.ts
|
|
1248
1310
|
import {
|
|
1249
|
-
CommandError as
|
|
1311
|
+
CommandError as CommandError13,
|
|
1250
1312
|
apiBase,
|
|
1251
1313
|
configPath,
|
|
1252
1314
|
getMe as getMe2,
|
|
@@ -1257,7 +1319,7 @@ async function whoami(cfg, serverVersion) {
|
|
|
1257
1319
|
const resolved = cfg ?? await loadConfig7();
|
|
1258
1320
|
const key = resolveApiKey(resolved);
|
|
1259
1321
|
if (!key) {
|
|
1260
|
-
throw new
|
|
1322
|
+
throw new CommandError13(
|
|
1261
1323
|
"No API key. Run `mergestorm login` (agents: `mergestorm login --start`, then `--finish`) or set MERGESTORM_API_KEY.",
|
|
1262
1324
|
1,
|
|
1263
1325
|
"missing_api_key"
|
|
@@ -1265,7 +1327,7 @@ async function whoami(cfg, serverVersion) {
|
|
|
1265
1327
|
}
|
|
1266
1328
|
const me = await getMe2(resolved);
|
|
1267
1329
|
if (!me) {
|
|
1268
|
-
throw new
|
|
1330
|
+
throw new CommandError13("Live account details unavailable. Could not verify account with /me.");
|
|
1269
1331
|
}
|
|
1270
1332
|
const data = {
|
|
1271
1333
|
key_prefix: me.key.prefix,
|
|
@@ -1340,7 +1402,7 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
|
|
|
1340
1402
|
|
|
1341
1403
|
// src/server.ts
|
|
1342
1404
|
var MCP_SERVER_NAME = "mergestorm";
|
|
1343
|
-
var MCP_SERVER_VERSION = "0.2.
|
|
1405
|
+
var MCP_SERVER_VERSION = "0.2.22";
|
|
1344
1406
|
var MCP_SERVER_INSTRUCTIONS = [
|
|
1345
1407
|
MCP_STACK_DONE_INSTRUCTIONS,
|
|
1346
1408
|
MCP_PR_LOOP_INSTRUCTIONS,
|
|
@@ -1359,14 +1421,14 @@ function ok(payload) {
|
|
|
1359
1421
|
};
|
|
1360
1422
|
}
|
|
1361
1423
|
function fail(err) {
|
|
1362
|
-
const message = err instanceof
|
|
1424
|
+
const message = err instanceof CommandError14 ? err.code ? `Mergestorm request failed (${err.code}${err.reason ? `, reason ${err.reason}` : ""}): ${err.message}.` : err.message : err instanceof Error ? err.message : String(err);
|
|
1363
1425
|
return ok({
|
|
1364
1426
|
isError: true,
|
|
1365
1427
|
summary: message,
|
|
1366
1428
|
data: {
|
|
1367
1429
|
error: {
|
|
1368
1430
|
message: err instanceof Error ? err.message : String(err),
|
|
1369
|
-
...err instanceof
|
|
1431
|
+
...err instanceof CommandError14 ? {
|
|
1370
1432
|
exit_code: err.exitCode,
|
|
1371
1433
|
...err.code !== void 0 ? { code: err.code } : {},
|
|
1372
1434
|
...err.reason !== void 0 ? { reason: err.reason } : {},
|
|
@@ -1708,6 +1770,43 @@ function createMergestormMcpServer() {
|
|
|
1708
1770
|
}
|
|
1709
1771
|
}
|
|
1710
1772
|
);
|
|
1773
|
+
addTool(
|
|
1774
|
+
"repo_settings_get",
|
|
1775
|
+
{
|
|
1776
|
+
title: "Get repository settings",
|
|
1777
|
+
description: "Read the repository-level Auto patch, Auto review and Auto land values for the repositories connected to this account. Each value is true, false, or null; null means not set, so the account setting applies. Auto patch and Auto review precedence is the stack override (stack_set), then the repository value, then the account setting (settings_get). The Auto land repository value only seeds new stacks at adoption; it does not override an existing stack. Pass repo as owner/repo for one repository, or omit it for all.",
|
|
1778
|
+
inputSchema: { repo: z5.string().min(3).optional() },
|
|
1779
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
1780
|
+
},
|
|
1781
|
+
async (args) => {
|
|
1782
|
+
try {
|
|
1783
|
+
return ok(await repoSettingsGet(args ?? {}));
|
|
1784
|
+
} catch (err) {
|
|
1785
|
+
return fail(err);
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
);
|
|
1789
|
+
addTool(
|
|
1790
|
+
"repo_settings_set",
|
|
1791
|
+
{
|
|
1792
|
+
title: "Update repository settings",
|
|
1793
|
+
description: "Set Auto patch (Cyclone), Auto review (Vortex) or the Auto land default for every stack and pull request in one repository connected to this account, and return the stored result. true or false sets the repository value; null clears it so the account setting applies again. A stack override (stack_set) still wins for that stack. auto_patch and auto_review apply to open stacks without an override from their next decision; nothing is cancelled or re-queued. auto_land only seeds new stacks. Only the account that connected the repository can change it. Never changes account settings.",
|
|
1794
|
+
inputSchema: {
|
|
1795
|
+
repo: z5.string().min(3),
|
|
1796
|
+
auto_patch: z5.boolean().nullable().optional(),
|
|
1797
|
+
auto_review: z5.boolean().nullable().optional(),
|
|
1798
|
+
auto_land: z5.boolean().nullable().optional()
|
|
1799
|
+
},
|
|
1800
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
|
|
1801
|
+
},
|
|
1802
|
+
async (args) => {
|
|
1803
|
+
try {
|
|
1804
|
+
return ok(await repoSettingsSet(args ?? {}));
|
|
1805
|
+
} catch (err) {
|
|
1806
|
+
return fail(err);
|
|
1807
|
+
}
|
|
1808
|
+
}
|
|
1809
|
+
);
|
|
1711
1810
|
addTool(
|
|
1712
1811
|
"settings_get",
|
|
1713
1812
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mergestorm-mcp",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.22",
|
|
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.56",
|
|
33
33
|
"zod": "^3.24.2"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|