@mgsoftwarebv/mg-dashboard-mcp 7.4.17 → 7.4.18

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 (2) hide show
  1. package/dist/index.js +158 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawn } from 'child_process';
3
- import { existsSync, statSync, createReadStream, readFileSync } from 'fs';
4
- import { isAbsolute, join } from 'path';
3
+ import { readFileSync, existsSync, statSync, createReadStream } from 'fs';
4
+ import { join, dirname, sep, isAbsolute } from 'path';
5
5
  import { Client as Client$1 } from '@modelcontextprotocol/sdk/client/index.js';
6
6
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
7
7
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
@@ -21,6 +21,7 @@ import { sql } from 'drizzle-orm';
21
21
  import { once } from 'events';
22
22
  import { lookup } from 'dns/promises';
23
23
  import { connect } from 'tls';
24
+ import { fileURLToPath } from 'url';
24
25
  import { pgTable, timestamp, uuid, jsonb, boolean, text, customType, integer, date, real, index, uniqueIndex, pgEnum, check, bigint, doublePrecision, primaryKey, foreignKey } from 'drizzle-orm/pg-core';
25
26
  import { HeadObjectCommand, ListObjectsV2Command, DeleteObjectsCommand, S3Client, DeleteObjectCommand, CreateMultipartUploadCommand, UploadPartCommand, CompleteMultipartUploadCommand, AbortMultipartUploadCommand, PutObjectCommand, GetObjectCommand, CopyObjectCommand } from '@aws-sdk/client-s3';
26
27
 
@@ -839,13 +840,13 @@ async function handleTriggerTool(name, args2, deps) {
839
840
  return { content: [{ type: "text", text: "No Trigger.dev projects found." }] };
840
841
  }
841
842
  const header = `${"SLUG".padEnd(25)} NAME`;
842
- const sep = "-".repeat(55);
843
+ const sep2 = "-".repeat(55);
843
844
  const lines = output.split("\n").map((line) => {
844
845
  const [slug, name2] = line.split("|");
845
846
  return `${(slug || "").padEnd(25)} ${name2 || ""}`;
846
847
  });
847
848
  return { content: [{ type: "text", text: `${header}
848
- ${sep}
849
+ ${sep2}
849
850
  ${lines.join("\n")}` }] };
850
851
  }
851
852
  // -----------------------------------------------------------------
@@ -1315,6 +1316,151 @@ async function proxyJson(ctx, route, body) {
1315
1316
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
1316
1317
  };
1317
1318
  }
