webcake-landing-mcp 1.0.80 → 1.0.81

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.
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "v": "1.0.81",
4
+ "d": "16/06/2026",
5
+ "type": "Changed",
6
+ "en": "The Playwright screenshot engine that backs render_preview's GET /api/render/screenshot route now defaults to JPEG output instead of PNG, reducing…",
7
+ "vi": "Engine chụp màn hình Playwright phục vụ route GET /api/render/screenshot của render_preview nay mặc định xuất ảnh JPEG thay vì PNG, giúp giảm kích…"
8
+ },
2
9
  {
3
10
  "v": "1.0.80",
4
11
  "d": "16/06/2026",
@@ -33,12 +40,5 @@
33
40
  "type": "Added",
34
41
  "en": "validate_page now warns when specials.custom_css sets layout or structural CSS properties (position, top, left, right, bottom, inset, width, height,…",
35
42
  "vi": "validate_page nay cảnh báo khi specials.custom_css đặt các thuộc tính CSS layout hoặc cấu trúc (position, top, left, right, bottom, inset, width,…"
36
- },
37
- {
38
- "v": "1.0.75",
39
- "d": "15/06/2026",
40
- "type": "Added",
41
- "en": "New get_icon_svg tool resolves Material Symbols (ms:<name>) and Font Awesome (fa:<name>) icon-font references to real inline SVG markup via the…",
42
- "vi": "Tool mới get_icon_svg resolve tên icon-font Material Symbols (ms:<name>) và Font Awesome (fa:<name>) thành SVG inline thực sự qua Iconify API công…"
43
43
  }
44
44
  ]
package/dist/http.js CHANGED
@@ -355,8 +355,8 @@ async function handleRenderScreenshot(req, res) {
355
355
  // 503 when the engine is absent (caller should fall back / skip), 502 otherwise.
356
356
  return sendErr(r.reason === "not_installed" ? 503 : 502, { ok: false, error: r.error });
357
357
  }
358
- res.writeHead(200, { "content-type": "image/png", "cache-control": "no-store", ...cors });
359
- return res.end(r.png);
358
+ res.writeHead(200, { "content-type": r.mimeType, "cache-control": "no-store", ...cors });
359
+ return res.end(r.data);
360
360
  }
361
361
  export async function startHttpServer(port) {
362
362
  // mcp-session-id -> live transport (each bound to its own McpServer instance).
@@ -63,6 +63,22 @@ async function getBrowser() {
63
63
  return null;
64
64
  }
65
65
  }
66
+ /**
67
+ * Output tuning (env-controlled, so the VPS operator picks the size/quality
68
+ * tradeoff). Default JPEG — a full-page landing screenshot is ~5–10× smaller as
69
+ * JPEG than PNG with no loss that matters for a layout/colour comparison, which
70
+ * shrinks the base64 the model receives. `scale` (deviceScaleFactor) renders at a
71
+ * lower pixel density to cut dimensions too; 1 = crisp, 0.5 = quarter the pixels.
72
+ */
73
+ function outputOpts() {
74
+ const fmt = (process.env.RENDER_SCREENSHOT_FORMAT ?? "jpeg").toLowerCase();
75
+ const type = fmt === "png" ? "png" : "jpeg";
76
+ const q = parseInt(process.env.RENDER_SCREENSHOT_QUALITY ?? "", 10);
77
+ const quality = type === "jpeg" ? (Number.isFinite(q) && q >= 1 && q <= 100 ? q : 72) : undefined;
78
+ const s = parseFloat(process.env.RENDER_SCREENSHOT_SCALE ?? "");
79
+ const scale = Number.isFinite(s) && s > 0 && s <= 2 ? s : 1;
80
+ return { type, quality, scale };
81
+ }
66
82
  /** Screenshot a URL with Playwright. Never throws. */
67
83
  export async function captureWithPlaywright(url, opts = {}) {
68
84
  const pw = await loadPlaywright();
@@ -88,15 +104,20 @@ export async function captureWithPlaywright(url, opts = {}) {
88
104
  }
89
105
  let ctx;
90
106
  try {
107
+ const out = outputOpts();
91
108
  ctx = await browser.newContext({
92
109
  viewport: { width: opts.width && Number.isFinite(opts.width) ? Math.round(opts.width) : 1280, height: 900 },
93
- deviceScaleFactor: 1,
110
+ deviceScaleFactor: out.scale,
94
111
  });
95
112
  const page = await ctx.newPage();
96
113
  await page.goto(url, { waitUntil: "load", timeout: 30_000 });
97
114
  await page.waitForTimeout(1200); // let webfonts/lazy images settle
98
- const png = await page.screenshot({ fullPage: opts.fullPage !== false, type: "png" });
99
- return { ok: true, png: Buffer.from(png) };
115
+ const shot = await page.screenshot({
116
+ fullPage: opts.fullPage !== false,
117
+ type: out.type,
118
+ ...(out.type === "jpeg" ? { quality: out.quality } : {}),
119
+ });
120
+ return { ok: true, data: Buffer.from(shot), mimeType: out.type === "png" ? "image/png" : "image/jpeg" };
100
121
  }
101
122
  catch (e) {
102
123
  const msg = String(e?.message ?? e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcake-landing-mcp",
3
- "version": "1.0.80",
3
+ "version": "1.0.81",
4
4
  "description": "MCP server exposing Webcake landing-page element schemas + AI usage hints, and persisting LLM-generated page sources to a Webcake backend.",
5
5
  "mcpName": "io.github.vuluu2k/webcake-landing-mcp",
6
6
  "type": "module",