@formfeed/mcp 0.3.12 → 0.3.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/bin/formfeed-mcp.mjs +97 -36
- package/package.json +1 -1
package/bin/formfeed-mcp.mjs
CHANGED
|
@@ -70689,7 +70689,10 @@ var barcodeTypes = {
|
|
|
70689
70689
|
var ownTextLayout = /* @__PURE__ */ new Set(["ean13", "ean8", "upca"]);
|
|
70690
70690
|
function codeText(helper, value) {
|
|
70691
70691
|
const text4 = value === void 0 || value === null ? "" : String(value);
|
|
70692
|
-
if (text4 === "")
|
|
70692
|
+
if (text4 === "")
|
|
70693
|
+
throw new Error(
|
|
70694
|
+
`${helper}: nothing to encode, the value is empty or missing from the data`
|
|
70695
|
+
);
|
|
70693
70696
|
return text4;
|
|
70694
70697
|
}
|
|
70695
70698
|
var codeHelpers = [
|
|
@@ -70698,18 +70701,25 @@ var codeHelpers = [
|
|
|
70698
70701
|
aliases: ["qr"],
|
|
70699
70702
|
doc: {
|
|
70700
70703
|
signature: "qrcode(value, { size = 160, ecc = 'M', margin = 1, color, background })",
|
|
70701
|
-
description: "QR code as an SVG data URI for an <img> src.",
|
|
70704
|
+
description: "QR code as an SVG data URI for an <img> src. Give the image an `alt` that says where the code leads: a screen reader cannot scan it.",
|
|
70702
70705
|
examples: {
|
|
70703
|
-
jinja2: '<img src="{{ qrcode(order.url, { size: 120 }) }}">',
|
|
70704
|
-
liquid: '<img src="{{ order.url | qrcode: size: 120 }}">',
|
|
70705
|
-
handlebars: '<img src="{{qrcode order.url size=120}}">'
|
|
70706
|
+
jinja2: '<img src="{{ qrcode(order.url, { size: 120 }) }}" alt="QR code: {{ order.url }}">',
|
|
70707
|
+
liquid: '<img src="{{ order.url | qrcode: size: 120 }}" alt="QR code: {{ order.url }}">',
|
|
70708
|
+
handlebars: '<img src="{{qrcode order.url size=120}}" alt="QR code: {{order.url}}">'
|
|
70706
70709
|
},
|
|
70707
70710
|
category: "code"
|
|
70708
70711
|
},
|
|
70709
70712
|
fn: (ctx, value, options) => {
|
|
70710
70713
|
const o = options ?? {};
|
|
70711
70714
|
const svg = qrSvg(codeText("qrcode", value), o);
|
|
70712
|
-
if (ctx.drawing)
|
|
70715
|
+
if (ctx.drawing)
|
|
70716
|
+
return ctx.drawing({
|
|
70717
|
+
kind: "svg",
|
|
70718
|
+
svg,
|
|
70719
|
+
width: o.size,
|
|
70720
|
+
height: o.size,
|
|
70721
|
+
alt: "QR code"
|
|
70722
|
+
});
|
|
70713
70723
|
return svgDataUri(svg);
|
|
70714
70724
|
}
|
|
70715
70725
|
},
|
|
@@ -70717,11 +70727,11 @@ var codeHelpers = [
|
|
|
70717
70727
|
name: "barcode",
|
|
70718
70728
|
doc: {
|
|
70719
70729
|
signature: "barcode(value, { type = 'code128', height = 12, width, text = true, scale = 2 })",
|
|
70720
|
-
description: "Barcode (code128, ean13, ean8, upc, itf14, code39, datamatrix, pdf417) as an SVG data URI.",
|
|
70730
|
+
description: "Barcode (code128, ean13, ean8, upc, itf14, code39, datamatrix, pdf417) as an SVG data URI. Give the image an `alt` with the value it encodes.",
|
|
70721
70731
|
examples: {
|
|
70722
|
-
jinja2: `<img src="{{ barcode(item.sku, { type: 'code128' }) }}">`,
|
|
70723
|
-
liquid: `<img src="{{ item.sku | barcode: type: 'code128' }}">`,
|
|
70724
|
-
handlebars: `<img src="{{barcode item.sku type='code128'}}">`
|
|
70732
|
+
jinja2: `<img src="{{ barcode(item.sku, { type: 'code128' }) }}" alt="Barcode {{ item.sku }}">`,
|
|
70733
|
+
liquid: `<img src="{{ item.sku | barcode: type: 'code128' }}" alt="Barcode {{ item.sku }}">`,
|
|
70734
|
+
handlebars: `<img src="{{barcode item.sku type='code128'}}" alt="Barcode {{item.sku}}">`
|
|
70725
70735
|
},
|
|
70726
70736
|
category: "code"
|
|
70727
70737
|
},
|
|
@@ -70738,7 +70748,8 @@ var codeHelpers = [
|
|
|
70738
70748
|
includetext: o.text !== false,
|
|
70739
70749
|
...ownTextLayout.has(bcid) ? {} : { textxalign: "center" }
|
|
70740
70750
|
});
|
|
70741
|
-
if (ctx.drawing)
|
|
70751
|
+
if (ctx.drawing)
|
|
70752
|
+
return ctx.drawing({ kind: "svg", svg, alt: `Barcode ${text4}` });
|
|
70742
70753
|
return svgDataUri(svg);
|
|
70743
70754
|
}
|
|
70744
70755
|
},
|
|
@@ -70747,11 +70758,11 @@ var codeHelpers = [
|
|
|
70747
70758
|
aliases: ["epc_qr", "girocode"],
|
|
70748
70759
|
doc: {
|
|
70749
70760
|
signature: "epcQr({ name, iban, bic?, amount?, reference?, text? }, { size })",
|
|
70750
|
-
description: "SEPA credit transfer QR code (EPC069-12 / GiroCode) that banking apps scan to prefill a payment.",
|
|
70761
|
+
description: "SEPA credit transfer QR code (EPC069-12 / GiroCode) that banking apps scan to prefill a payment. Give the image an `alt`, and print the bank details as text as well: the code is a picture.",
|
|
70751
70762
|
examples: {
|
|
70752
|
-
jinja2: '<img src="{{ epcQr({ name: company.name, iban: company.iban, amount: invoice.total, reference: invoice.number }) }}">',
|
|
70753
|
-
liquid: '<img src="{{ company.iban | epcQr: name: company.name, amount: invoice.total, reference: invoice.number }}">',
|
|
70754
|
-
handlebars: '<img src="{{epcQr name=company.name iban=company.iban amount=invoice.total reference=invoice.number}}">'
|
|
70763
|
+
jinja2: '<img src="{{ epcQr({ name: company.name, iban: company.iban, amount: invoice.total, reference: invoice.number }) }}" alt="QR code to pay invoice {{ invoice.number }}">',
|
|
70764
|
+
liquid: '<img src="{{ company.iban | epcQr: name: company.name, amount: invoice.total, reference: invoice.number }}" alt="QR code to pay invoice {{ invoice.number }}">',
|
|
70765
|
+
handlebars: '<img src="{{epcQr name=company.name iban=company.iban amount=invoice.total reference=invoice.number}}" alt="QR code to pay invoice {{invoice.number}}">'
|
|
70755
70766
|
},
|
|
70756
70767
|
category: "code"
|
|
70757
70768
|
},
|
|
@@ -70770,12 +70781,27 @@ var codeHelpers = [
|
|
|
70770
70781
|
(EPC_FIELDS.has(key) ? payment2 : qr)[key] = value;
|
|
70771
70782
|
const o = { ecc: "M", ...qr };
|
|
70772
70783
|
const svg = qrSvg(epcPayload(payment2), o);
|
|
70773
|
-
if (ctx.drawing)
|
|
70784
|
+
if (ctx.drawing)
|
|
70785
|
+
return ctx.drawing({
|
|
70786
|
+
kind: "svg",
|
|
70787
|
+
svg,
|
|
70788
|
+
width: o.size,
|
|
70789
|
+
height: o.size,
|
|
70790
|
+
alt: "GiroCode"
|
|
70791
|
+
});
|
|
70774
70792
|
return svgDataUri(svg);
|
|
70775
70793
|
}
|
|
70776
70794
|
}
|
|
70777
70795
|
];
|
|
70778
|
-
var EPC_FIELDS = /* @__PURE__ */ new Set([
|
|
70796
|
+
var EPC_FIELDS = /* @__PURE__ */ new Set([
|
|
70797
|
+
"name",
|
|
70798
|
+
"iban",
|
|
70799
|
+
"bic",
|
|
70800
|
+
"amount",
|
|
70801
|
+
"reference",
|
|
70802
|
+
"text",
|
|
70803
|
+
"purpose"
|
|
70804
|
+
]);
|
|
70779
70805
|
|
|
70780
70806
|
// node_modules/.pnpm/@date-fns+tz@1.5.0/node_modules/@date-fns/tz/constants/index.js
|
|
70781
70807
|
var constructFromSymbol = Symbol.for("constructDateFrom");
|
|
@@ -78352,7 +78378,16 @@ var collectionHelpers = [
|
|
|
78352
78378
|
];
|
|
78353
78379
|
|
|
78354
78380
|
// packages/engine/src/lib/helpers/document.ts
|
|
78355
|
-
var CHART_PALETTE = [
|
|
78381
|
+
var CHART_PALETTE = [
|
|
78382
|
+
"#3E63DD",
|
|
78383
|
+
"#12A594",
|
|
78384
|
+
"#E5484D",
|
|
78385
|
+
"#F76B15",
|
|
78386
|
+
"#8E4EC6",
|
|
78387
|
+
"#FFC53D",
|
|
78388
|
+
"#0090FF",
|
|
78389
|
+
"#978365"
|
|
78390
|
+
];
|
|
78356
78391
|
var SLICED = /* @__PURE__ */ new Set(["pie", "doughnut", "polarArea"]);
|
|
78357
78392
|
var colour = (value) => typeof value === "string" && value ? value : Array.isArray(value) && value.length ? value.map(String) : void 0;
|
|
78358
78393
|
function chartDataFromPlain(spec) {
|
|
@@ -78366,8 +78401,13 @@ function chartDataFromPlain(spec) {
|
|
|
78366
78401
|
});
|
|
78367
78402
|
const own = colour(s.color);
|
|
78368
78403
|
const fill = SLICED.has(type) ? own ?? labels.map((_2, i) => CHART_PALETTE[i % CHART_PALETTE.length]) : own ?? CHART_PALETTE[index % CHART_PALETTE.length];
|
|
78369
|
-
const dataset = {
|
|
78370
|
-
|
|
78404
|
+
const dataset = {
|
|
78405
|
+
data,
|
|
78406
|
+
backgroundColor: fill,
|
|
78407
|
+
borderColor: fill
|
|
78408
|
+
};
|
|
78409
|
+
if (s.label !== void 0 && s.label !== null && s.label !== "")
|
|
78410
|
+
dataset["label"] = String(s.label);
|
|
78371
78411
|
if (type === "line") dataset["fill"] = false;
|
|
78372
78412
|
return dataset;
|
|
78373
78413
|
});
|
|
@@ -78384,7 +78424,8 @@ function chartPayload(spec) {
|
|
|
78384
78424
|
const options = { ...spec.options ?? {} };
|
|
78385
78425
|
options["animation"] = false;
|
|
78386
78426
|
options["responsive"] = false;
|
|
78387
|
-
if (!isPlain(spec))
|
|
78427
|
+
if (!isPlain(spec))
|
|
78428
|
+
return { type: spec.type ?? "bar", data: spec.data ?? {}, options };
|
|
78388
78429
|
const data = chartDataFromPlain(spec);
|
|
78389
78430
|
const unnamed = data.datasets.length === 1 && data.datasets[0]?.["label"] === void 0;
|
|
78390
78431
|
const plugins = asObject(options["plugins"]);
|
|
@@ -78397,7 +78438,8 @@ function chartMarkup(spec, id) {
|
|
|
78397
78438
|
const height = toNumber(spec.height ?? 240) || 240;
|
|
78398
78439
|
const payload = escapeHtml(JSON.stringify(chartPayload(spec)));
|
|
78399
78440
|
const idAttr = id ? ` id="${escapeHtml(id)}"` : "";
|
|
78400
|
-
|
|
78441
|
+
const alt = typeof spec.alt === "string" && spec.alt.trim() ? ` role="img" aria-label="${escapeHtml(spec.alt.trim())}"` : "";
|
|
78442
|
+
return `<canvas class="ff-chart"${idAttr}${alt} width="${width}" height="${height}" style="width:${width}px;height:${height}px" data-ff-chart="${payload}"></canvas>`;
|
|
78401
78443
|
}
|
|
78402
78444
|
function imageMarkup(url, options = {}) {
|
|
78403
78445
|
const styles = [
|
|
@@ -78418,18 +78460,21 @@ var documentHelpers = [
|
|
|
78418
78460
|
name: "chart",
|
|
78419
78461
|
html: true,
|
|
78420
78462
|
doc: {
|
|
78421
|
-
signature: "chart({ type, labels, values, label, color } | { type, labels, series } | { type, data, options }, { width, height })",
|
|
78422
|
-
description: "Draws a Chart.js chart (bar, line, pie, doughnut, radar, \u2026) from plain data, `labels` with `values` or several `series` of `{ label, values, color }`, or from a full Chart.js `data` and `options`; animations are disabled so PDF and preview match.",
|
|
78463
|
+
signature: "chart({ type, labels, values, label, color } | { type, labels, series } | { type, data, options }, { width, height, alt })",
|
|
78464
|
+
description: "Draws a Chart.js chart (bar, line, pie, doughnut, radar, \u2026) from plain data, `labels` with `values` or several `series` of `{ label, values, color }`, or from a full Chart.js `data` and `options`; animations are disabled so PDF and preview match. `alt` says in words what the chart shows: a screen reader reads it in place of the picture, and a tagged PDF needs it.",
|
|
78423
78465
|
examples: {
|
|
78424
|
-
jinja2: "{{ chart({ type: 'line', labels: sales.labels, values: sales.quarters, width: 480 }) }}",
|
|
78425
|
-
liquid: "{{ '' | chart: type: 'line', labels: sales.labels, values: sales.quarters, width: 480 }}",
|
|
78426
|
-
handlebars: "{{chart type='line' labels=sales.labels values=sales.quarters width=480}}"
|
|
78466
|
+
jinja2: "{{ chart({ type: 'line', labels: sales.labels, values: sales.quarters, width: 480, alt: 'Sales by quarter' }) }}",
|
|
78467
|
+
liquid: "{{ '' | chart: type: 'line', labels: sales.labels, values: sales.quarters, width: 480, alt: 'Sales by quarter' }}",
|
|
78468
|
+
handlebars: "{{chart type='line' labels=sales.labels values=sales.quarters width=480 alt='Sales by quarter'}}"
|
|
78427
78469
|
},
|
|
78428
78470
|
category: "document"
|
|
78429
78471
|
},
|
|
78430
78472
|
fn: (ctx, spec, extra) => {
|
|
78431
78473
|
if (ctx.mode === "office") throw new Error(officeUnsupported("chart"));
|
|
78432
|
-
return chartMarkup({
|
|
78474
|
+
return chartMarkup({
|
|
78475
|
+
...asObject(spec),
|
|
78476
|
+
...asObject(extra)
|
|
78477
|
+
});
|
|
78433
78478
|
}
|
|
78434
78479
|
},
|
|
78435
78480
|
{
|
|
@@ -78437,18 +78482,24 @@ var documentHelpers = [
|
|
|
78437
78482
|
html: true,
|
|
78438
78483
|
doc: {
|
|
78439
78484
|
signature: "image(url, { width, height, fit, alt })",
|
|
78440
|
-
description: "Places an image with fixed size and crop mode (`cover`, `contain`, `fill`); the render-worker fetches it through its cache and blocks private hosts.",
|
|
78485
|
+
description: "Places an image with fixed size and crop mode (`cover`, `contain`, `fill`); the render-worker fetches it through its cache and blocks private hosts. `alt` says what it shows; without one the image counts as decoration and a screen reader passes over it.",
|
|
78441
78486
|
examples: {
|
|
78442
|
-
jinja2: "{{ image(product.photo, { width: 120, height: 80, fit: 'cover' }) }}",
|
|
78443
|
-
liquid: "{{ product.photo | image: width: 120, height: 80, fit: 'cover' }}",
|
|
78444
|
-
handlebars: "{{image product.photo width=120 height=80 fit='cover'}}"
|
|
78487
|
+
jinja2: "{{ image(product.photo, { width: 120, height: 80, fit: 'cover', alt: product.name }) }}",
|
|
78488
|
+
liquid: "{{ product.photo | image: width: 120, height: 80, fit: 'cover', alt: product.name }}",
|
|
78489
|
+
handlebars: "{{image product.photo width=120 height=80 fit='cover' alt=product.name}}"
|
|
78445
78490
|
},
|
|
78446
78491
|
category: "document"
|
|
78447
78492
|
},
|
|
78448
78493
|
fn: (ctx, url, options) => {
|
|
78449
78494
|
const o = asObject(options);
|
|
78450
78495
|
if (ctx.drawing)
|
|
78451
|
-
return ctx.drawing({
|
|
78496
|
+
return ctx.drawing({
|
|
78497
|
+
kind: "url",
|
|
78498
|
+
url: resolveAsset(ctx.assetBaseUrl, String(url ?? "")),
|
|
78499
|
+
width: o.width,
|
|
78500
|
+
height: o.height,
|
|
78501
|
+
alt: o.alt
|
|
78502
|
+
});
|
|
78452
78503
|
return imageMarkup(String(url ?? ""), o);
|
|
78453
78504
|
}
|
|
78454
78505
|
}
|
|
@@ -82514,7 +82565,7 @@ var encoder2 = new TextEncoder();
|
|
|
82514
82565
|
// packages/mcp/src/lib/server.ts
|
|
82515
82566
|
import { z as z3 } from "zod";
|
|
82516
82567
|
var CONVERT_LIMIT_BYTES = 20 * 1024 * 1024;
|
|
82517
|
-
var SERVER_INFO = { name: "formfeed", version: "0.3.
|
|
82568
|
+
var SERVER_INFO = { name: "formfeed", version: "0.3.13" };
|
|
82518
82569
|
var READS = {
|
|
82519
82570
|
readOnlyHint: true,
|
|
82520
82571
|
destructiveHint: false,
|
|
@@ -82549,7 +82600,10 @@ var renderSummary = (r) => ({
|
|
|
82549
82600
|
units: r.units,
|
|
82550
82601
|
environment: r.environment,
|
|
82551
82602
|
template: r.template,
|
|
82552
|
-
error: r.error
|
|
82603
|
+
error: r.error,
|
|
82604
|
+
// the validator's verdict of a render whose template declares PDF/UA-1 (plan 21): whether the
|
|
82605
|
+
// file passed, and for each failed rule what to change and in which elements
|
|
82606
|
+
...r.accessibility ? { accessibility: r.accessibility } : {}
|
|
82553
82607
|
});
|
|
82554
82608
|
function text3(data) {
|
|
82555
82609
|
return {
|
|
@@ -82559,8 +82613,15 @@ function text3(data) {
|
|
|
82559
82613
|
}
|
|
82560
82614
|
function failure(e) {
|
|
82561
82615
|
const message2 = e instanceof FormfeedError ? `${e.code}: ${e.message}` : e instanceof Error ? e.message : String(e);
|
|
82616
|
+
const verdict = e instanceof FormfeedError && e.code === "pdfua_validation_failed" ? e.problem?.["accessibility"] : void 0;
|
|
82562
82617
|
return {
|
|
82563
|
-
content: [
|
|
82618
|
+
content: [
|
|
82619
|
+
{
|
|
82620
|
+
type: "text",
|
|
82621
|
+
text: verdict ? `${message2}
|
|
82622
|
+
${JSON.stringify({ accessibility: verdict }, null, 2)}` : message2
|
|
82623
|
+
}
|
|
82624
|
+
],
|
|
82564
82625
|
isError: true
|
|
82565
82626
|
};
|
|
82566
82627
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@formfeed/mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.13",
|
|
4
4
|
"mcpName": "io.github.formfeed-dev/formfeed",
|
|
5
5
|
"description": "Model Context Protocol server for Formfeed: list templates, read data schemas, validate and render documents from AI agents.",
|
|
6
6
|
"license": "MIT",
|