1319
+ var MCP_NPM_PACKAGE = "@mgsoftwarebv/mg-dashboard-mcp";
1320
+ var MCP_SKIP_SELF_UPDATE_ENV = "MG_MCP_SKIP_SELF_UPDATE";
1321
+ var MCP_SELF_UPDATE_TIMEOUT_MS = 2500;
1322
+ var MCP_REQUIRED_VERSION_PATH = "/api/mcp/required-version";
1323
+ var MG_DASHBOARD_ORIGIN_DEFAULT = "https://dashboard.mgsoftware.nl";
1324
+ function npmLatestUrl(pkg = MCP_NPM_PACKAGE) {
1325
+ const slash = pkg.indexOf("/");
1326
+ if (slash < 0) return `https://registry.npmjs.org/${pkg}/latest`;
1327
+ return `https://registry.npmjs.org/${pkg.slice(0, slash)}%2f${pkg.slice(slash + 1)}/latest`;
1328
+ }
1329
+ function parseNpmVersion(value) {
1330
+ const match = /^(\d+)\.(\d+)\.(\d+)/.exec(value?.trim() ?? "");
1331
+ if (!match) return null;
1332
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
1333
+ }
1334
+ function isNpmVersionBehind(installed, latest) {
1335
+ const a = parseNpmVersion(installed);
1336
+ const b = parseNpmVersion(latest);
1337
+ if (!a || !b) return false;
1338
+ if (a[0] !== b[0]) return a[0] < b[0];
1339
+ if (a[1] !== b[1]) return a[1] < b[1];
1340
+ return a[2] < b[2];
1341
+ }
1342
+ function packageRootFromModuleUrl(moduleUrl) {
1343
+ const here = dirname(fileURLToPath(moduleUrl));
1344
+ const base = here.split(sep).pop();
1345
+ if (base === "dist" || base === "src") return join(here, "..");
1346
+ return here;
1347
+ }
1348
+ function isLocalMonorepoCheckout(packageRoot) {
1349
+ return existsSync(join(packageRoot, "../../apps/backoffice/package.json"));
1350
+ }
1351
+ function readInstalledMcpVersion(packageRoot = packageRootFromModuleUrl(import.meta.url)) {
1352
+ try {
1353
+ const raw = readFileSync(join(packageRoot, "package.json"), "utf8");
1354
+ const parsed = JSON.parse(raw);
1355
+ return typeof parsed.version === "string" ? parsed.version : null;
1356
+ } catch {
1357
+ return null;
1358
+ }
1359
+ }
1360
+ function mcpRequiredVersionUrl(origin = MG_DASHBOARD_ORIGIN_DEFAULT) {
1361
+ return `${origin.replace(/\/$/, "")}${MCP_REQUIRED_VERSION_PATH}`;
1362
+ }
1363
+ function parseDashboardRequiredVersion(json) {
1364
+ if (!json || typeof json !== "object") return null;
1365
+ const version = json.version;
1366
+ if (typeof version !== "string") return null;
1367
+ return parseNpmVersion(version) ? version.trim() : null;
1368
+ }
1369
+ async function fetchDashboardRequiredVersion(fetchFn, origin, timeoutMs = MCP_SELF_UPDATE_TIMEOUT_MS) {
1370
+ const controller = new AbortController();
1371
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1372
+ try {
1373
+ const response = await fetchFn(mcpRequiredVersionUrl(origin), {
1374
+ signal: controller.signal,
1375
+ headers: { Accept: "application/json", "cache-control": "no-store" }
1376
+ });
1377
+ if (!response.ok) return null;
1378
+ return parseDashboardRequiredVersion(await response.json());
1379
+ } catch {
1380
+ return null;
1381
+ } finally {
1382
+ clearTimeout(timer);
1383
+ }
1384
+ }
1385
+ async function fetchLatestNpmVersion(fetchFn, pkg = MCP_NPM_PACKAGE, timeoutMs = MCP_SELF_UPDATE_TIMEOUT_MS) {
1386
+ const controller = new AbortController();
1387
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
1388
+ try {
1389
+ const response = await fetchFn(npmLatestUrl(pkg), {
1390
+ signal: controller.signal,
1391
+ headers: { Accept: "application/json" }
1392
+ });
1393
+ if (!response.ok) return null;
1394
+ const json = await response.json();
1395
+ return typeof json.version === "string" ? json.version : null;
1396
+ } catch {
1397
+ return null;
1398
+ } finally {
1399
+ clearTimeout(timer);
1400
+ }
1401
+ }
1402
+ function shouldSkipMcpSelfUpdate(io = {}) {
1403
+ const env = io.env ?? process.env;
1404
+ if (env[MCP_SKIP_SELF_UPDATE_ENV] === "1") return true;
1405
+ const packageRoot = packageRootFromModuleUrl(io.moduleUrl ?? import.meta.url);
1406
+ const monorepo = io.monorepo ?? isLocalMonorepoCheckout(packageRoot);
1407
+ return monorepo;
1408
+ }
1409
+ function buildNpxSelfUpdateArgs(latest, argv) {
1410
+ const command = process.platform === "win32" ? "npx.cmd" : "npx";
1411
+ return {
1412
+ command,
1413
+ args: ["-y", "--prefer-online", `${MCP_NPM_PACKAGE}@${latest}`, ...argv]
1414
+ };
1415
+ }
1416
+ function waitForSpawnedChild(child) {
1417
+ return new Promise((resolve) => {
1418
+ child.on("error", () => resolve(1));
1419
+ child.on("close", (code) => resolve(code ?? 1));
1420
+ });
1421
+ }
1422
+ async function maybeReexecLatestMcp(io = {}) {
1423
+ if (shouldSkipMcpSelfUpdate(io)) return false;
1424
+ const packageRoot = packageRootFromModuleUrl(io.moduleUrl ?? import.meta.url);
1425
+ const installed = io.installedVersion !== void 0 ? io.installedVersion : readInstalledMcpVersion(packageRoot);
1426
+ if (!installed) return false;
1427
+ const fetchFn = io.fetchFn ?? fetch;
1428
+ const origin = (io.dashboardBaseUrl || io.env?.MG_DASHBOARD_BASE_URL || MG_DASHBOARD_ORIGIN_DEFAULT).replace(/\/$/, "");
1429
+ const dashboardVersion = await fetchDashboardRequiredVersion(fetchFn, origin);
1430
+ const npmVersion = dashboardVersion ? null : await fetchLatestNpmVersion(fetchFn);
1431
+ const latest = dashboardVersion ?? npmVersion;
1432
+ if (!latest || !isNpmVersionBehind(installed, latest)) return false;
1433
+ const argv = io.argv ?? process.argv.slice(2);
1434
+ const { command, args: args2 } = buildNpxSelfUpdateArgs(latest, argv);
1435
+ const log = io.log ?? ((message) => console.error(message));
1436
+ log(
1437
+ `[mcp] ${MCP_NPM_PACKAGE}@${installed} is behind npm ${latest}; restarting via npx --prefer-online`
1438
+ );
1439
+ const spawnFn = io.spawnFn ?? spawn;
1440
+ let spawnFailed = false;
1441
+ const child = spawnFn(command, args2, {
1442
+ stdio: "inherit",
1443
+ env: {
1444
+ ...process.env,
1445
+ [MCP_SKIP_SELF_UPDATE_ENV]: "1"
1446
+ },
1447
+ shell: process.platform === "win32",
1448
+ windowsHide: true
1449
+ });
1450
+ child.on?.("error", () => {
1451
+ spawnFailed = true;
1452
+ });
1453
+ const wait = io.waitForChild ?? waitForSpawnedChild;
1454
+ const code = await wait(child);
1455
+ if (spawnFailed) {
1456
+ log(
1457
+ `[mcp] self-update spawn failed; continuing on ${MCP_NPM_PACKAGE}@${installed}`
1458
+ );
1459
+ return false;
1460
+ }
1461
+ if (code !== 0) process.exitCode = code;
1462
+ return true;
1463
+ }
1318
1464
  var ALGORITHM = "aes-256-gcm";
