@mgsoftwarebv/mcp-server-bridge 3.5.12 → 3.5.13

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
@@ -106586,6 +106586,24 @@ var TOOLS = [
106586
106586
  required: ["id"]
106587
106587
  }
106588
106588
  },
106589
+ {
106590
+ name: "get-document-link",
106591
+ description: "Get a safe, usable link for a document (use after create-document to share it). Never leaks an auth/session URL. Choose `linkType`:\n- dashboard (default): internal editor deep link for logged-in Refront users, plus the current PDF status and a public link when the document is already shared publicly.\n- pdf_signed (alias: pdf): a temporary signed PDF download URL when a compiled PDF exists; if it is still compiling it returns pdfStatus 'pending' with pdfUrl null and triggers a (re)compile instead of failing.\n- public_share: enables a public customer share (token + visibility=public, recompiling only when no fresh PDF exists) and returns the /p/<token> link. Only use when the document may be shared publicly. Revoke later from the dashboard.\nReturns a JSON object: { documentId, title, status, dashboardUrl, pdfStatus (ready|stale|pending|unavailable), pdfUrl, publicShareUrl, expiresAt }. Respects team/provider access; draft/private documents never expose a public share URL unless they are actually shared.",
106592
+ inputSchema: {
106593
+ type: "object",
106594
+ properties: {
106595
+ teamId: teamIdProp,
106596
+ documentId: { type: "string", description: "Document ID (UUID)" },
106597
+ linkType: {
106598
+ type: "string",
106599
+ enum: ["dashboard", "pdf_signed", "pdf", "public_share"],
106600
+ default: "dashboard",
106601
+ description: "dashboard (default) = editor URL + PDF status; pdf_signed (alias pdf) = temporary signed PDF download URL; public_share = enable + return the public /p/<token> link."
106602
+ }
106603
+ },
106604
+ required: ["documentId"]
106605
+ }
106606
+ },
106589
106607
  {
106590
106608
  name: "create-document",
106591
106609
  description: 'Create a document (proposal, report, deliverables/opleverdocument, ...) from an array of content blocks. Use type \'deliverables\' for a document describing what was delivered for a customer; optionally pass `invoiceId` to link it to an invoice so it can be sent along as a PDF attachment. Each block is `{ id?, type, data }` (ids are auto-generated when omitted). Supported block types and their `data` shapes:\n- cover: { title, subtitle?, showLogo: bool, showDate: bool, clientName?, clientCompany?, date? }\n- toc: { title, maxDepth: 1-6 }\n- heading: { text, level: 1|2|3, numbered: bool }\n- text: { content: TipTapDoc | plain string (auto-converted; supports paragraphs and "- " bullet lists) }\n- callout: { variant: "info"|"warning"|"tip"|"important", title?, content: TipTapDoc | string }\n- table: { title?, headers: string[], rows: string[][] }\n- chart: { title?, chartType: "bar"|"line"|"pie", points: [{label, value}], seriesName?, series?: [{name, color?, points: [{label, value}]}], unit? ("\u20AC"|"%"|...), showValues: bool, color? }. Multi-series (bar/line only): extra series values are matched to the primary points by index; a legend is rendered automatically.\n- pricing: { title?, items: [{description, quantity?, unit?, price}], currency: "EUR", showTotal: bool, vatRate?, includeVat: bool }\n- timeline: { title?, phases: [{name, description?, duration, deliverables?: string[]}] }\n- two_column: { left: TipTapDoc|string, right: TipTapDoc|string, ratio?: "50_50"|"60_40"|"40_60"|"70_30"|"30_70" }\n- divider: { style: "page_break"|"line"|"space" }\n- signature: { title?, description?, signers: [{id, label, name?, company?, role?}] }\nAll text content runs through a humanizer that strips AI-sounding patterns (em-dashes, clich\xE9s, filler phrases); control it with `humanize`. The result includes ready-to-use links (internal dashboard editor URL + PDF status). Use get-document-link afterwards for a PDF download link or to publish a public customer share link.',
@@ -109730,6 +109748,59 @@ function ensureTipTapFormat(text3) {
109730
109748
  if (isTipTapJson(text3)) return text3;
109731
109749
  return JSON.stringify(plainTextToTipTap(text3));
109732
109750
  }
109751
+
109752
+ // src/tools/document-links.ts
109753
+ function derivePdfStatus(doc) {
109754
+ const currentHash = computeDocumentContentHash({
109755
+ blocks: doc.blocks,
109756
+ branding: doc.branding,
109757
+ pageSize: doc.pageSize,
109758
+ locale: doc.locale,
109759
+ title: doc.title
109760
+ });
109761
+ if (doc.filePath) {
109762
+ if (doc.compiledHash && doc.compiledHash === currentHash) {
109763
+ return { status: "ready", currentHash };
109764
+ }
109765
+ return { status: "stale", currentHash };
109766
+ }
109767
+ if (doc.compiledHash) return { status: "pending", currentHash };
109768
+ return { status: "unavailable", currentHash };
109769
+ }
109770
+ function getDashboardBaseUrl() {
109771
+ return (process.env.DASHBOARD_URL || "https://app.refront.nl").replace(
109772
+ /\/+$/,
109773
+ ""
109774
+ );
109775
+ }
109776
+ function buildDashboardUrl(documentId) {
109777
+ return `${getDashboardBaseUrl()}/quotations/documents?editDocument=true&documentId=${encodeURIComponent(
109778
+ documentId
109779
+ )}`;
109780
+ }
109781
+ function buildPublicShareUrl(token) {
109782
+ return `${getDashboardBaseUrl()}/p/${encodeURIComponent(token)}`;
109783
+ }
109784
+ function isPubliclyShared(doc) {
109785
+ return !!doc.token && doc.shareVisibility === "public";
109786
+ }
109787
+ function formatDocumentLinksSummary(doc) {
109788
+ const { status: pdfStatus } = derivePdfStatus(doc);
109789
+ const lines = [
109790
+ "\u{1F517} Links:",
109791
+ `- Dashboard: ${buildDashboardUrl(doc.id)}`,
109792
+ `- PDF status: ${pdfStatus}`
109793
+ ];
109794
+ if (isPubliclyShared(doc) && doc.token) {
109795
+ lines.push(`- Public share: ${buildPublicShareUrl(doc.token)}`);
109796
+ }
109797
+ lines.push(
109798
+ "- Use get-document-link (linkType pdf_signed for a temporary PDF download URL, public_share to publish a public link)."
109799
+ );
109800
+ return lines.join("\n");
109801
+ }
109802
+
109803
+ // src/tools/documents.ts
109733
109804
  var DOCUMENT_TYPES = [
109734
109805
  "proposal",
109735
109806
  "plan_of_action",
@@ -109771,7 +109842,6 @@ var PDF_STATUS_LABEL = {
109771
109842
  };
109772
109843
  function buildLinksSection(doc, opts) {
109773
109844
  let status = computePdfStatus(doc);
109774
- if (opts?.compileTriggered && status !== "ready") status = "pending";
109775
109845
  const lines = [
109776
109846
  "Links:",
109777
109847
  `- Dashboard (internal, login required): ${documentDashboardUrl(doc.id)}`,
@@ -109872,7 +109942,10 @@ var TRIGGER_API_URL = process.env.TRIGGER_API_URL || "https://trigger-dev.mgsoft
109872
109942
  async function maybeTriggerPdfCompile(documentId, teamId) {
109873
109943
  const secret = process.env.TRIGGER_SECRET_KEY;
109874
109944
  if (!secret) {
109875
- return "PDF: niet gecompileerd (TRIGGER_SECRET_KEY ontbreekt); de dashboard-editor compileert bij openen/delen.";
109945
+ return {
109946
+ triggered: false,
109947
+ message: "PDF: niet gecompileerd (TRIGGER_SECRET_KEY ontbreekt); de dashboard-editor compileert bij openen/delen."
109948
+ };
109876
109949
  }
109877
109950
  try {
109878
109951
  const response = await fetch(
@@ -109888,12 +109961,21 @@ async function maybeTriggerPdfCompile(documentId, teamId) {
109888
109961
  );
109889
109962
  if (!response.ok) {
109890
109963
  const body = await response.text();
109891
- return `PDF: compile-trigger mislukt (HTTP ${response.status}): ${body.slice(0, 200)}`;
109964
+ return {
109965
+ triggered: false,
109966
+ message: `PDF: compile-trigger mislukt (HTTP ${response.status}): ${body.slice(0, 200)}`
109967
+ };
109892
109968
  }
109893
109969
  const json5 = await response.json();
109894
- return `PDF: compile-document-pdf getriggerd (run ${json5.id ?? "?"}).`;
109970
+ return {
109971
+ triggered: true,
109972
+ message: `PDF: compile-document-pdf getriggerd (run ${json5.id ?? "?"}).`
109973
+ };
109895
109974
  } catch (error49) {
109896
- return `PDF: compile-trigger mislukt: ${error49 instanceof Error ? error49.message : String(error49)}`;
109975
+ return {
109976
+ triggered: false,
109977
+ message: `PDF: compile-trigger mislukt: ${error49 instanceof Error ? error49.message : String(error49)}`
109978
+ };
109897
109979
  }
109898
109980
  }
109899
109981
  async function applyBlockOps(existing, ops, humanize) {
@@ -110078,7 +110160,7 @@ Type: ${doc.type} | Status: ${doc.status} | Locale: ${doc.locale}
110078
110160
  Team: ${doc.teamId}${doc.customerId ? ` | Customer: ${doc.customerId}` : ""}${doc.invoiceId ? ` | Invoice: ${doc.invoiceId}` : ""}
110079
110161
  Blocks (${blocks.length}): ${blockTypeSummary(blocks) || "none"}
110080
110162
 
110081
- ${buildLinksSection(doc)}
110163
+ ${formatDocumentLinksSummary(doc)}
110082
110164
 
110083
110165
  Blocks JSON:
110084
110166
  \`\`\`json
@@ -110265,22 +110347,19 @@ async function handleCreateDocument(input) {
110265
110347
  content: [{ type: "text", text: "Error: document insert failed." }]
110266
110348
  };
110267
110349
  }
110268
- const pdfLine = compilePdf ? await maybeTriggerPdfCompile(created.id, resolved.teamId) : null;
110269
- const linksSection = buildLinksSection(
110270
- {
110271
- id: created.id,
110272
- title: title.trim(),
110273
- blocks: humanized.blocks,
110274
- branding: {},
110275
- pageSize: "a4",
110276
- locale,
110277
- filePath: null,
110278
- compiledHash: null,
110279
- token: null,
110280
- shareVisibility: "private"
110281
- },
110282
- { compileTriggered: compilePdf && Boolean(process.env.TRIGGER_SECRET_KEY) }
110283
- );
110350
+ const pdfResult = compilePdf ? await maybeTriggerPdfCompile(created.id, resolved.teamId) : null;
110351
+ const linksSummary = formatDocumentLinksSummary({
110352
+ id: created.id,
110353
+ title: title.trim(),
110354
+ blocks: humanized.blocks,
110355
+ branding: {},
110356
+ pageSize: "a4",
110357
+ locale,
110358
+ filePath: null,
110359
+ compiledHash: null,
110360
+ token: null,
110361
+ shareVisibility: "private"
110362
+ });
110284
110363
  return {
110285
110364
  content: [
110286
110365
  {
@@ -110294,10 +110373,10 @@ Team: ${resolved.teamId}${customerId ? ` | Customer: ${customerId}` : ""}
110294
110373
  ${invoiceLine ? `${invoiceLine}
110295
110374
  ` : ""}Blocks (${humanized.blocks.length}): ${blockTypeSummary(humanized.blocks)}
110296
110375
 
110297
- ${humanized.summary}${pdfLine ? `
110298
- ${pdfLine}` : ""}
110376
+ ${humanized.summary}${pdfResult ? `
110377
+ ${pdfResult.message}` : ""}
110299
110378
 
110300
- ` + linksSection
110379
+ ${linksSummary}`
110301
110380
  }
110302
110381
  ]
110303
110382
  };
@@ -110459,23 +110538,20 @@ async function handleUpdateDocument(input) {
110459
110538
  };
110460
110539
  }
110461
110540
  await db.update(schema_exports.documents).set(patch).where(eq(schema_exports.documents.id, doc.id));
110462
- const pdfLine = compilePdf ? await maybeTriggerPdfCompile(doc.id, doc.teamId) : null;
110463
- const linksSection = buildLinksSection(
110464
- {
110465
- id: doc.id,
110466
- title: patch.title ?? doc.title,
110467
- status: patch.status ?? doc.status,
110468
- blocks: patch.blocks ?? doc.blocks,
110469
- branding: doc.branding,
110470
- pageSize: doc.pageSize,
110471
- locale: doc.locale,
110472
- filePath: doc.filePath,
110473
- compiledHash: doc.compiledHash,
110474
- token: doc.token,
110475
- shareVisibility: doc.shareVisibility
110476
- },
110477
- { compileTriggered: compilePdf && Boolean(process.env.TRIGGER_SECRET_KEY) }
110478
- );
110541
+ const pdfResult = compilePdf ? await maybeTriggerPdfCompile(doc.id, doc.teamId) : null;
110542
+ const linksSummary = formatDocumentLinksSummary({
110543
+ id: doc.id,
110544
+ title: patch.title ?? doc.title,
110545
+ status: patch.status ?? doc.status,
110546
+ blocks: "blocks" in patch ? patch.blocks : doc.blocks,
110547
+ branding: doc.branding,
110548
+ pageSize: doc.pageSize,
110549
+ locale: doc.locale,
110550
+ filePath: doc.filePath,
110551
+ compiledHash: doc.compiledHash,
110552
+ token: doc.token,
110553
+ shareVisibility: doc.shareVisibility
110554
+ });
110479
110555
  return {
110480
110556
  content: [
110481
110557
  {
@@ -110485,10 +110561,10 @@ async function handleUpdateDocument(input) {
110485
110561
  ID: ${doc.id}
110486
110562
  ${changeLines.map((l4) => `- ${l4}`).join("\n")}${humanizeSummary ? `
110487
110563
 
110488
- ${humanizeSummary}` : ""}${pdfLine ? `
110489
- ${pdfLine}` : ""}
110564
+ ${humanizeSummary}` : ""}${pdfResult ? `
110565
+ ${pdfResult.message}` : ""}
110490
110566
 
110491
- ` + linksSection
110567
+ ${linksSummary}`
110492
110568
  }
110493
110569
  ]
110494
110570
  };