@mgsoftwarebv/mg-dashboard-mcp 7.2.0 → 7.3.0
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 +328 -38
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -956,9 +956,9 @@ async function fetchAndFormatRun(conn, proxy, sshExec2, instance, runId) {
|
|
|
956
956
|
return { content: [{ type: "text", text: `Invalid API response:
|
|
957
957
|
${rawJson.substring(0, 500)}` }] };
|
|
958
958
|
}
|
|
959
|
-
let
|
|
960
|
-
if (logs)
|
|
961
|
-
return { content: [{ type: "text", text:
|
|
959
|
+
let text9 = formatRunDetail(run);
|
|
960
|
+
if (logs) text9 += "\n\n--- Logs ---\n" + logs;
|
|
961
|
+
return { content: [{ type: "text", text: text9 }] };
|
|
962
962
|
}
|
|
963
963
|
async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSeconds) {
|
|
964
964
|
const pollInterval = 3e3;
|
|
@@ -980,10 +980,10 @@ async function waitForCompletion(conn, proxy, sshExec2, instance, runId, waitSec
|
|
|
980
980
|
continue;
|
|
981
981
|
}
|
|
982
982
|
if (TERMINAL_STATUSES.has(run.status)) {
|
|
983
|
-
let
|
|
983
|
+
let text9 = formatRunDetail(run);
|
|
984
984
|
const logs = await fetchRunLogs(runId, conn, proxy, sshExec2);
|
|
985
|
-
if (logs)
|
|
986
|
-
return { content: [{ type: "text", text:
|
|
985
|
+
if (logs) text9 += "\n\n--- Logs ---\n" + logs;
|
|
986
|
+
return { content: [{ type: "text", text: text9 }] };
|
|
987
987
|
}
|
|
988
988
|
}
|
|
989
989
|
return {
|
|
@@ -3670,10 +3670,10 @@ var ZodObject = class _ZodObject extends ZodType {
|
|
|
3670
3670
|
// }) as any;
|
|
3671
3671
|
// return merged;
|
|
3672
3672
|
// }
|
|
3673
|
-
catchall(
|
|
3673
|
+
catchall(index7) {
|
|
3674
3674
|
return new _ZodObject({
|
|
3675
3675
|
...this._def,
|
|
3676
|
-
catchall:
|
|
3676
|
+
catchall: index7
|
|
3677
3677
|
});
|
|
3678
3678
|
}
|
|
3679
3679
|
pick(mask) {
|
|
@@ -3991,9 +3991,9 @@ function mergeValues(a, b) {
|
|
|
3991
3991
|
return { valid: false };
|
|
3992
3992
|
}
|
|
3993
3993
|
const newArray = [];
|
|
3994
|
-
for (let
|
|
3995
|
-
const itemA = a[
|
|
3996
|
-
const itemB = b[
|
|
3994
|
+
for (let index7 = 0; index7 < a.length; index7++) {
|
|
3995
|
+
const itemA = a[index7];
|
|
3996
|
+
const itemB = b[index7];
|
|
3997
3997
|
const sharedValue = mergeValues(itemA, itemB);
|
|
3998
3998
|
if (!sharedValue.valid) {
|
|
3999
3999
|
return { valid: false };
|
|
@@ -4199,10 +4199,10 @@ var ZodMap = class extends ZodType {
|
|
|
4199
4199
|
}
|
|
4200
4200
|
const keyType = this._def.keyType;
|
|
4201
4201
|
const valueType = this._def.valueType;
|
|
4202
|
-
const pairs = [...ctx.data.entries()].map(([key, value],
|
|
4202
|
+
const pairs = [...ctx.data.entries()].map(([key, value], index7) => {
|
|
4203
4203
|
return {
|
|
4204
|
-
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [
|
|
4205
|
-
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [
|
|
4204
|
+
key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index7, "key"])),
|
|
4205
|
+
value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index7, "value"]))
|
|
4206
4206
|
};
|
|
4207
4207
|
});
|
|
4208
4208
|
if (ctx.common.async) {
|
|
@@ -5363,6 +5363,14 @@ pgTable(
|
|
|
5363
5363
|
headings: jsonb("headings").$type().notNull().default([]),
|
|
5364
5364
|
internalLinks: jsonb("internal_links").$type().notNull().default([]),
|
|
5365
5365
|
metadata: jsonb("metadata").$type().notNull().default({}),
|
|
5366
|
+
/**
|
|
5367
|
+
* Run that captured this snapshot (managed site content sync, 2026-DASMG-042).
|
|
5368
|
+
* Soft pointer (no Drizzle .references() to avoid a schema import cycle); the
|
|
5369
|
+
* DB foreign key is declared in the migration.
|
|
5370
|
+
*/
|
|
5371
|
+
ingestionRunId: uuid("ingestion_run_id"),
|
|
5372
|
+
/** Source git commit / deploy id this snapshot was captured for, when known. */
|
|
5373
|
+
sourceCommit: text("source_commit"),
|
|
5366
5374
|
capturedAt: timestamp("captured_at", { withTimezone: true }).notNull().defaultNow(),
|
|
5367
5375
|
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
5368
5376
|
},
|
|
@@ -5376,6 +5384,7 @@ pgTable(
|
|
|
5376
5384
|
table.capturedAt.desc()
|
|
5377
5385
|
),
|
|
5378
5386
|
index("content_snapshots_text_hash_idx").on(table.textHash),
|
|
5387
|
+
index("content_snapshots_ingestion_run_idx").on(table.ingestionRunId),
|
|
5379
5388
|
uniqueIndex("content_snapshots_corpus_hash_uidx").on(
|
|
5380
5389
|
table.corpusItemId,
|
|
5381
5390
|
table.textHash
|
|
@@ -5961,6 +5970,103 @@ pgTable(
|
|
|
5961
5970
|
index("github_webhook_secret_owner_idx").on(table.owner)
|
|
5962
5971
|
]
|
|
5963
5972
|
);
|
|
5973
|
+
var managedSiteSyncMode = pgEnum("managed_site_sync_mode", [
|
|
5974
|
+
"sitemap",
|
|
5975
|
+
"git",
|
|
5976
|
+
"hybrid",
|
|
5977
|
+
"manual"
|
|
5978
|
+
]);
|
|
5979
|
+
var contentIngestionTrigger = pgEnum("content_ingestion_trigger", [
|
|
5980
|
+
"manual",
|
|
5981
|
+
"git_push",
|
|
5982
|
+
"deploy",
|
|
5983
|
+
"cron",
|
|
5984
|
+
"sitemap"
|
|
5985
|
+
]);
|
|
5986
|
+
var contentIngestionStatus = pgEnum("content_ingestion_status", [
|
|
5987
|
+
"queued",
|
|
5988
|
+
"running",
|
|
5989
|
+
"completed",
|
|
5990
|
+
"partial",
|
|
5991
|
+
"failed"
|
|
5992
|
+
]);
|
|
5993
|
+
var managedSites = pgTable(
|
|
5994
|
+
"managed_sites",
|
|
5995
|
+
{
|
|
5996
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
5997
|
+
projectKey: text("project_key").notNull(),
|
|
5998
|
+
siteKey: text("site_key"),
|
|
5999
|
+
name: text("name"),
|
|
6000
|
+
domain: text("domain").notNull(),
|
|
6001
|
+
/** GitHub repo (owner/repo) that publishes this site, when git-driven. */
|
|
6002
|
+
repo: text("repo"),
|
|
6003
|
+
/** Branch whose pushes trigger a sync; null = any branch. */
|
|
6004
|
+
branch: text("branch"),
|
|
6005
|
+
sitemapUrl: text("sitemap_url"),
|
|
6006
|
+
sourceType: contentSourceType("source_type").notNull().default("own_site"),
|
|
6007
|
+
enabled: boolean("enabled").notNull().default(true),
|
|
6008
|
+
syncMode: managedSiteSyncMode("sync_mode").notNull().default("sitemap"),
|
|
6009
|
+
/** Git path -> URL mapping rules used to turn changed files into URLs. */
|
|
6010
|
+
pathUrlMap: jsonb("path_url_map").$type().notNull().default([]),
|
|
6011
|
+
/** Per-run URL cap; null = use the engine default. */
|
|
6012
|
+
maxUrlsPerRun: integer("max_urls_per_run"),
|
|
6013
|
+
/** When true, changed pages are flagged for an MG SEO CLI follow-up (soft handoff). */
|
|
6014
|
+
exportToSeoCli: boolean("export_to_seo_cli").notNull().default(false),
|
|
6015
|
+
lastSyncAt: timestamp("last_sync_at", { withTimezone: true }),
|
|
6016
|
+
/** Soft pointer to the most recent run (no FK to avoid a cycle). */
|
|
6017
|
+
lastRunId: uuid("last_run_id"),
|
|
6018
|
+
metadata: jsonb("metadata").$type().notNull().default({}),
|
|
6019
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
6020
|
+
updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow()
|
|
6021
|
+
},
|
|
6022
|
+
(table) => [
|
|
6023
|
+
uniqueIndex("managed_sites_project_domain_uidx").on(
|
|
6024
|
+
table.projectKey,
|
|
6025
|
+
table.domain
|
|
6026
|
+
),
|
|
6027
|
+
index("managed_sites_repo_idx").on(table.repo),
|
|
6028
|
+
index("managed_sites_enabled_idx").on(table.enabled),
|
|
6029
|
+
index("managed_sites_project_idx").on(table.projectKey)
|
|
6030
|
+
]
|
|
6031
|
+
);
|
|
6032
|
+
pgTable(
|
|
6033
|
+
"content_ingestion_runs",
|
|
6034
|
+
{
|
|
6035
|
+
id: uuid("id").primaryKey().defaultRandom(),
|
|
6036
|
+
siteId: uuid("site_id").notNull().references(() => managedSites.id, { onDelete: "cascade" }),
|
|
6037
|
+
projectKey: text("project_key"),
|
|
6038
|
+
triggerType: contentIngestionTrigger("trigger_type").notNull(),
|
|
6039
|
+
status: contentIngestionStatus("status").notNull().default("queued"),
|
|
6040
|
+
/** Trigger.dev run id handling this ingestion, when dispatched. */
|
|
6041
|
+
triggerRunId: text("trigger_run_id"),
|
|
6042
|
+
sourceCommit: text("source_commit"),
|
|
6043
|
+
sourceRef: text("source_ref"),
|
|
6044
|
+
changedUrls: jsonb("changed_urls").$type().notNull().default([]),
|
|
6045
|
+
skippedUrls: jsonb("skipped_urls").$type().notNull().default([]),
|
|
6046
|
+
failedUrls: jsonb("failed_urls").$type().notNull().default([]),
|
|
6047
|
+
limitations: jsonb("limitations").$type().notNull().default([]),
|
|
6048
|
+
/** Corpus item ids touched by this run (for QC / MG SEO CLI handoff). */
|
|
6049
|
+
corpusItemIds: jsonb("corpus_item_ids").$type().notNull().default([]),
|
|
6050
|
+
changedCount: integer("changed_count").notNull().default(0),
|
|
6051
|
+
skippedCount: integer("skipped_count").notNull().default(0),
|
|
6052
|
+
failedCount: integer("failed_count").notNull().default(0),
|
|
6053
|
+
/** Set when changed pages were flagged for an MG SEO CLI follow-up. */
|
|
6054
|
+
qcMarked: boolean("qc_marked").notNull().default(false),
|
|
6055
|
+
error: text("error"),
|
|
6056
|
+
startedAt: timestamp("started_at", { withTimezone: true }),
|
|
6057
|
+
finishedAt: timestamp("finished_at", { withTimezone: true }),
|
|
6058
|
+
createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow()
|
|
6059
|
+
},
|
|
6060
|
+
(table) => [
|
|
6061
|
+
index("content_ingestion_runs_site_idx").on(
|
|
6062
|
+
table.siteId,
|
|
6063
|
+
table.createdAt.desc()
|
|
6064
|
+
),
|
|
6065
|
+
index("content_ingestion_runs_status_idx").on(table.status),
|
|
6066
|
+
index("content_ingestion_runs_trigger_run_idx").on(table.triggerRunId),
|
|
6067
|
+
index("content_ingestion_runs_project_idx").on(table.projectKey)
|
|
6068
|
+
]
|
|
6069
|
+
);
|
|
5964
6070
|
var GITHUB_API = "https://api.github.com";
|
|
5965
6071
|
var ReleaseProfileQuickCreateError = class extends Error {
|
|
5966
6072
|
constructor(message, code = "INTERNAL_SERVER_ERROR") {
|
|
@@ -7291,7 +7397,7 @@ function getEncryptionKey() {
|
|
|
7291
7397
|
throw new Error("ENCRYPTION_KEY must be a 64-character hex string");
|
|
7292
7398
|
return buf;
|
|
7293
7399
|
}
|
|
7294
|
-
function encrypt(
|
|
7400
|
+
function encrypt(text9) {
|
|
7295
7401
|
const key = getEncryptionKey();
|
|
7296
7402
|
const iv = randomBytes(ENC_IV_LENGTH);
|
|
7297
7403
|
const cipher = createCipheriv(
|
|
@@ -7299,7 +7405,7 @@ function encrypt(text8) {
|
|
|
7299
7405
|
new Uint8Array(key),
|
|
7300
7406
|
new Uint8Array(iv)
|
|
7301
7407
|
);
|
|
7302
|
-
let encrypted = cipher.update(
|
|
7408
|
+
let encrypted = cipher.update(text9, "utf8", "hex");
|
|
7303
7409
|
encrypted += cipher.final("hex");
|
|
7304
7410
|
const authTag = cipher.getAuthTag();
|
|
7305
7411
|
return Buffer.concat([
|
|
@@ -8019,10 +8125,10 @@ async function r2GetObjectRange(bucket, key, range) {
|
|
|
8019
8125
|
const body = result.Body;
|
|
8020
8126
|
if (!body?.transformToString)
|
|
8021
8127
|
throw new Error("R2 returned no readable body");
|
|
8022
|
-
const
|
|
8128
|
+
const text9 = await body.transformToString();
|
|
8023
8129
|
const header = `# range: bytes ${range.offset}-${end} of ${size} (${effectiveLen} bytes)`;
|
|
8024
8130
|
return `${header}
|
|
8025
|
-
${
|
|
8131
|
+
${text9}`;
|
|
8026
8132
|
} catch (e) {
|
|
8027
8133
|
throw r2WrapError(bucket, key, e);
|
|
8028
8134
|
}
|
|
@@ -8385,15 +8491,15 @@ async function sftpRead(opts, filePath, proxy, options) {
|
|
|
8385
8491
|
clearTimeout(timer);
|
|
8386
8492
|
cleanup?.();
|
|
8387
8493
|
cleanup = void 0;
|
|
8388
|
-
const
|
|
8494
|
+
const text9 = Buffer.concat(
|
|
8389
8495
|
chunks.map((ch) => new Uint8Array(ch))
|
|
8390
8496
|
).toString("utf-8");
|
|
8391
8497
|
if (!isWholeFileRequest) {
|
|
8392
8498
|
const header = `# range: bytes ${offset}-${offset + effectiveLen - 1} of ${total} (${effectiveLen} bytes)`;
|
|
8393
8499
|
resolve(`${header}
|
|
8394
|
-
${
|
|
8500
|
+
${text9}`);
|
|
8395
8501
|
} else {
|
|
8396
|
-
resolve(
|
|
8502
|
+
resolve(text9);
|
|
8397
8503
|
}
|
|
8398
8504
|
});
|
|
8399
8505
|
rs.on("error", (e) => {
|
|
@@ -8441,7 +8547,13 @@ var RAW_JSON_TOOLS = /* @__PURE__ */ new Set([
|
|
|
8441
8547
|
"save_content_quality_run",
|
|
8442
8548
|
"list_content_snapshots",
|
|
8443
8549
|
"link_content_pack_to_ticket",
|
|
8444
|
-
"prune_content_snapshots"
|
|
8550
|
+
"prune_content_snapshots",
|
|
8551
|
+
// Managed site content sync (2026-DASMG-042) — compact JSON consumed verbatim.
|
|
8552
|
+
"register_managed_site",
|
|
8553
|
+
"update_managed_site",
|
|
8554
|
+
"list_managed_sites",
|
|
8555
|
+
"trigger_content_sync",
|
|
8556
|
+
"get_content_sync_status"
|
|
8445
8557
|
]);
|
|
8446
8558
|
var TOOL_CACHE_TTL_MS = {
|
|
8447
8559
|
"list-servers": 6e4,
|
|
@@ -8542,11 +8654,11 @@ function getKnownContainers(serverId, maxAgeMs = 5 * 6e4) {
|
|
|
8542
8654
|
if (Date.now() - e.capturedAt > maxAgeMs) return void 0;
|
|
8543
8655
|
return e.names;
|
|
8544
8656
|
}
|
|
8545
|
-
function truncateForLLM(
|
|
8546
|
-
const totalBytes = Buffer.byteLength(
|
|
8657
|
+
function truncateForLLM(text9, maxBytes) {
|
|
8658
|
+
const totalBytes = Buffer.byteLength(text9, "utf8");
|
|
8547
8659
|
if (totalBytes <= maxBytes)
|
|
8548
|
-
return { text:
|
|
8549
|
-
const buf = Buffer.from(
|
|
8660
|
+
return { text: text9, truncated: false, totalBytes, shownBytes: totalBytes };
|
|
8661
|
+
const buf = Buffer.from(text9, "utf8");
|
|
8550
8662
|
let cut = maxBytes;
|
|
8551
8663
|
while (cut > 0 && (buf[cut] & 192) === 128) cut--;
|
|
8552
8664
|
const head = buf.subarray(0, cut).toString("utf8");
|
|
@@ -8577,10 +8689,10 @@ function postprocessResult(result, meta) {
|
|
|
8577
8689
|
if (!result.content?.length) return result;
|
|
8578
8690
|
if (RAW_JSON_TOOLS.has(meta.toolName)) return result;
|
|
8579
8691
|
const block = result.content[0];
|
|
8580
|
-
let
|
|
8581
|
-
const trunc = truncateForLLM(
|
|
8692
|
+
let text9 = String(block.text ?? "");
|
|
8693
|
+
const trunc = truncateForLLM(text9, RESPONSE_MAX_BYTES);
|
|
8582
8694
|
if (trunc.truncated) {
|
|
8583
|
-
|
|
8695
|
+
text9 = trunc.text + "\n\n... " + buildTruncationHint(
|
|
8584
8696
|
meta.toolName,
|
|
8585
8697
|
meta.args,
|
|
8586
8698
|
trunc.totalBytes,
|
|
@@ -8594,11 +8706,11 @@ function postprocessResult(result, meta) {
|
|
|
8594
8706
|
const parts = [`took ${tookStr}`, sizeStr];
|
|
8595
8707
|
if (meta.serverIdLabel) parts.push(`server: ${meta.serverIdLabel}`);
|
|
8596
8708
|
if (meta.cached) parts.push("cached");
|
|
8597
|
-
|
|
8709
|
+
text9 = `${text9}
|
|
8598
8710
|
|
|
8599
8711
|
[${parts.join(", ")}]`;
|
|
8600
8712
|
}
|
|
8601
|
-
return { ...result, content: [{ ...block, text:
|
|
8713
|
+
return { ...result, content: [{ ...block, text: text9 }] };
|
|
8602
8714
|
}
|
|
8603
8715
|
function buildPipelineScript(commands, shell, marker, stopOnError) {
|
|
8604
8716
|
if (shell === "powershell") {
|
|
@@ -10961,6 +11073,151 @@ var TOOLS = [
|
|
|
10961
11073
|
}
|
|
10962
11074
|
}
|
|
10963
11075
|
},
|
|
11076
|
+
{
|
|
11077
|
+
name: "register_managed_site",
|
|
11078
|
+
description: "Register (or upsert by projectKey+domain) a site for content sync (2026-DASMG-042): domain, optional repo/branch + sitemapUrl, syncMode and a git pathUrlMap. Optional + additive \u2014 external/unmanaged sites still work via extract_article without this. Enables git-push/cron/manual ingestion that re-indexes only CHANGED pages into the corpus (hash-skips unchanged ones).",
|
|
11079
|
+
inputSchema: {
|
|
11080
|
+
type: "object",
|
|
11081
|
+
properties: {
|
|
11082
|
+
projectKey: { type: "string", description: "Project identifier (required)." },
|
|
11083
|
+
domain: { type: "string", description: "Site domain, e.g. example.nl (required)." },
|
|
11084
|
+
siteKey: { type: "string", description: "Optional site identifier within the project." },
|
|
11085
|
+
name: { type: "string", description: "Human-friendly site name." },
|
|
11086
|
+
repo: { type: "string", description: "GitHub repo owner/repo that publishes the site (for git pushes)." },
|
|
11087
|
+
branch: { type: "string", description: "Branch whose pushes trigger a sync; omit for any branch." },
|
|
11088
|
+
sitemapUrl: { type: "string", description: "Sitemap URL for sitemap/hybrid detection." },
|
|
11089
|
+
sourceType: {
|
|
11090
|
+
type: "string",
|
|
11091
|
+
enum: [
|
|
11092
|
+
"own_site",
|
|
11093
|
+
"client_site",
|
|
11094
|
+
"external_source",
|
|
11095
|
+
"competitor",
|
|
11096
|
+
"news",
|
|
11097
|
+
"government",
|
|
11098
|
+
"supplier",
|
|
11099
|
+
"unknown"
|
|
11100
|
+
],
|
|
11101
|
+
description: "Provenance label for produced corpus items (default own_site)."
|
|
11102
|
+
},
|
|
11103
|
+
enabled: { type: "boolean", description: "Whether syncs run (default true)." },
|
|
11104
|
+
syncMode: {
|
|
11105
|
+
type: "string",
|
|
11106
|
+
enum: ["sitemap", "git", "hybrid", "manual"],
|
|
11107
|
+
description: "Change detection: sitemap (lastmod/hash), git (changed paths via pathUrlMap), hybrid (both), manual (only on trigger_content_sync)."
|
|
11108
|
+
},
|
|
11109
|
+
pathUrlMap: {
|
|
11110
|
+
type: "array",
|
|
11111
|
+
items: { type: "object" },
|
|
11112
|
+
description: "Git path -> URL rules ([{pathPrefix,urlPrefix}])."
|
|
11113
|
+
},
|
|
11114
|
+
maxUrlsPerRun: { type: "integer", description: "Per-run URL cap (default 200)." },
|
|
11115
|
+
exportToSeoCli: {
|
|
11116
|
+
type: "boolean",
|
|
11117
|
+
description: "Flag changed pages for an MG SEO CLI follow-up (soft handoff)."
|
|
11118
|
+
},
|
|
11119
|
+
metadata: { type: "object" }
|
|
11120
|
+
},
|
|
11121
|
+
required: ["projectKey", "domain"]
|
|
11122
|
+
}
|
|
11123
|
+
},
|
|
11124
|
+
{
|
|
11125
|
+
name: "update_managed_site",
|
|
11126
|
+
description: "Update an existing managed site by id (2026-DASMG-042). Only the provided fields change \u2014 enable/disable, switch syncMode, set sitemapUrl/pathUrlMap, etc.",
|
|
11127
|
+
inputSchema: {
|
|
11128
|
+
type: "object",
|
|
11129
|
+
properties: {
|
|
11130
|
+
id: { type: "string", description: "managed_sites.id (uuid, required)." },
|
|
11131
|
+
name: { type: "string", description: "Human-friendly site name." },
|
|
11132
|
+
domain: { type: "string", description: "Site domain." },
|
|
11133
|
+
siteKey: { type: "string", description: "Site identifier within the project." },
|
|
11134
|
+
repo: { type: "string", description: "GitHub repo owner/repo." },
|
|
11135
|
+
branch: { type: "string", description: "Branch whose pushes trigger a sync." },
|
|
11136
|
+
sitemapUrl: { type: "string", description: "Sitemap URL." },
|
|
11137
|
+
sourceType: {
|
|
11138
|
+
type: "string",
|
|
11139
|
+
enum: [
|
|
11140
|
+
"own_site",
|
|
11141
|
+
"client_site",
|
|
11142
|
+
"external_source",
|
|
11143
|
+
"competitor",
|
|
11144
|
+
"news",
|
|
11145
|
+
"government",
|
|
11146
|
+
"supplier",
|
|
11147
|
+
"unknown"
|
|
11148
|
+
]
|
|
11149
|
+
},
|
|
11150
|
+
enabled: { type: "boolean", description: "Enable/disable syncs." },
|
|
11151
|
+
syncMode: {
|
|
11152
|
+
type: "string",
|
|
11153
|
+
enum: ["sitemap", "git", "hybrid", "manual"]
|
|
11154
|
+
},
|
|
11155
|
+
pathUrlMap: { type: "array", items: { type: "object" } },
|
|
11156
|
+
maxUrlsPerRun: { type: "integer", description: "Per-run URL cap." },
|
|
11157
|
+
exportToSeoCli: { type: "boolean" },
|
|
11158
|
+
metadata: { type: "object" }
|
|
11159
|
+
},
|
|
11160
|
+
required: ["id"]
|
|
11161
|
+
}
|
|
11162
|
+
},
|
|
11163
|
+
{
|
|
11164
|
+
name: "list_managed_sites",
|
|
11165
|
+
description: "List managed sites (2026-DASMG-042), filter by projectKey/domain/repo/enabledOnly. Compact, paginated.",
|
|
11166
|
+
inputSchema: {
|
|
11167
|
+
type: "object",
|
|
11168
|
+
properties: {
|
|
11169
|
+
projectKey: { type: "string", description: "Project filter." },
|
|
11170
|
+
domain: { type: "string", description: "Domain filter." },
|
|
11171
|
+
repo: { type: "string", description: "Repo filter (owner/repo)." },
|
|
11172
|
+
enabledOnly: { type: "boolean", description: "Only enabled sites." },
|
|
11173
|
+
limit: { type: "integer", description: "Max rows (default 50, max 200)." },
|
|
11174
|
+
offset: { type: "integer", description: "Pagination offset." }
|
|
11175
|
+
}
|
|
11176
|
+
}
|
|
11177
|
+
},
|
|
11178
|
+
{
|
|
11179
|
+
name: "trigger_content_sync",
|
|
11180
|
+
description: "Start a content ingestion run for a managed site (2026-DASMG-042) by siteId, or projectKey+domain. Detects changed pages (sitemap/git/hash), re-indexes only changes into the corpus and snapshots the previous version. Returns the runId; poll get_content_sync_status for results.",
|
|
11181
|
+
inputSchema: {
|
|
11182
|
+
type: "object",
|
|
11183
|
+
properties: {
|
|
11184
|
+
siteId: { type: "string", description: "managed_sites.id (uuid)." },
|
|
11185
|
+
projectKey: { type: "string", description: "Project identifier (with domain)." },
|
|
11186
|
+
domain: { type: "string", description: "Site domain (with projectKey)." },
|
|
11187
|
+
triggerType: {
|
|
11188
|
+
type: "string",
|
|
11189
|
+
enum: ["manual", "git_push", "deploy", "cron", "sitemap"],
|
|
11190
|
+
description: "Trigger label recorded on the run (default manual)."
|
|
11191
|
+
},
|
|
11192
|
+
sourceCommit: { type: "string", description: "Source git commit/deploy id, when known." },
|
|
11193
|
+
sourceRef: { type: "string", description: "Source git ref, when known." },
|
|
11194
|
+
urls: {
|
|
11195
|
+
type: "array",
|
|
11196
|
+
items: { type: "string" },
|
|
11197
|
+
description: "Restrict the run to these URLs (skips detection)."
|
|
11198
|
+
},
|
|
11199
|
+
changedPaths: {
|
|
11200
|
+
type: "array",
|
|
11201
|
+
items: { type: "string" },
|
|
11202
|
+
description: "Changed repo paths to map to URLs via pathUrlMap."
|
|
11203
|
+
}
|
|
11204
|
+
}
|
|
11205
|
+
}
|
|
11206
|
+
},
|
|
11207
|
+
{
|
|
11208
|
+
name: "get_content_sync_status",
|
|
11209
|
+
description: "Read ingestion run status (2026-DASMG-042): by runId (that run), or by siteId / projectKey+domain (recent runs). Returns changed/skipped/failed counts, the changed URLs, limitations and the site summary.",
|
|
11210
|
+
inputSchema: {
|
|
11211
|
+
type: "object",
|
|
11212
|
+
properties: {
|
|
11213
|
+
runId: { type: "string", description: "content_ingestion_runs.id (uuid)." },
|
|
11214
|
+
siteId: { type: "string", description: "managed_sites.id (uuid)." },
|
|
11215
|
+
projectKey: { type: "string", description: "Project identifier (with domain)." },
|
|
11216
|
+
domain: { type: "string", description: "Site domain (with projectKey)." },
|
|
11217
|
+
limit: { type: "integer", description: "Max recent runs to return (default 10)." }
|
|
11218
|
+
}
|
|
11219
|
+
}
|
|
11220
|
+
},
|
|
10964
11221
|
{
|
|
10965
11222
|
name: "search-team-memory",
|
|
10966
11223
|
description: "Search the team's ENTIRE past Cursor history (every developer, every project) for how something was handled before. Use this FIRST, before investigating from scratch, whenever you: hit a non-trivial bug or error, are about to build something that may have been done before, need a project-specific convention/gotcha, or the user asks 'have we done X', 'how did we fix Y', or 'did we solve this already'. Hybrid semantic + keyword search over mirrored conversations. Returns ranked past chats with repo, date, a solution snippet and a similarity score. Phrase the query as the problem in natural language (e.g. 'release pipeline PM2 deploy fails with module not found').",
|
|
@@ -11061,7 +11318,7 @@ var TOOLS = [
|
|
|
11061
11318
|
// ----- Trigger.dev -----
|
|
11062
11319
|
...TRIGGER_TOOLS
|
|
11063
11320
|
];
|
|
11064
|
-
var MCP_VERSION = "7.0
|
|
11321
|
+
var MCP_VERSION = "7.3.0";
|
|
11065
11322
|
async function handleListTools() {
|
|
11066
11323
|
if (!authContext) return { tools: TOOLS };
|
|
11067
11324
|
const allowedTools = authContext.allowedTools;
|
|
@@ -11305,6 +11562,39 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
11305
11562
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
11306
11563
|
};
|
|
11307
11564
|
}
|
|
11565
|
+
// ----- Managed site content sync (2026-DASMG-042) -----
|
|
11566
|
+
// The 5 PUBLIC managed-site tools proxy to one dispatcher route; the tool
|
|
11567
|
+
// name is the dispatcher `action`, args forwarded verbatim as `params`
|
|
11568
|
+
// (the route validates them and only allows the public actions).
|
|
11569
|
+
case "register_managed_site":
|
|
11570
|
+
case "update_managed_site":
|
|
11571
|
+
case "list_managed_sites":
|
|
11572
|
+
case "trigger_content_sync":
|
|
11573
|
+
case "get_content_sync_status": {
|
|
11574
|
+
const res = await fetch(`${dashboardBaseUrl}/api/tools/managed-site`, {
|
|
11575
|
+
method: "POST",
|
|
11576
|
+
headers: {
|
|
11577
|
+
"content-type": "application/json",
|
|
11578
|
+
authorization: `Bearer ${apiKey}`
|
|
11579
|
+
},
|
|
11580
|
+
body: JSON.stringify({ action: name, params: a })
|
|
11581
|
+
});
|
|
11582
|
+
if (!res.ok) {
|
|
11583
|
+
const detail = await res.text().catch(() => "");
|
|
11584
|
+
return {
|
|
11585
|
+
content: [
|
|
11586
|
+
{
|
|
11587
|
+
type: "text",
|
|
11588
|
+
text: `Error: ${name} failed (${res.status}). ${detail.slice(0, 300)}`
|
|
11589
|
+
}
|
|
11590
|
+
]
|
|
11591
|
+
};
|
|
11592
|
+
}
|
|
11593
|
+
const data = await res.json();
|
|
11594
|
+
return {
|
|
11595
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
|
|
11596
|
+
};
|
|
11597
|
+
}
|
|
11308
11598
|
// ----- Team memory -----
|
|
11309
11599
|
case "search-team-memory": {
|
|
11310
11600
|
const query = typeof a.query === "string" ? a.query.trim() : "";
|
|
@@ -11346,7 +11636,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
11346
11636
|
]
|
|
11347
11637
|
};
|
|
11348
11638
|
}
|
|
11349
|
-
const lines = data.hits.map((hit,
|
|
11639
|
+
const lines = data.hits.map((hit, index7) => {
|
|
11350
11640
|
const when = hit.lastMessageAt ? new Date(hit.lastMessageAt).toISOString().slice(0, 10) : "unknown date";
|
|
11351
11641
|
const repo = hit.repo ?? "unknown repo";
|
|
11352
11642
|
const sim = hit.similarity !== null ? ` \xB7 ${(hit.similarity * 100).toFixed(0)}% match` : "";
|
|
@@ -11356,7 +11646,7 @@ async function executeToolCall(name, a, _serverId) {
|
|
|
11356
11646
|
...Array.isArray(hit.tech) ? hit.tech.slice(0, 4) : []
|
|
11357
11647
|
].filter(Boolean);
|
|
11358
11648
|
const tags = facets.length > 0 ? ` \xB7 ${facets.join(", ")}` : "";
|
|
11359
|
-
return `${
|
|
11649
|
+
return `${index7 + 1}. [${repo} \xB7 ${when}${sim}${tags}] ${hit.title}
|
|
11360
11650
|
id: ${hit.id}
|
|
11361
11651
|
${(hit.summary ?? hit.snippet).replace(/\s+/g, " ").slice(0, 500)}`;
|
|
11362
11652
|
});
|
|
@@ -12541,8 +12831,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
12541
12831
|
};
|
|
12542
12832
|
const filtered = sortRows(applyFilter(only.rows));
|
|
12543
12833
|
if (format === "json") {
|
|
12544
|
-
const
|
|
12545
|
-
return { content: [{ type: "text", text:
|
|
12834
|
+
const text10 = filtered.map((c) => JSON.stringify(c)).join("\n") || "(no containers)";
|
|
12835
|
+
return { content: [{ type: "text", text: text10 }] };
|
|
12546
12836
|
}
|
|
12547
12837
|
if (groupByProject) {
|
|
12548
12838
|
const groups = /* @__PURE__ */ new Map();
|
|
@@ -12569,8 +12859,8 @@ ${sample.join("\n")}${files.length > 5 ? `
|
|
|
12569
12859
|
}
|
|
12570
12860
|
const header = `${"NAMES".padEnd(36)} ${"IMAGE".padEnd(40)} ${"STATUS".padEnd(24)} ${"HEALTH".padEnd(10)} ${"PORTS".padEnd(40)} PROJECT`;
|
|
12571
12861
|
const body = filtered.map((r) => `${fmtRow(r)} ${r.Project || ""}`);
|
|
12572
|
-
const
|
|
12573
|
-
return { content: [{ type: "text", text:
|
|
12862
|
+
const text9 = filtered.length === 0 ? "(no containers match)" : [header, ...body].join("\n");
|
|
12863
|
+
return { content: [{ type: "text", text: text9 }] };
|
|
12574
12864
|
}
|
|
12575
12865
|
if (format === "json") {
|
|
12576
12866
|
const lines = [];
|