@mgsoftwarebv/mg-dashboard-mcp 7.0.1 → 7.0.2

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 CHANGED
@@ -677,10 +677,10 @@ var TRIGGER_TOOL_MODULE_MAP = {
677
677
  "trigger-run": "ci_cd"
678
678
  };
679
679
  async function discoverInstance(projectSlug, conn, proxy, sshExec2) {
680
- const sql25 = `SELECT re.\\"apiKey\\" FROM \\"RuntimeEnvironment\\" re JOIN \\"Project\\" p ON re.\\"projectId\\" = p.id WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;
680
+ const sql27 = `SELECT re.\\"apiKey\\" FROM \\"RuntimeEnvironment\\" re JOIN \\"Project\\" p ON re.\\"projectId\\" = p.id WHERE p.slug='${projectSlug}' AND re.slug='prod' LIMIT 1`;
681
681
  const cmd = [
682
682
  `PORT=$(docker port "${WA_CONTAINER}" 3000/tcp 2>/dev/null | head -1 | sed 's/.*://')`,
683
- `KEY=$(docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql25}" 2>/dev/null | tr -d '[:space:]')`,
683
+ `KEY=$(docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql27}" 2>/dev/null | tr -d '[:space:]')`,
684
684
  'echo "$PORT|$KEY"'
685
685
  ].join(" && ");
686
686
  const result = await sshExec2(conn, cmd, proxy);
@@ -701,8 +701,8 @@ async function discoverInstance(projectSlug, conn, proxy, sshExec2) {
701
701
  return { port, apiKey: apiKey2 };
702
702
  }
703
703
  async function fetchRunLogs(runId, conn, proxy, sshExec2) {
704
- const sql25 = `SELECT level, message, \\"isError\\", \\"createdAt\\" FROM \\"TaskEvent\\" WHERE \\"runId\\" = '${runId}' AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') ORDER BY \\"startTime\\" ASC LIMIT 200`;
705
- const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql25}" 2>/dev/null`;
704
+ const sql27 = `SELECT level, message, \\"isError\\", \\"createdAt\\" FROM \\"TaskEvent\\" WHERE \\"runId\\" = '${runId}' AND level IN ('INFO','WARN','ERROR','DEBUG','LOG','TRACE') ORDER BY \\"startTime\\" ASC LIMIT 200`;
705
+ const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql27}" 2>/dev/null`;
706
706
  const result = await sshExec2(conn, cmd, proxy);
707
707
  const output = result.stdout.trim();
708
708
  if (!output) return "";
