@mgsoftwarebv/mg-dashboard-mcp 7.4.16 → 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.
- package/dist/index.js +280 -150
- 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
|
|
4
|
-
import {
|
|
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
|
|
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
|
-
${
|
|
849
|
+
${sep2}
|
|
849
850
|
${lines.join("\n")}` }] };
|
|
850
851
|
}
|
|
851
852
|
// -----------------------------------------------------------------
|
|
@@ -1010,9 +1011,9 @@ ${raw2.substring(0, 500)}` }] };
|
|
|
1010
1011
|
return { content: [{ type: "text", text: `No environment variables for ${project}/${env}.` }] };
|
|
1011
1012
|
}
|
|
1012
1013
|
const lines = vars.map((v) => `${v.isSecret ? "[secret]" : " "} ${v.name}`).sort();
|
|
1013
|
-
const
|
|
1014
|
+
const text21 = `Env vars for ${project}/${env} (${vars.length}) \u2014 values hidden, use action="get" with a key:
|
|
1014
1015
|
` + "-".repeat(50) + "\n" + lines.join("\n");
|
|
1015
|
-
return { content: [{ type: "text", text:
|
|
1016
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1016
1017
|
}
|
|
1017
1018
|
if (action === "get") {
|
|
1018
1019
|
const key2 = String(args2.key ?? "");
|
|
@@ -1099,9 +1100,9 @@ async function fetchAndFormatRun(conn, proxy, sshExec2, instance, runId) {
|
|
|
1099
1100
|
return { content: [{ type: "text", text: `Invalid API response:
|
|
1100
1101
|
${rawJson.substring(0, 500)}` }] };
|
|
1101
1102
|
}
|
|
1102
|
-
let
|
|
1103
|
-
if (logs)
|
|
1104
|
-
return { content: [{ type: "text", text:
|
|
1103
|
+
let text21 = formatRunDetail(run);
|
|
1104
|
+
if (logs) text21 += "\n\n--- Logs ---\n" + logs;
|
|
1105
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1105
1106
|
}
|
|
1106
1107
|
async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSeconds) {
|
|
1107
1108
|
const pollInterval = 3e3;
|
|
@@ -1123,10 +1124,10 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
|
|
|
1123
1124
|
continue;
|
|
1124
1125
|
}
|
|
1125
1126
|
if (TERMINAL_STATUSES.has(run.status)) {
|
|
1126
|
-
let
|
|
1127
|
+
let text21 = formatRunDetail(run);
|
|
1127
1128
|
const logs = await fetchRunLogs(runId, conn, proxy, sshExec2);
|
|
1128
|
-
if (logs)
|
|
1129
|
-
return { content: [{ type: "text", text:
|
|
1129
|
+
if (logs) text21 += "\n\n--- Logs ---\n" + logs;
|
|
1130
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
1130
1131
|
}
|
|
1131
1132
|
}
|
|
1132
1133
|
return {
|
|
@@ -1138,32 +1139,65 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
|
|
|
1138
1139
|
}
|
|
1139
1140
|
|
|
1140
1141
|
// src/github-code-access-tools.ts
|
|
1142
|
+
var FILE_PROPERTIES = {
|
|
1143
|
+
repository: {
|
|
1144
|
+
type: "string",
|
|
1145
|
+
description: "owner/repo, e.g. MGSoftwareBV/tickets-v2. Org must be allowlisted (CODE_BATTLE_GITHUB_ORGS)."
|
|
1146
|
+
},
|
|
1147
|
+
path: {
|
|
1148
|
+
type: "string",
|
|
1149
|
+
description: "File path inside the repo (not a directory)."
|
|
1150
|
+
},
|
|
1151
|
+
ref: {
|
|
1152
|
+
type: "string",
|
|
1153
|
+
description: "Optional commit sha, branch, or tag. Defaults to the repository default branch."
|
|
1154
|
+
}
|
|
1155
|
+
};
|
|
1156
|
+
var FILE_DESCRIPTION = "Read ONE source file from an ingested GitHub org/repo (CODE_BATTLE_GITHUB_ORGS, default MGSoftwareBV). Path + optional ref (defaults to the repo default branch). Returns metadata + text content (secrets redacted). Credential paths (.env, keys) are denied. Binary files return { binary: true } with no payload. Use list-dir to browse a folder first. Compact diffs stay on get_mg_dashboard_diff.";
|
|
1141
1157
|
var GITHUB_CODE_ACCESS_TOOLS = [
|
|
1142
1158
|
{
|
|
1143
|
-
name: "
|
|
1144
|
-
description:
|
|
1159
|
+
name: "read-file",
|
|
1160
|
+
description: FILE_DESCRIPTION,
|
|
1161
|
+
inputSchema: {
|
|
1162
|
+
type: "object",
|
|
1163
|
+
properties: FILE_PROPERTIES,
|
|
1164
|
+
required: ["repository", "path"]
|
|
1165
|
+
}
|
|
1166
|
+
},
|
|
1167
|
+
{
|
|
1168
|
+
name: "list-dir",
|
|
1169
|
+
description: "List ONE directory on an ingested GitHub org/repo (CODE_BATTLE_GITHUB_ORGS). Path is optional (empty or '/' = repo root). Ref is optional (defaults to the repo default branch). Returns name/path/type/size/sha per entry. Credential files are omitted. No file contents, no clone.",
|
|
1145
1170
|
inputSchema: {
|
|
1146
1171
|
type: "object",
|
|
1147
1172
|
properties: {
|
|
1148
1173
|
repository: {
|
|
1149
1174
|
type: "string",
|
|
1150
|
-
description: "owner/repo, e.g. MGSoftwareBV/
|
|
1175
|
+
description: "owner/repo, e.g. MGSoftwareBV/tickets-v2. Org must be allowlisted."
|
|
1151
1176
|
},
|
|
1152
|
-
|
|
1177
|
+
path: {
|
|
1153
1178
|
type: "string",
|
|
1154
|
-
description: "
|
|
1179
|
+
description: "Directory path (e.g. wbso-planning). Empty string or '/' for the repository root."
|
|
1155
1180
|
},
|
|
1156
|
-
|
|
1181
|
+
ref: {
|
|
1157
1182
|
type: "string",
|
|
1158
|
-
description: "
|
|
1183
|
+
description: "Optional commit sha, branch, or tag. Defaults to the repository default branch."
|
|
1159
1184
|
}
|
|
1160
1185
|
},
|
|
1161
|
-
required: ["repository"
|
|
1186
|
+
required: ["repository"]
|
|
1187
|
+
}
|
|
1188
|
+
},
|
|
1189
|
+
{
|
|
1190
|
+
name: "get_mg_dashboard_file",
|
|
1191
|
+
description: `${FILE_DESCRIPTION} Alias of read-file.`,
|
|
1192
|
+
inputSchema: {
|
|
1193
|
+
type: "object",
|
|
1194
|
+
properties: FILE_PROPERTIES,
|
|
1195
|
+
required: ["repository", "path"]
|
|
1162
1196
|
}
|
|
1163
1197
|
},
|
|
1164
1198
|
{
|
|
1165
1199
|
name: "get_mg_dashboard_diff",
|
|
1166
|
-
description: "Fetch a COMPACT unified diff for one commit sha XOR one pull request number, same org allowlist as
|
|
1200
|
+
description: "Fetch a COMPACT unified diff for one commit sha XOR one pull request number, same org allowlist as read-file. Returns per-file path/status/+/- and a truncated patch (secrets redacted). Binary files are omitted. Does not change get_mg_dashboard_commits (metadata-only by design).",
|
|
1167
1201
|
inputSchema: {
|
|
1168
1202
|
type: "object",
|
|
1169
1203
|
properties: {
|
|
@@ -1184,25 +1218,49 @@ var GITHUB_CODE_ACCESS_TOOLS = [
|
|
|
1184
1218
|
}
|
|
1185
1219
|
}
|
|
1186
1220
|
];
|
|
1221
|
+
function optionalString(value) {
|
|
1222
|
+
if (typeof value !== "string") return void 0;
|
|
1223
|
+
const trimmed = value.trim();
|
|
1224
|
+
return trimmed ? trimmed : void 0;
|
|
1225
|
+
}
|
|
1187
1226
|
async function handleGithubCodeAccessTool(name, args2, ctx) {
|
|
1188
|
-
if (name === "get_mg_dashboard_file") {
|
|
1189
|
-
const repository =
|
|
1190
|
-
const
|
|
1191
|
-
const
|
|
1192
|
-
if (!repository || !
|
|
1227
|
+
if (name === "get_mg_dashboard_file" || name === "read-file") {
|
|
1228
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1229
|
+
const path = optionalString(args2.path) ?? "";
|
|
1230
|
+
const ref = optionalString(args2.ref);
|
|
1231
|
+
if (!repository || !path) {
|
|
1193
1232
|
return {
|
|
1194
1233
|
content: [
|
|
1195
1234
|
{
|
|
1196
1235
|
type: "text",
|
|
1197
|
-
text: "Error: repository
|
|
1236
|
+
text: "Error: repository and path are required"
|
|
1198
1237
|
}
|
|
1199
1238
|
]
|
|
1200
1239
|
};
|
|
1201
1240
|
}
|
|
1202
|
-
return proxyJson(ctx, "/api/activity/file", {
|
|
1241
|
+
return proxyJson(ctx, "/api/activity/file", {
|
|
1242
|
+
repository,
|
|
1243
|
+
path,
|
|
1244
|
+
...ref ? { ref } : {}
|
|
1245
|
+
});
|
|
1246
|
+
}
|
|
1247
|
+
if (name === "list-dir") {
|
|
1248
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1249
|
+
if (!repository) {
|
|
1250
|
+
return {
|
|
1251
|
+
content: [{ type: "text", text: "Error: repository is required" }]
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
const path = typeof args2.path === "string" ? args2.path : "";
|
|
1255
|
+
const ref = optionalString(args2.ref);
|
|
1256
|
+
return proxyJson(ctx, "/api/activity/list-dir", {
|
|
1257
|
+
repository,
|
|
1258
|
+
path,
|
|
1259
|
+
...ref ? { ref } : {}
|
|
1260
|
+
});
|
|
1203
1261
|
}
|
|
1204
1262
|
if (name === "get_mg_dashboard_diff") {
|
|
1205
|
-
const repository =
|
|
1263
|
+
const repository = optionalString(args2.repository) ?? "";
|
|
1206
1264
|
if (!repository) {
|
|
1207
1265
|
return {
|
|
1208
1266
|
content: [
|
|
@@ -1210,7 +1268,7 @@ async function handleGithubCodeAccessTool(name, args2, ctx) {
|
|
|
1210
1268
|
]
|
|
1211
1269
|
};
|
|
1212
1270
|
}
|
|
1213
|
-
const sha =
|
|
1271
|
+
const sha = optionalString(args2.sha);
|
|
1214
1272
|
const pullNumber = typeof args2.pullNumber === "number" ? args2.pullNumber : void 0;
|
|
1215
1273
|
const hasSha = Boolean(sha);
|
|
1216
1274
|
const hasPr = pullNumber != null;
|
|
@@ -1258,6 +1316,151 @@ async function proxyJson(ctx, route, body) {
|
|
|
1258
1316
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
1259
1317
|
};
|
|
1260
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
|
+
}
|
|
1261
1464
|
var ALGORITHM = "aes-256-gcm";
|
|
1262
1465
|
var IV_LENGTH = 16;
|
|
1263
1466
|
var AUTH_TAG_LENGTH = 16;
|
|
@@ -3935,10 +4138,10 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
3935
4138
|
// }) as any;
|
|
3936
4139
|
// return merged;
|
|
3937
4140
|
// }
|
|
3938
|
-
catchall(
|
|
4141
|
+
catchall(index18) {
|
|
3939
4142
|
return new _ZodObject({
|
|
3940
4143
|
...this._def,
|
|
3941
|
-
catchall:
|
|
4144
|
+
catchall: index18
|
|
3942
4145
|
});
|
|
3943
4146
|
}
|
|
3944
4147
|
pick(mask) {
|
|
@@ -4256,9 +4459,9 @@ function mergeValues(a, b) {
|
|
|
4256
4459
|
return { valid: false };
|
|
4257
4460
|
}
|
|
4258
4461
|
const newArray = [];
|
|
4259
|
-
for (let
|
|
4260
|
-
const itemA = a[
|
|
4261
|
-
const itemB = b[
|
|
4462
|
+
for (let index18 = 0; index18 < a.length; index18++) {
|
|
4463
|
+
const itemA = a[index18];
|
|
4464
|
+
const itemB = b[index18];
|
|
4262
4465
|
const sharedValue = mergeValues(itemA, itemB);
|
|
4263
4466
|
if (!sharedValue.valid) {
|
|
4264
4467
|
return { valid: false };
|
|
@@ -4464,10 +4667,10 @@ var ZodMap = class extends ZodType {
|
|
|
4464
4667
|
}
|
|
4465
4668
|
const keyType = this._def.keyType;
|
|
4466
4669
|
const valueType = this._def.valueType;
|
|
4467
|
-
const pairs = [...ctx.data.entries()].map(([key, value],
|
|
4670
|
+
const pairs = [...ctx.data.entries()].map(([key, value], index18) => {
|
|
4468
4671
|
return {
|
|
4469
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [
|
|
4470
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [
|
|
4672
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index18, "key"])),
|
|
4673
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index18, "value"]))
|
|
4471
4674
|
};
|
|
4472
4675
|
});
|
|
4473
4676
|
if (ctx.common.async) {
|
|
@@ -5788,88 +5991,6 @@ pgTable(
|
|
|
5788
5991
|
index("idx_agent_memory_kind").on(table.kind)
|
|
5789
5992
|
]
|
|
5790
5993
|
);
|
|
5791
|
-
var agentWorldAgent = pgTable(
|
|
5792
|
-
"agent_world_agent",
|
|
5793
|
-
{
|
|
5794
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5795
|
-
name: text("name").notNull(),
|
|
5796
|
-
color: text("color").notNull(),
|
|
5797
|
-
/** Personality sliders 0–100: curiosity, sociability, diligence, calm. */
|
|
5798
|
-
personality: jsonb("personality").$type().notNull().default({
|
|
5799
|
-
curiosity: 50,
|
|
5800
|
-
sociability: 50,
|
|
5801
|
-
diligence: 50,
|
|
5802
|
-
calm: 50
|
|
5803
|
-
}),
|
|
5804
|
-
/** Needs 0–100: higher = more urgent. */
|
|
5805
|
-
needs: jsonb("needs").$type().notNull().default({ energy: 40, coffee: 30, focus: 35, social: 25 }),
|
|
5806
|
-
position: jsonb("position").$type().notNull().default({ x: 0, y: 0, z: 0 }),
|
|
5807
|
-
target: jsonb("target").$type(),
|
|
5808
|
-
activity: text("activity").notNull().default("idle"),
|
|
5809
|
-
waypoint: text("waypoint"),
|
|
5810
|
-
memories: jsonb("memories").$type().notNull().default([]),
|
|
5811
|
-
diaryCount: integer("diary_count").notNull().default(0),
|
|
5812
|
-
lastSay: text("last_say"),
|
|
5813
|
-
lastSayAt: timestamp("last_say_at", { withTimezone: true }),
|
|
5814
|
-
sortOrder: integer("sort_order").notNull().default(0),
|
|
5815
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5816
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5817
|
-
},
|
|
5818
|
-
(table) => [index("idx_agent_world_agent_sort").on(table.sortOrder)]
|
|
5819
|
-
);
|
|
5820
|
-
pgTable(
|
|
5821
|
-
"agent_world_event",
|
|
5822
|
-
{
|
|
5823
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5824
|
-
/** say | diary | think | god | activity | memo | system */
|
|
5825
|
-
type: text("type").notNull(),
|
|
5826
|
-
agentId: uuid("agent_id").references(() => agentWorldAgent.id, {
|
|
5827
|
-
onDelete: "set null"
|
|
5828
|
-
}),
|
|
5829
|
-
message: text("message").notNull(),
|
|
5830
|
-
meta: jsonb("meta").$type().notNull().default({}),
|
|
5831
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5832
|
-
},
|
|
5833
|
-
(table) => [
|
|
5834
|
-
index("idx_agent_world_event_created").on(table.createdAt),
|
|
5835
|
-
index("idx_agent_world_event_type").on(table.type),
|
|
5836
|
-
index("idx_agent_world_event_agent").on(table.agentId),
|
|
5837
|
-
// Diary / per-agent feed: WHERE agent_id ORDER BY created_at DESC LIMIT N
|
|
5838
|
-
index("idx_agent_world_event_agent_created").on(
|
|
5839
|
-
table.agentId,
|
|
5840
|
-
table.createdAt
|
|
5841
|
-
)
|
|
5842
|
-
]
|
|
5843
|
-
);
|
|
5844
|
-
pgTable(
|
|
5845
|
-
"agent_world_memo",
|
|
5846
|
-
{
|
|
5847
|
-
id: uuid("id").primaryKey().defaultRandom(),
|
|
5848
|
-
agentId: uuid("agent_id").references(() => agentWorldAgent.id, {
|
|
5849
|
-
onDelete: "set null"
|
|
5850
|
-
}),
|
|
5851
|
-
title: text("title").notNull(),
|
|
5852
|
-
content: text("content").notNull(),
|
|
5853
|
-
location: text("location").notNull().default("whiteboard"),
|
|
5854
|
-
reads: integer("reads").notNull().default(0),
|
|
5855
|
-
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5856
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5857
|
-
},
|
|
5858
|
-
(table) => [
|
|
5859
|
-
index("idx_agent_world_memo_created").on(table.createdAt),
|
|
5860
|
-
index("idx_agent_world_memo_location").on(table.location)
|
|
5861
|
-
]
|
|
5862
|
-
);
|
|
5863
|
-
pgTable("agent_world_state", {
|
|
5864
|
-
id: text("id").primaryKey().default("world"),
|
|
5865
|
-
tick: integer("tick").notNull().default(0),
|
|
5866
|
-
/** Simulated minutes since day start (0–1439 wraps). */
|
|
5867
|
-
simMinutes: integer("sim_minutes").notNull().default(540),
|
|
5868
|
-
paused: boolean("paused").notNull().default(false),
|
|
5869
|
-
lastThinkAt: timestamp("last_think_at", { withTimezone: true }),
|
|
5870
|
-
lastThinkAgentId: uuid("last_think_agent_id"),
|
|
5871
|
-
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
5872
|
-
});
|
|
5873
5994
|
var contentSourceType = pgEnum("content_source_type", [
|
|
5874
5995
|
"own_site",
|
|
5875
5996
|
"client_site",
|
|
@@ -9538,7 +9659,7 @@ function getEncryptionKey() {
|
|
|
9538
9659
|
throw new Error("ENCRYPTION_KEY must be a 64-character hex string");
|
|
9539
9660
|
return buf;
|
|
9540
9661
|
}
|
|
9541
|
-
function encrypt(
|
|
9662
|
+
function encrypt(text21) {
|
|
9542
9663
|
const key = getEncryptionKey();
|
|
9543
9664
|
const iv = randomBytes(ENC_IV_LENGTH);
|
|
9544
9665
|
const cipher = createCipheriv(
|
|
@@ -9546,7 +9667,7 @@ function encrypt(text22) {
|
|
|
9546
9667
|
new Uint8Array(key),
|
|
9547
9668
|
new Uint8Array(iv)
|
|
9548
9669
|
);
|
|
9549
|
-
let encrypted = cipher.update(
|
|
9670
|
+
let encrypted = cipher.update(text21, "utf8", "hex");
|
|
9550
9671
|
encrypted += cipher.final("hex");
|
|
9551
9672
|
const authTag = cipher.getAuthTag();
|
|
9552
9673
|
return Buffer.concat([
|
|
@@ -10266,10 +10387,10 @@ async function r2GetObjectRange(bucket, key, range) {
|
|
|
10266
10387
|
const body = result.Body;
|
|
10267
10388
|
if (!body?.transformToString)
|
|
10268
10389
|
throw new Error("R2 returned no readable body");
|
|
10269
|
-
const
|
|
10390
|
+
const text21 = await body.transformToString();
|
|
10270
10391
|
const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;
|
|
10271
10392
|
return `${header}
|
|
10272
|
-
${
|
|
10393
|
+
${text21}`;
|
|
10273
10394
|
} catch (e) {
|
|
10274
10395
|
throw r2WrapError(bucket, key, e);
|
|
10275
10396
|
}
|
|
@@ -10632,15 +10753,15 @@ async function sftpRead(opts, filePath, proxy, options) {
|
|
|
10632
10753
|
clearTimeout(timer);
|
|
10633
10754
|
cleanup?.();
|
|
10634
10755
|
cleanup = void 0;
|
|
10635
|
-
const
|
|
10756
|
+
const text21 = Buffer.concat(
|
|
10636
10757
|
chunks.map((ch) => new Uint8Array(ch))
|
|
10637
10758
|
).toString("utf-8");
|
|
10638
10759
|
if (!isWholeFileRequest) {
|
|
10639
10760
|
const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;
|
|
10640
10761
|
resolve(`${header}
|
|
10641
|
-
${
|
|
10762
|
+
${text21}`);
|
|
10642
10763
|
} else {
|
|
10643
|
-
resolve(
|
|
10764
|
+
resolve(text21);
|
|
10644
10765
|
}
|
|
10645
10766
|
});
|
|
10646
10767
|
rs.on("error", (e) => {
|
|
@@ -10675,6 +10796,8 @@ var RAW_JSON_TOOLS = /* @__PURE__ */ new Set([
|
|
|
10675
10796
|
"get_mg_dashboard_commits",
|
|
10676
10797
|
"get_mg_dashboard_file",
|
|
10677
10798
|
"get_mg_dashboard_diff",
|
|
10799
|
+
"read-file",
|
|
10800
|
+
"list-dir",
|
|
10678
10801
|
"extract_article",
|
|
10679
10802
|
// Content family (2026-DASMG-040/041/042) — compact JSON consumed verbatim.
|
|
10680
10803
|
// Consolidated action-based tools (the Cursor surface); each proxies to the
|
|
@@ -10793,11 +10916,11 @@ function getKnownContainers(serverId, maxAgeMs = 5 * 6e4) {
|
|
|
10793
10916
|
if (Date.now() - e.capturedAt > maxAgeMs) return void 0;
|
|
10794
10917
|
return e.names;
|
|
10795
10918
|
}
|
|
10796
|
-
function truncateForLLM(
|
|
10797
|
-
const totalBytes = Buffer.byteLength(
|
|
10919
|
+
function truncateForLLM(text21, maxBytes) {
|
|
10920
|
+
const totalBytes = Buffer.byteLength(text21, "utf8");
|
|
10798
10921
|
if (totalBytes <= maxBytes)
|
|
10799
|
-
return { text:
|
|
10800
|
-
const buf = Buffer.from(
|
|
10922
|
+
return { text: text21, truncated: false, totalBytes, shownBytes: totalBytes };
|
|
10923
|
+
const buf = Buffer.from(text21, "utf8");
|
|
10801
10924
|
let cut = maxBytes;
|
|
10802
10925
|
while (cut > 0 && (buf[cut] & 192) === 128) cut--;
|
|
10803
10926
|
const head = buf.subarray(0, cut).toString("utf8");
|
|
@@ -10828,10 +10951,10 @@ function postprocessResult(result, meta) {
|
|
|
10828
10951
|
if (!result.content?.length) return result;
|
|
10829
10952
|
if (RAW_JSON_TOOLS.has(meta.toolName)) return result;
|
|
10830
10953
|
const block = result.content[0];
|
|
10831
|
-
let
|
|
10832
|
-
const trunc = truncateForLLM(
|
|
10954
|
+
let text21 = String(block.text ?? "");
|
|
10955
|
+
const trunc = truncateForLLM(text21, RESPONSE_MAX_BYTES);
|
|
10833
10956
|
if (trunc.truncated) {
|
|
10834
|
-
|
|
10957
|
+
text21 = trunc.text + "\n\n... " + buildTruncationHint(
|
|
10835
10958
|
meta.toolName,
|
|
10836
10959
|
meta.args,
|
|
10837
10960
|
trunc.totalBytes,
|
|
@@ -10845,11 +10968,11 @@ function postprocessResult(result, meta) {
|
|
|
10845
10968
|
const parts = [`took ${tookStr}`, sizeStr];
|
|
10846
10969
|
if (meta.serverIdLabel) parts.push(`server: ${meta.serverIdLabel}`);
|
|
10847
10970
|
if (meta.cached) parts.push("cached");
|
|
10848
|
-
|
|
10971
|
+
text21 = `${text21}
|
|
10849
10972
|
|
|
10850
10973
|
[${parts.join(", ")}]`;
|
|
10851
10974
|
}
|
|
10852
|
-
return { ...result, content: [{ ...block, text:
|
|
10975
|
+
return { ...result, content: [{ ...block, text: text21 }] };
|
|
10853
10976
|
}
|
|
10854
10977
|
function buildPipelineScript(commands, shell, marker, stopOnError) {
|
|
10855
10978
|
if (shell === "powershell") {
|
|
@@ -13653,7 +13776,7 @@ var TOOLS = [
|
|
|
13653
13776
|
// ----- Trigger.dev -----
|
|
13654
13777
|
...TRIGGER_TOOLS
|
|
13655
13778
|
];
|
|
13656
|
-
var MCP_VERSION = "
|
|
13779
|
+
var MCP_VERSION = readInstalledMcpVersion() ?? "0.0.0";
|
|
13657
13780
|
async function handleListTools() {
|
|
13658
13781
|
if (!authContext) return { tools: TOOLS };
|
|
13659
13782
|
const allowedTools = authContext.allowedTools;
|
|
@@ -13796,6 +13919,8 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13796
13919
|
}
|
|
13797
13920
|
case "get_mg_dashboard_file":
|
|
13798
13921
|
case "get_mg_dashboard_diff":
|
|
13922
|
+
case "read-file":
|
|
13923
|
+
case "list-dir":
|
|
13799
13924
|
return handleGithubCodeAccessTool(name, a, {
|
|
13800
13925
|
dashboardBaseUrl,
|
|
13801
13926
|
apiKey: apiKey ?? ""
|
|
@@ -13950,7 +14075,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13950
14075
|
]
|
|
13951
14076
|
};
|
|
13952
14077
|
}
|
|
13953
|
-
const lines = data.hits.map((hit,
|
|
14078
|
+
const lines = data.hits.map((hit, index18) => {
|
|
13954
14079
|
const when = hit.lastMessageAt ? new Date(hit.lastMessageAt).toISOString().slice(0, 10) : "unknown date";
|
|
13955
14080
|
const repo = hit.repo ?? "unknown repo";
|
|
13956
14081
|
const sim = hit.similarity !== null ? ` \xB7 ${(hit.similarity * 100).toFixed(0)}% match` : "";
|
|
@@ -13960,7 +14085,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
13960
14085
|
...Array.isArray(hit.tech) ? hit.tech.slice(0, 4) : []
|
|
13961
14086
|
].filter(Boolean);
|
|
13962
14087
|
const tags = facets.length > 0 ? ` \xB7 ${facets.join(", ")}` : "";
|
|
13963
|
-
return `${
|
|
14088
|
+
return `${index18 + 1}. [${repo} \xB7 ${when}${sim}${tags}] ${hit.title}
|
|
13964
14089
|
id: ${hit.id}
|
|
13965
14090
|
${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 500)}`;
|
|
13966
14091
|
});
|
|
@@ -14167,12 +14292,12 @@ Searchable via search-team-memory once indexing completes (usually immediate).`
|
|
|
14167
14292
|
]
|
|
14168
14293
|
};
|
|
14169
14294
|
}
|
|
14170
|
-
const lines = data.hits.map((hit,
|
|
14295
|
+
const lines = data.hits.map((hit, index18) => {
|
|
14171
14296
|
const sim = hit.similarity !== null ? ` \xB7 ${Math.round(hit.similarity * 100)}% match` : "";
|
|
14172
14297
|
const tags = hit.tags.length ? ` \xB7 ${hit.tags.slice(0, 5).join(", ")}` : "";
|
|
14173
14298
|
const sources = hit.sources.length ? `
|
|
14174
14299
|
sources: ${hit.sources.slice(0, 6).map((s) => `${s.type}:${s.ref}`).join(", ")}` : "";
|
|
14175
|
-
return `${
|
|
14300
|
+
return `${index18 + 1}. [${hit.status} \xB7 updated ${hit.pageUpdatedOn ?? "unknown"}${sim}${tags}] ${hit.title}
|
|
14176
14301
|
slug: ${hit.slug}${sources}
|
|
14177
14302
|
${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 400)}`;
|
|
14178
14303
|
});
|
|
@@ -14350,7 +14475,7 @@ Archived sources (${archiveOnly.length}):
|
|
|
14350
14475
|
let formatItems2 = function(items) {
|
|
14351
14476
|
if (items.length === 0) return "(none)";
|
|
14352
14477
|
return items.map(
|
|
14353
|
-
(item,
|
|
14478
|
+
(item, index18) => `${index18 + 1}. [${item.status} \xB7 ${item.folder} \xB7 updated ${item.updated ?? "unknown"}] ${item.title}
|
|
14354
14479
|
slug: ${item.slug}`
|
|
14355
14480
|
).join("\n");
|
|
14356
14481
|
};
|
|
@@ -14377,9 +14502,9 @@ Archived sources (${archiveOnly.length}):
|
|
|
14377
14502
|
}
|
|
14378
14503
|
const data = await res.json();
|
|
14379
14504
|
const countLine = Object.entries(data.counts).sort(([left], [right]) => left.localeCompare(right)).map(([status, count]) => `${status} ${count}`).join(" \xB7 ");
|
|
14380
|
-
const flagLines = data.flags.length === 0 ? "(none)" : data.flags.map((flag,
|
|
14505
|
+
const flagLines = data.flags.length === 0 ? "(none)" : data.flags.map((flag, index18) => {
|
|
14381
14506
|
const detail = flag.detail.replace(/\s+/g, " ").slice(0, 240);
|
|
14382
|
-
return `${
|
|
14507
|
+
return `${index18 + 1}. [${flag.kind} \xB7 ${flag.folder}${flag.status ? ` \xB7 page ${flag.status}` : ""}] ${flag.title}
|
|
14383
14508
|
slug: ${flag.slug}
|
|
14384
14509
|
${detail}`;
|
|
14385
14510
|
}).join("\n");
|
|
@@ -15545,8 +15670,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
15545
15670
|
};
|
|
15546
15671
|
const filtered = sortRows(applyFilter(only.rows));
|
|
15547
15672
|
if (format === "json") {
|
|
15548
|
-
const
|
|
15549
|
-
return { content: [{ type: "text", text:
|
|
15673
|
+
const text22 = filtered.map((c) => JSON.stringify(c)).join("\n") || "(no containers)";
|
|
15674
|
+
return { content: [{ type: "text", text: text22 }] };
|
|
15550
15675
|
}
|
|
15551
15676
|
if (groupByProject) {
|
|
15552
15677
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -15573,8 +15698,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
15573
15698
|
}
|
|
15574
15699
|
const header = `${"NAMES".padEnd(36)} ${"IMAGE".padEnd(40)} ${"STATUS".padEnd(24)} ${"HEALTH".padEnd(10)} ${"PORTS".padEnd(40)} PROJECT`;
|
|
15575
15700
|
const body = filtered.map((r) => `${fmtRow(r)} ${r.Project || ""}`);
|
|
15576
|
-
const
|
|
15577
|
-
return { content: [{ type: "text", text:
|
|
15701
|
+
const text21 = filtered.length === 0 ? "(no containers match)" : [header, ...body].join("\n");
|
|
15702
|
+
return { content: [{ type: "text", text: text21 }] };
|
|
15578
15703
|
}
|
|
15579
15704
|
if (format === "json") {
|
|
15580
15705
|
const lines = [];
|
|
@@ -17063,7 +17188,7 @@ ${lines.join("\n")}`
|
|
|
17063
17188
|
};
|
|
17064
17189
|
}
|
|
17065
17190
|
const header = "TYPE NAME VALUE TTL";
|
|
17066
|
-
const
|
|
17191
|
+
const sep2 = "-".repeat(90);
|
|
17067
17192
|
const lines = records.map(
|
|
17068
17193
|
(r) => `${r.type.padEnd(10)}${r.name.padEnd(31)}${r.value.substring(0, 40).padEnd(41)}${r.ttl}`
|
|
17069
17194
|
);
|
|
@@ -17074,7 +17199,7 @@ ${lines.join("\n")}`
|
|
|
17074
17199
|
text: `DNS records for ${domain} (${records.length}):
|
|
17075
17200
|
|
|
17076
17201
|
${header}
|
|
17077
|
-
${
|
|
17202
|
+
${sep2}
|
|
17078
17203
|
${lines.join("\n")}`
|
|
17079
17204
|
}
|
|
17080
17205
|
]
|
|
@@ -17416,6 +17541,11 @@ function createMcpServer() {
|
|
|
17416
17541
|
var server = createMcpServer();
|
|
17417
17542
|
async function main() {
|
|
17418
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;
|
|
17419
17549
|
const apiAuthContext = await validateApiKey(apiKey);
|
|
17420
17550
|
if (!apiAuthContext) {
|
|
17421
17551
|
console.error("API key validation failed");
|
package/package.json
CHANGED