1319
1465
  var IV_LENGTH = 16;
1320
1466
  var AUTH_TAG_LENGTH = 16;
@@ -13630,7 +13776,7 @@ var TOOLS = [
13630
13776
  // ----- Trigger.dev -----
13631
13777
  ...TRIGGER_TOOLS
13632
13778
  ];
13633
- var MCP_VERSION = "7.4.14";
13779
+ var MCP_VERSION = readInstalledMcpVersion() ?? "0.0.0";
13634
13780
  async function handleListTools() {
13635
13781
  if (!authContext) return { tools: TOOLS };
13636
13782
  const allowedTools = authContext.allowedTools;
@@ -17042,7 +17188,7 @@ ${lines.join("\n")}`
17042
17188
  };
17043
17189
  }
17044
17190
  const header = "TYPE NAME VALUE TTL";
17045
- const sep = "-".repeat(90);
17191
+ const sep2 = "-".repeat(90);
17046
17192
  const lines = records.map(
17047
17193
  (r) => `${r.type.padEnd(10)}${r.name.padEnd(31)}${r.value.substring(0, 40).padEnd(41)}${r.ttl}`
17048
17194
  );
@@ -17053,7 +17199,7 @@ ${lines.join("\n")}`
17053
17199
  text: `DNS records for ${domain} (${records.length}):
17054
17200
 
17055
17201
  ${header}
17056
- ${sep}
17202
+ ${sep2}
17057
17203
  ${lines.join("\n")}`
17058
17204
  }
17059
17205
  ]
@@ -17395,6 +17541,11 @@ function createMcpServer() {
17395
17541
  var server = createMcpServer();
17396
17542
  async function main() {
17397
17543
  console.error("Starting MG Dashboard MCP Server...");
17544
+ const replaced = await maybeReexecLatestMcp({
17545
+ argv: process.argv.slice(2),
17546
+ dashboardBaseUrl
17547
+ });
17548
+ if (replaced) return;
17398
17549
  const apiAuthContext = await validateApiKey(apiKey);
17399
17550
  if (!apiAuthContext) {
17400
17551
  console.error("API key validation failed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mgsoftwarebv/mg-dashboard-mcp",
3
- "version": "7.4.17",
3
+ "version": "7.4.18",
4
4
  "description": "MCP Server for MG Dashboard - SSH, SFTP, Docker, domains, DNS, and environment config tools for Cursor",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",