mergestorm-mcp 0.2.21 → 0.2.23

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +117 -17
  3. 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 CommandError13, BEARER_SETTINGS as BEARER_SETTINGS2 } from "mergestorm/client";
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 CommandError10, stackWatchObligation as stackWatchObligation4 } from "mergestorm/client";
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 CommandError10 ? err.code ?? "stack_adopt_failed" : "stack_adopt_failed",
1073
+ code: err instanceof CommandError11 ? err.code ?? "stack_adopt_failed" : "stack_adopt_failed",
1012
1074
  message,
1013
- ...err instanceof CommandError10 ? { exit_code: err.exitCode } : {},
1014
- ...err instanceof CommandError10 && err.reason !== void 0 ? { reason: err.reason } : {},
1015
- ...err instanceof CommandError10 && err.retryAfterSeconds !== void 0 ? { retry_after_seconds: err.retryAfterSeconds } : {}
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 CommandError11,
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 CommandError11 ? err.code ?? fallback : fallback,
1177
+ code: err instanceof CommandError12 ? err.code ?? fallback : fallback,
1116
1178
  message,
1117
- ...err instanceof CommandError11 && err.retryAfterSeconds !== void 0 ? { retry_after_seconds: err.retryAfterSeconds } : {}
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 CommandError12,
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 CommandError12(
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 CommandError12("Live account details unavailable. Could not verify account with /me.");
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,
@@ -1327,6 +1389,7 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
1327
1389
  "- 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.",
1328
1390
  `- A stack whose layers are all merged into mg-stack-N but which has no open land PR (the branch was deleted, or the land PR cannot be opened) returns attention: blocker "No open land PR for mg-stack-N ...", repair kind land_pr_unavailable. Do not patch or push; tell the human to restore the branch from the closed land PR's head or close the stack.`,
1329
1391
  '- 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.',
1392
+ '- While stack autoLandOff reads reason cancelled or watcher and the current PR has no live blocker of its own (a live blocker is reported first, with its own repair), the watch returns attention: blocker "Auto land switched off: <why>", repair kind auto_land_switched_off. No bounce did it and the layers need no change: do not patch, push or turn Auto land back on yourself; tell the human, who decides whether to turn it back on.',
1330
1393
  '- 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.',
1331
1394
  `- 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.`,
1332
1395
  `- 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.`,
@@ -1340,7 +1403,7 @@ var MCP_STACK_WATCH_INSTRUCTIONS = [
1340
1403
 
1341
1404
  // src/server.ts
1342
1405
  var MCP_SERVER_NAME = "mergestorm";
1343
- var MCP_SERVER_VERSION = "0.2.21";
1406
+ var MCP_SERVER_VERSION = "0.2.23";
1344
1407
  var MCP_SERVER_INSTRUCTIONS = [
1345
1408
  MCP_STACK_DONE_INSTRUCTIONS,
1346
1409
  MCP_PR_LOOP_INSTRUCTIONS,
@@ -1359,14 +1422,14 @@ function ok(payload) {
1359
1422
  };
1360
1423
  }
1361
1424
  function fail(err) {
1362
- const message = err instanceof CommandError13 ? err.code ? `Mergestorm request failed (${err.code}${err.reason ? `, reason ${err.reason}` : ""}): ${err.message}.` : err.message : err instanceof Error ? err.message : String(err);
1425
+ 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
1426
  return ok({
1364
1427
  isError: true,
1365
1428
  summary: message,
1366
1429
  data: {
1367
1430
  error: {
1368
1431
  message: err instanceof Error ? err.message : String(err),
1369
- ...err instanceof CommandError13 ? {
1432
+ ...err instanceof CommandError14 ? {
1370
1433
  exit_code: err.exitCode,
1371
1434
  ...err.code !== void 0 ? { code: err.code } : {},
1372
1435
  ...err.reason !== void 0 ? { reason: err.reason } : {},
@@ -1659,7 +1722,7 @@ function createMergestormMcpServer() {
1659
1722
  "stack_status",
1660
1723
  {
1661
1724
  title: "Get stack status",
1662
- 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. 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. repair names the concrete fix for attention; landGatePending is a wait, not attention. held names a blocker no agent run clears while Vortex or Cyclone is still busy on that PR (actAfter agents_idle, waitingOn); repair then describes the fix to plan, not to apply yet. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue. A Vortex request_changes handoff at the live head returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify its findings against the live head.` + STACK_WATCH_RESULT_NOTE,
1725
+ 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. 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. repair names the concrete fix for attention; landGatePending is a wait, not attention. held names a blocker no agent run clears while Vortex or Cyclone is still busy on that PR (actAfter agents_idle, waitingOn); repair then describes the fix to plan, not to apply yet. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue. auto_land_switched_off (returned only when the PR has no live blocker of its own): Auto land was switched off without a bounce (queue entry cancelled, or nothing left to land); do not patch, push or turn it back on yourself, tell the human. A Vortex request_changes handoff at the live head returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify its findings against the live head.` + STACK_WATCH_RESULT_NOTE,
1663
1726
  inputSchema: {
1664
1727
  stack_id: z5.string().min(1)
1665
1728
  },
@@ -1677,7 +1740,7 @@ function createMergestormMcpServer() {
1677
1740
  "stack_wait",
1678
1741
  {
1679
1742
  title: "Wait for stack attention",
1680
- 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. A stack that no longer exists returns status failed with watch.done true (reason not_found) and is not an error. While Cyclone or Vortex is still working on the blocked PR it returns in_progress, not attention, with busy[] naming the PR, blocker, and agent; agents carries that PR's vortexStatus, cycloneStatus, vortexReview, and busy flags. 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: plan the fix, and act when a snapshot after the agents finish returns attention, re-reading the blocker then. Blockers the agents can change keep blocker and actAfter null. Attention never calls for changing a PR's GitHub base. When present, repair names the concrete fix for attention (restack_conflict and merge_conflict carry liveParent, never mg-park-*). For the three stuck-seam blockers, repair 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. A pending land gate (landGatePending) returns in_progress, not attention. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue. A Vortex request_changes handoff at the live head returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify its findings against the live head.` + STACK_WATCH_RESULT_NOTE,
1743
+ 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. A stack that no longer exists returns status failed with watch.done true (reason not_found) and is not an error. While Cyclone or Vortex is still working on the blocked PR it returns in_progress, not attention, with busy[] naming the PR, blocker, and agent; agents carries that PR's vortexStatus, cycloneStatus, vortexReview, and busy flags. 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: plan the fix, and act when a snapshot after the agents finish returns attention, re-reading the blocker then. Blockers the agents can change keep blocker and actAfter null. Attention never calls for changing a PR's GitHub base. When present, repair names the concrete fix for attention (restack_conflict and merge_conflict carry liveParent, never mg-park-*). For the three stuck-seam blockers, repair 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. A pending land gate (landGatePending) returns in_progress, not attention. Auto land off after a merge_failed, gh_error, or ci_timeout bounce (the stack's autoLandOff reads reason bounced) returns attention with the blocker "Auto land off after <kind> bounce", the bounce in issues[], and a repair of kind auto_land_off: fix the cause, then turn Auto land back on or enqueue. auto_land_switched_off (returned only when the PR has no live blocker of its own): Auto land was switched off without a bounce (queue entry cancelled, or nothing left to land); do not patch, push or turn it back on yourself, tell the human. A Vortex request_changes handoff at the live head returns attention with blocker "Vortex findings need a person" and repair kind vortex_findings; verify its findings against the live head.` + STACK_WATCH_RESULT_NOTE,
1681
1744
  inputSchema: stackWaitSchema,
1682
1745
  annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
1683
1746
  },
@@ -1708,6 +1771,43 @@ function createMergestormMcpServer() {
1708
1771
  }
1709
1772
  }
1710
1773
  );
1774
+ addTool(
1775
+ "repo_settings_get",
1776
+ {
1777
+ title: "Get repository settings",
1778
+ 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.",
1779
+ inputSchema: { repo: z5.string().min(3).optional() },
1780
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
1781
+ },
1782
+ async (args) => {
1783
+ try {
1784
+ return ok(await repoSettingsGet(args ?? {}));
1785
+ } catch (err) {
1786
+ return fail(err);
1787
+ }
1788
+ }
1789
+ );
1790
+ addTool(
1791
+ "repo_settings_set",
1792
+ {
1793
+ title: "Update repository settings",
1794
+ 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.",
1795
+ inputSchema: {
1796
+ repo: z5.string().min(3),
1797
+ auto_patch: z5.boolean().nullable().optional(),
1798
+ auto_review: z5.boolean().nullable().optional(),
1799
+ auto_land: z5.boolean().nullable().optional()
1800
+ },
1801
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
1802
+ },
1803
+ async (args) => {
1804
+ try {
1805
+ return ok(await repoSettingsSet(args ?? {}));
1806
+ } catch (err) {
1807
+ return fail(err);
1808
+ }
1809
+ }
1810
+ );
1711
1811
  addTool(
1712
1812
  "settings_get",
1713
1813
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mergestorm-mcp",
3
- "version": "0.2.21",
3
+ "version": "0.2.23",
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.54",
32
+ "mergestorm": "0.3.58",
33
33
  "zod": "^3.24.2"
34
34
  },
35
35
  "devDependencies": {