webcake-landing-mcp 1.0.25 → 1.0.26
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/changelog.json +7 -7
- package/dist/http.js +28 -0
- package/dist/og.png +0 -0
- package/dist/web-guide.js +15 -7
- package/package.json +1 -1
package/dist/changelog.json
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "1.0.26",
|
|
4
|
+
"d": "07/06/2026",
|
|
5
|
+
"type": "Added",
|
|
6
|
+
"en": "The HTTP server now serves a pre-rendered 1200×630 PNG social card at GET /og.png; the guide page's og:image and twitter:image meta tags now point…",
|
|
7
|
+
"vi": "HTTP server nay phục vụ ảnh social card PNG được render sẵn 1200×630 tại GET /og.png; các meta tag og:image và twitter:image của trang hướng dẫn nay…"
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"v": "1.0.25",
|
|
4
11
|
"d": "07/06/2026",
|
|
@@ -33,12 +40,5 @@
|
|
|
33
40
|
"type": "Added",
|
|
34
41
|
"en": "The HTTP server's GET / guide page is now bilingual (vi/en): append ?lang=en to the URL to switch to English (default is Vietnamese), a language…",
|
|
35
42
|
"vi": "Trang hướng dẫn GET / của HTTP server nay hỗ trợ song ngữ (vi/en): thêm ?lang=en vào URL để chuyển sang tiếng Anh (mặc định là tiếng Việt), kèm nút…"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"v": "1.0.20",
|
|
39
|
-
"d": "07/06/2026",
|
|
40
|
-
"type": "Changed",
|
|
41
|
-
"en": "get_generation_guide now includes a Layout Archetypes block that maps seven page types (sales/COD, lead-gen/service, event/invitation, app/SaaS…",
|
|
42
|
-
"vi": "get_generation_guide now includes a Layout Archetypes block that maps seven page types (sales/COD, lead-gen/service, event/invitation, app/SaaS…"
|
|
43
43
|
}
|
|
44
44
|
]
|
package/dist/http.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
* All logging stays on stderr (console.error), same as stdio mode.
|
|
13
13
|
*/
|
|
14
14
|
import { randomUUID } from "node:crypto";
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
15
16
|
import { createServer as createHttpServer } from "node:http";
|
|
16
17
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
17
18
|
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -19,6 +20,21 @@ import { createServer } from "./server.js";
|
|
|
19
20
|
import { ICON_SVG, ICON_MIME } from "./branding.js";
|
|
20
21
|
import { guideHtml, ogImageSvg, normalizeLang } from "./web-guide.js";
|
|
21
22
|
const MCP_PATH = "/mcp";
|
|
23
|
+
// The raster social card (1200x630), pre-rendered and committed at src/og.png,
|
|
24
|
+
// mirrored to dist/og.png by copy-assets. Served at GET /og.png as the og:image —
|
|
25
|
+
// SVG OG images don't unfurl on Facebook/X/LinkedIn/Zalo. Read once, lazily.
|
|
26
|
+
let OG_PNG = null;
|
|
27
|
+
function ogImagePng() {
|
|
28
|
+
if (OG_PNG)
|
|
29
|
+
return OG_PNG;
|
|
30
|
+
try {
|
|
31
|
+
OG_PNG = readFileSync(new URL("./og.png", import.meta.url));
|
|
32
|
+
return OG_PNG;
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
22
38
|
function sendJson(res, status, body) {
|
|
23
39
|
res.writeHead(status, { "content-type": "application/json" });
|
|
24
40
|
res.end(JSON.stringify(body));
|
|
@@ -75,6 +91,18 @@ export async function startHttpServer(port) {
|
|
|
75
91
|
return res.end(ICON_SVG);
|
|
76
92
|
}
|
|
77
93
|
// Social-card image referenced by the landing page's og:image / twitter:image.
|
|
94
|
+
// PNG is the canonical og:image (unfurls everywhere); the SVG stays for clients
|
|
95
|
+
// that prefer it (Slack/Telegram/Discord) and as a fallback if og.png is absent.
|
|
96
|
+
if (req.method === "GET" && path === "/og.png") {
|
|
97
|
+
const png = ogImagePng();
|
|
98
|
+
if (png) {
|
|
99
|
+
res.writeHead(200, { "content-type": "image/png", "cache-control": "public, max-age=86400" });
|
|
100
|
+
return res.end(png);
|
|
101
|
+
}
|
|
102
|
+
// Fall back to the SVG card if the raster asset didn't ship.
|
|
103
|
+
res.writeHead(200, { "content-type": ICON_MIME, "cache-control": "public, max-age=86400" });
|
|
104
|
+
return res.end(ogImageSvg());
|
|
105
|
+
}
|
|
78
106
|
if (req.method === "GET" && path === "/og.svg") {
|
|
79
107
|
res.writeHead(200, { "content-type": ICON_MIME, "cache-control": "public, max-age=86400" });
|
|
80
108
|
return res.end(ogImageSvg());
|
package/dist/og.png
ADDED
|
Binary file
|
package/dist/web-guide.js
CHANGED
|
@@ -16,7 +16,9 @@
|
|
|
16
16
|
* It's also built to be *shareable*: a full SEO `<head>` (description, canonical,
|
|
17
17
|
* Open Graph, Twitter Card, JSON-LD for SoftwareApplication + WebSite + FAQPage)
|
|
18
18
|
* so links unfurl nicely on social/chat and the page can be indexed. The social
|
|
19
|
-
* card image is
|
|
19
|
+
* card image is a pre-rendered 1200x630 PNG at `/og.png` (committed src/og.png,
|
|
20
|
+
* regenerated by scripts/render-og.mjs from `ogImageSvg`) — PNG because SVG OG
|
|
21
|
+
* images don't unfurl on Facebook/X/LinkedIn/Zalo. `/og.svg` is still served too.
|
|
20
22
|
*
|
|
21
23
|
* Self-contained (inline CSS + the Webcake icon, no external assets/fonts/trackers)
|
|
22
24
|
* so it loads instantly and leaks nothing.
|
|
@@ -333,7 +335,8 @@ export function guideHtml(origin, lang = "vi") {
|
|
|
333
335
|
const m = META[L];
|
|
334
336
|
const faq = FAQ[L];
|
|
335
337
|
const endpoint = `${origin}/mcp`;
|
|
336
|
-
|
|
338
|
+
// PNG (not SVG) so the card unfurls on Facebook/X/LinkedIn/Zalo; served by http.ts.
|
|
339
|
+
const ogImage = `${origin}/og.png`;
|
|
337
340
|
const selfPath = L === "en" ? "?lang=en" : "/";
|
|
338
341
|
const otherLang = L === "vi" ? "en" : "vi";
|
|
339
342
|
const otherHref = otherLang === "en" ? "?lang=en" : "?lang=vi";
|
|
@@ -396,14 +399,17 @@ export function guideHtml(origin, lang = "vi") {
|
|
|
396
399
|
<meta property="og:description" content="${m.desc}">
|
|
397
400
|
<meta property="og:url" content="${canonical}">
|
|
398
401
|
<meta property="og:image" content="${ogImage}">
|
|
402
|
+
<meta property="og:image:type" content="image/png">
|
|
399
403
|
<meta property="og:image:width" content="1200">
|
|
400
404
|
<meta property="og:image:height" content="630">
|
|
405
|
+
<meta property="og:image:alt" content="${m.title}">
|
|
401
406
|
<meta property="og:locale" content="${m.locale}">
|
|
402
407
|
<meta property="og:locale:alternate" content="${META[otherLang].locale}">
|
|
403
408
|
<meta name="twitter:card" content="summary_large_image">
|
|
404
409
|
<meta name="twitter:title" content="${m.title}">
|
|
405
410
|
<meta name="twitter:description" content="${m.desc}">
|
|
406
411
|
<meta name="twitter:image" content="${ogImage}">
|
|
412
|
+
<meta name="twitter:image:alt" content="${m.title}">
|
|
407
413
|
<script type="application/ld+json">${jsonLdScript}</script>
|
|
408
414
|
<style>
|
|
409
415
|
/* Light defaults. Dark applies via OS preference OR a forced [data-theme="dark"]
|
|
@@ -751,11 +757,13 @@ export function guideHtml(origin, lang = "vi") {
|
|
|
751
757
|
</body></html>`;
|
|
752
758
|
}
|
|
753
759
|
/**
|
|
754
|
-
* The social-card
|
|
755
|
-
*
|
|
756
|
-
*
|
|
757
|
-
*
|
|
758
|
-
*
|
|
760
|
+
* The social-card source: a self-contained 1200×630 branded SVG (the size social
|
|
761
|
+
* scrapers expect) — no external fonts/assets. This is the SOURCE that
|
|
762
|
+
* scripts/render-og.mjs rasterizes into the committed src/og.png used as the
|
|
763
|
+
* canonical `og:image` / `twitter:image` (PNG unfurls on Facebook/X/LinkedIn/Zalo
|
|
764
|
+
* where SVG doesn't). Still served verbatim at `/og.svg` for SVG-friendly clients
|
|
765
|
+
* (Slack/Telegram/Discord) and as the http.ts fallback. EDIT THIS, then re-run
|
|
766
|
+
* scripts/render-og.mjs and commit the regenerated PNG.
|
|
759
767
|
*/
|
|
760
768
|
export function ogImageSvg() {
|
|
761
769
|
return `<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="630" viewBox="0 0 1200 630" fill="none" font-family="system-ui,-apple-system,Segoe UI,Roboto,sans-serif">
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-landing-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
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
|
"type": "module",
|
|
6
6
|
"bin": {
|