@@ -784,8 +784,8 @@ async function handleTriggerTool(name, args2, deps) {
784
784
  switch (name) {
785
785
  // -----------------------------------------------------------------
786
786
  case "trigger-list": {
787
- const sql25 = 'SELECT slug, name FROM \\"Project\\" ORDER BY name';
788
- const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql25}" 2>/dev/null`;
787
+ const sql27 = 'SELECT slug, name FROM \\"Project\\" ORDER BY name';
788
+ const cmd = `docker exec "${PG_CONTAINER}" psql -U postgres -d main -t -A -c "${sql27}" 2>/dev/null`;
789
789
  const result = await sshExec2(conn, cmd, proxy);
790
790
  const output = result.stdout.trim();
791
791
  if (!output) {
@@ -5158,7 +5158,8 @@ function parseReleasePipelineConfig(value) {
5158
5158
  const config = value;
5159
5159
  const hasSshScripts = Array.isArray(config.sshScripts) && config.sshScripts.length > 0;
5160
5160
  const hasMigration = config.migration != null && typeof config.migration === "object";
5161
- if (!hasSshScripts && !hasMigration) return null;
5161
+ const hasNpmPublish = Array.isArray(config.npmPublish) && config.npmPublish.length > 0;
5162
+ if (!hasSshScripts && !hasMigration && !hasNpmPublish) return null;
5162
5163
  return config;
5163
5164
  }
5164
5165
  function injectSshScriptSteps(baseSteps, config, context = {}) {
@@ -5249,6 +5250,11 @@ function shouldRunConventionTests(profile, ctx) {
5249
5250
  if (repo === MG_DASHBOARD_REPO || repo === MG_BOILER_REPO) return true;
5250
5251
  return isBoilerPm2Build(ctx.buildFilters);
5251
5252
  }
5253
+ function npmPublishWatchPaths(config) {
5254
+ if (config.paths?.length) return config.paths;
5255
+ const dir = config.path.replace(/\/+$/, "");
5256
+ return [`${dir}/**`];
5257
+ }
5252
5258
 
5253
5259
  // ../jobs/src/build-step-list.ts
5254
5260
  function buildStepList(stage, profile, options) {
@@ -5290,6 +5296,19 @@ function buildStepList(stage, profile, options) {
5290
5296
  const pipelineConfig = parseReleasePipelineConfig(
5291
5297
  profile?.release_pipeline_config
5292
5298
  );
5299
+ for (const pkg of pipelineConfig?.npmPublish ?? []) {
5300
+ if (!pkg.id || !pkg.path) continue;
5301
+ steps.push({
5302
+ type: "publish_npm",
5303
+ label: pkg.label ?? `Publish npm (${pkg.path})`,
5304
+ stepConfig: {
5305
+ packageId: pkg.id,
5306
+ packagePath: pkg.path,
5307
+ watchPaths: npmPublishWatchPaths(pkg),
5308
+ tokenEnvVar: pkg.tokenEnvVar
5309
+ }
5310
+ });
5311
+ }
5293
5312
  const withScripts = injectSshScriptSteps(steps, pipelineConfig, {
5294
5313
  changedPaths: options?.changedPaths,
5295
5314
  runAllConditional: options?.runAllConditional,
@@ -6485,6 +6504,108 @@ async function getServerConnection(serverIdOrName) {
6485
6504
  const os = data.os_type === "windows" ? "windows" : "linux";
6486
6505
  return { serverId, conn, proxy, os };
6487
6506
  }
6507
+ function buildCachePurgeScript(mode) {
6508
+ const shared = `
6509
+ R=""
6510
+ # LiteSpeed cache files (delete files only \u2014 keep dirs + lock files)
6511
+ LS=0
6512
+ for cdir in /tmp/lshttpd/swap /usr/local/lsws/cachedata; do
6513
+ if [ -d "$cdir" ]; then
6514
+ n=$(find "$cdir" -type f 2>/dev/null | wc -l)
6515
+ if [ "$n" -gt 0 ]; then
6516
+ find "$cdir" -type f -delete 2>/dev/null && R="\${R}[OK] LS cache: removed $n file(s) under $cdir\\n" && LS=1 || R="\${R}[FAIL] LS cache: $cdir\\n"
6517
+ fi
6518
+ fi
6519
+ done
6520
+ [ "$LS" -eq 0 ] && R="\${R}[SKIP] LS cache: no cache files\\n"
6521
+ # WordPress + LiteSpeed plugin caches
6522
+ WP=0
6523
+ for dir in /var/www/*/; do
6524
+ [ -d "$dir" ] || continue
6525
+ for root in "$dir" "\${dir}html" "\${dir}public_html" "\${dir}public" "\${dir}httpdocs"; do
6526
+ [ -f "$root/wp-config.php" ] || continue
6527
+ WP=1; SITE=$(basename "$dir")
6528
+ if command -v wp >/dev/null 2>&1; then
6529
+ wp cache flush --allow-root --path="$root" 2>/dev/null && R="\${R}[OK] WP ($SITE): wp cache flush\\n" || R="\${R}[FAIL] WP ($SITE): wp cache flush\\n"
6530
+ if wp plugin is-active litespeed-cache --allow-root --path="$root" 2>/dev/null; then
6531
+ wp litespeed-purge all --allow-root --path="$root" 2>/dev/null && R="\${R}[OK] WP ($SITE): litespeed-purge all\\n" || R="\${R}[FAIL] WP ($SITE): litespeed-purge\\n"
6532
+ fi
6533
+ elif [ -d "$root/wp-content/cache" ]; then
6534
+ find "$root/wp-content/cache" -mindepth 1 -delete 2>/dev/null && R="\${R}[OK] WP ($SITE): cleared wp-content/cache\\n"
6535
+ else
6536
+ R="\${R}[SKIP] WP ($SITE): no cache dir, no wp-cli\\n"
6537
+ fi
6538
+ break
6539
+ done
6540
+ done
6541
+ [ "$WP" -eq 0 ] && R="\${R}[SKIP] WordPress: no sites found\\n"
6542
+ # PrestaShop file caches
6543
+ PS=0
6544
+ for dir in /var/www/*/; do
6545
+ [ -d "$dir" ] || continue
6546
+ for root in "$dir" "\${dir}html" "\${dir}public_html" "\${dir}public" "\${dir}httpdocs"; do
6547
+ IS=0
6548
+ [ -f "$root/app/config/parameters.php" ] && IS=1
6549
+ [ -f "$root/config/settings.inc.php" ] && IS=1
6550
+ [ "$IS" -eq 0 ] && continue
6551
+ PS=1; SITE=$(basename "$dir"); C=""
6552
+ [ -d "$root/var/cache" ] && find "$root/var/cache" -mindepth 1 -delete 2>/dev/null && C="\${C}var/cache "
6553
+ [ -d "$root/cache/smarty/compile" ] && find "$root/cache/smarty/compile" -mindepth 1 -delete 2>/dev/null && C="\${C}smarty/compile "
6554
+ [ -d "$root/cache/smarty/cache" ] && find "$root/cache/smarty/cache" -mindepth 1 -delete 2>/dev/null && C="\${C}smarty/cache "
6555
+ [ -n "$C" ] && R="\${R}[OK] PS ($SITE): cleared \${C}\\n" || R="\${R}[SKIP] PS ($SITE): no cache dirs\\n"
6556
+ break
6557
+ done
6558
+ done
6559
+ [ "$PS" -eq 0 ] && R="\${R}[SKIP] PrestaShop: no sites found\\n"
6560
+ `.trim();
6561
+ if (mode === "safe") {
6562
+ return `
6563
+ ${shared}
6564
+ # Safe mode: graceful LiteSpeed reload only (no killall lsphp, no Redis FLUSHALL)
6565
+ if [ -x /usr/local/lsws/bin/lswsctrl ]; then
6566
+ sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R="\${R}[OK] LiteSpeed: graceful restart (lswsctrl)\\n" || R="\${R}[FAIL] LiteSpeed: lswsctrl restart\\n"
6567
+ else
6568
+ R="\${R}[SKIP] LiteSpeed: lswsctrl not found\\n"
6569
+ fi
6570
+ R="\${R}[SKIP] OPcache: not reset in safe mode (use mode=full if needed)\\n"
6571
+ R="\${R}[SKIP] Redis: not flushed in safe mode (wp cache flush handles object cache per site)\\n"
6572
+ R="\${R}[SKIP] Memcached: not flushed in safe mode\\n"
6573
+ echo -e "$R"
6574
+ `.trim();
6575
+ }
6576
+ return `
6577
+ ${shared}
6578
+ # Full mode: nuclear steps \u2014 use only when safe purge is insufficient
6579
+ if pgrep -x lsphp >/dev/null 2>&1; then
6580
+ sudo killall lsphp 2>/dev/null && R="\${R}[OK] OPcache: killed lsphp processes\\n" || R="\${R}[FAIL] OPcache: could not kill lsphp\\n"
6581
+ else
6582
+ R="\${R}[SKIP] OPcache: no lsphp processes running\\n"
6583
+ fi
6584
+ if [ -x /usr/local/lsws/bin/lswsctrl ]; then
6585
+ sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R="\${R}[OK] LiteSpeed: graceful restart\\n" || R="\${R}[FAIL] LiteSpeed: restart failed\\n"
6586
+ elif systemctl is-active lsws >/dev/null 2>&1 || systemctl is-active lshttpd >/dev/null 2>&1; then
6587
+ sudo systemctl restart lsws 2>/dev/null || sudo systemctl restart lshttpd 2>/dev/null
6588
+ R="\${R}[OK] LiteSpeed: restarted via systemctl\\n"
6589
+ else
6590
+ R="\${R}[SKIP] LiteSpeed: not detected\\n"
6591
+ fi
6592
+ if command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then
6593
+ redis-cli FLUSHALL 2>/dev/null && R="\${R}[OK] Redis: FLUSHALL\\n" || R="\${R}[FAIL] Redis: FLUSHALL failed\\n"
6594
+ else
6595
+ R="\${R}[SKIP] Redis: not available\\n"
6596
+ fi
6597
+ if systemctl is-active memcached >/dev/null 2>&1; then
6598
+ if command -v memcflush >/dev/null 2>&1; then
6599
+ memcflush --servers=localhost 2>/dev/null && R="\${R}[OK] Memcached: flushed\\n" || R="\${R}[FAIL] Memcached: flush failed\\n"
6600
+ else
6601
+ echo "flush_all" | nc -q1 localhost 11211 2>/dev/null && R="\${R}[OK] Memcached: flushed via nc\\n" || R="\${R}[FAIL] Memcached: flush failed\\n"
6602
+ fi
6603
+ else
6604
+ R="\${R}[SKIP] Memcached: not active\\n"
6605
+ fi
6606
+ echo -e "$R"
6607
+ `.trim();
6608
+ }
6488
6609
  async function sshExec(opts, command, proxy, options) {
6489
6610
  const first = await sshExecOnce(opts, command, proxy, options);
6490
6611
  if (options?.noRetry) return first;
@@ -8276,11 +8397,11 @@ CREATE TABLE IF NOT EXISTS _mcp_migrations (
8276
8397
  applied_by TEXT
8277
8398
  );
8278
8399
  `.trim();
8279
- function normaliseMigrationSql(sql25) {
8280
- return sql25.replace(/\r\n/g, "\n").trim() + "\n";
8400
+ function normaliseMigrationSql(sql27) {
8401
+ return sql27.replace(/\r\n/g, "\n").trim() + "\n";
8281
8402
  }
8282
- function migrationSha256(sql25) {
8283
- return createHash("sha256").update(normaliseMigrationSql(sql25), "utf8").digest("hex");
8403
+ function migrationSha256(sql27) {
8404
+ return createHash("sha256").update(normaliseMigrationSql(sql27), "utf8").digest("hex");
8284
8405
  }
8285
8406
  function dollarQuoteTag(value) {
8286
8407
  let tag = "_mcp";
@@ -9349,11 +9470,16 @@ var TOOLS = [
9349
9470
  },
9350
9471
  {
9351
9472
  name: "cache-purge",
9352
- description: "Purge ALL caches on a server in one operation: OPcache (kills lsphp), LiteSpeed cache, WordPress object cache (wp-cli or file-based), PrestaShop Smarty/app cache, Redis FLUSHALL, and Memcached flush. Returns a per-cache status report.",
9473
+ description: 'Purge caches on a server. Default mode is **safe** (recommended): LiteSpeed file cache, WordPress/LiteSpeed plugin caches via wp-cli, PrestaShop file caches, graceful LiteSpeed reload \u2014 does NOT kill lsphp, FLUSHALL Redis, or hard-restart the web server.\n\nUse `mode: "full"` only when safe purge is insufficient: kills all lsphp (OPcache reset), clears Redis/Memcached entirely, and may hard-restart LiteSpeed \u2014 can briefly take sites offline or serve stale error pages until caches warm up (VCA multi-site risk).',
9353
9474
  inputSchema: {
9354
9475
  type: "object",
9355
9476
  properties: {
9356
- serverId: { type: "string", description: "UUID of the SSH server" }
9477
+ serverId: { type: "string", description: "UUID of the SSH server" },
9478
+ mode: {
9479
+ type: "string",
9480
+ enum: ["safe", "full"],
9481
+ description: "safe (default): wp cache flush + litespeed-purge per site, LiteSpeed cache files, graceful lswsctrl restart. full: legacy nuclear purge (killall lsphp, Redis FLUSHALL, memcached flush)."
9482
+ }
9357
9483
  },
9358
9484
  required: ["serverId"]
9359
9485
  }
@@ -11886,93 +12012,18 @@ LIMIT ${limit};
11886
12012
  // ----- Cache Purge -----
11887
12013
  case "cache-purge": {
11888
12014
  const { conn, proxy } = await getServerConnection(String(a.serverId));
11889
- conn.timeout = 12e4;
11890
- const script = `
11891
- R=""
11892
- # 1. OPcache \u2013 kill lsphp so it respawns with a fresh OPcache
11893
- if pgrep -x lsphp >/dev/null 2>&1; then
11894
- sudo killall lsphp 2>/dev/null && R="\${R}[OK] OPcache: killed lsphp processes\\n" || R="\${R}[FAIL] OPcache: could not kill lsphp\\n"
11895
- else
11896
- R="\${R}[SKIP] OPcache: no lsphp processes running\\n"
11897
- fi
11898
- # 2. LiteSpeed cache directories
11899
- LS=0
11900
- for cdir in /tmp/lshttpd/swap /usr/local/lsws/cachedata; do
11901
- if [ -d "$cdir" ] && [ "$(ls -A "$cdir" 2>/dev/null)" ]; then
11902
- sudo rm -rf "$cdir"/* 2>/dev/null && R="\${R}[OK] LS cache: cleared $cdir\\n" && LS=1 || R="\${R}[FAIL] LS cache: $cdir\\n"
11903
- fi
11904
- done
11905
- [ "$LS" -eq 0 ] && R="\${R}[SKIP] LS cache: no cache dirs with content\\n"
11906
- # 3. LiteSpeed graceful restart
11907
- if [ -x /usr/local/lsws/bin/lswsctrl ]; then
11908
- sudo /usr/local/lsws/bin/lswsctrl restart 2>/dev/null && R="\${R}[OK] LiteSpeed: graceful restart\\n" || R="\${R}[FAIL] LiteSpeed: restart failed\\n"
11909
- elif systemctl is-active lsws >/dev/null 2>&1 || systemctl is-active lshttpd >/dev/null 2>&1; then
11910
- sudo systemctl restart lsws 2>/dev/null || sudo systemctl restart lshttpd 2>/dev/null
11911
- R="\${R}[OK] LiteSpeed: restarted via systemctl\\n"
11912
- else
11913
- R="\${R}[SKIP] LiteSpeed: not detected\\n"
11914
- fi
11915
- # 4. WordPress caches
11916
- WP=0
11917
- for dir in /var/www/*/; do
11918
- [ -d "$dir" ] || continue
11919
- for root in "$dir" "\${dir}html" "\${dir}public_html" "\${dir}public" "\${dir}httpdocs"; do
11920
- [ -f "$root/wp-config.php" ] || continue
11921
- WP=1; SITE=$(basename "$dir")
11922
- if command -v wp >/dev/null 2>&1; then
11923
- wp cache flush --allow-root --path="$root" 2>/dev/null && R="\${R}[OK] WP ($SITE): wp cache flush\\n" || R="\${R}[FAIL] WP ($SITE): wp cache flush\\n"
11924
- elif [ -d "$root/wp-content/cache" ]; then
11925
- rm -rf "$root/wp-content/cache"/* 2>/dev/null && R="\${R}[OK] WP ($SITE): cleared wp-content/cache\\n"
11926
- else
11927
- R="\${R}[SKIP] WP ($SITE): no cache dir, no wp-cli\\n"
11928
- fi
11929
- break
11930
- done
11931
- done
11932
- [ "$WP" -eq 0 ] && R="\${R}[SKIP] WordPress: no sites found\\n"
11933
- # 5. PrestaShop caches
11934
- PS=0
11935
- for dir in /var/www/*/; do
11936
- [ -d "$dir" ] || continue
11937
- for root in "$dir" "\${dir}html" "\${dir}public_html" "\${dir}public" "\${dir}httpdocs"; do
11938
- IS=0
11939
- [ -f "$root/app/config/parameters.php" ] && IS=1
11940
- [ -f "$root/config/settings.inc.php" ] && IS=1
11941
- [ "$IS" -eq 0 ] && continue
11942
- PS=1; SITE=$(basename "$dir"); C=""
11943
- [ -d "$root/var/cache" ] && rm -rf "$root/var/cache"/* 2>/dev/null && C="\${C}var/cache "
11944
- [ -d "$root/cache/smarty/compile" ] && rm -rf "$root/cache/smarty/compile"/* 2>/dev/null && C="\${C}smarty/compile "
11945
- [ -d "$root/cache/smarty/cache" ] && rm -rf "$root/cache/smarty/cache"/* 2>/dev/null && C="\${C}smarty/cache "
11946
- [ -n "$C" ] && R="\${R}[OK] PS ($SITE): cleared \${C}\\n" || R="\${R}[SKIP] PS ($SITE): no cache dirs\\n"
11947
- break
11948
- done
11949
- done
11950
- [ "$PS" -eq 0 ] && R="\${R}[SKIP] PrestaShop: no sites found\\n"
11951
- # 6. Redis
11952
- if command -v redis-cli >/dev/null 2>&1 && redis-cli ping >/dev/null 2>&1; then
11953
- redis-cli FLUSHALL 2>/dev/null && R="\${R}[OK] Redis: FLUSHALL\\n" || R="\${R}[FAIL] Redis: FLUSHALL failed\\n"
11954
- else
11955
- R="\${R}[SKIP] Redis: not available\\n"
11956
- fi
11957
- # 7. Memcached
11958
- if systemctl is-active memcached >/dev/null 2>&1; then
11959
- if command -v memcflush >/dev/null 2>&1; then
11960
- memcflush --servers=localhost 2>/dev/null && R="\${R}[OK] Memcached: flushed\\n" || R="\${R}[FAIL] Memcached: flush failed\\n"
11961
- else
11962
- echo "flush_all" | nc -q1 localhost 11211 2>/dev/null && R="\${R}[OK] Memcached: flushed via nc\\n" || R="\${R}[FAIL] Memcached: flush failed\\n"
11963
- fi
11964
- else
11965
- R="\${R}[SKIP] Memcached: not active\\n"
11966
- fi
11967
- echo -e "$R"
11968
- `.trim();
12015
+ const mode = typeof a.mode === "string" && a.mode === "full" ? "full" : "safe";
12016
+ conn.timeout = mode === "full" ? 12e4 : 9e4;
12017
+ const script = buildCachePurgeScript(mode);
11969
12018
  const result = await sshExec(conn, script, proxy);
11970
12019
  const output = (result.stdout || "").trim();
12020
+ const header = `mode=${mode}
12021
+ `;
11971
12022
  return {
11972
12023
  content: [
11973
12024
  {
11974
12025
  type: "text",
11975
- text: output || "Cache purge completed (no output)"
12026
+ text: header + (output || "Cache purge completed (no output)")
11976
12027
  }
11977
12028
  ]
11978
12029
  };