webcake-landing-mcp 1.3.0 → 1.4.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/changelog.json
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"v": "1.4.0",
|
|
4
|
+
"d": "23/07/2026",
|
|
5
|
+
"type": "Changed",
|
|
6
|
+
"en": "publish_page now reuses the page's currently-attached domain when custom_domain is omitted — mirroring the editor's publish modal, a plain…",
|
|
7
|
+
"vi": "publish_page nay tự động dùng lại domain đang gắn với trang khi bỏ trống custom_domain — giống cách modal publish của editor hoạt động, gọi…"
|
|
8
|
+
},
|
|
2
9
|
{
|
|
3
10
|
"v": "1.3.0",
|
|
4
11
|
"d": "17/07/2026",
|
|
@@ -33,12 +40,5 @@
|
|
|
33
40
|
"type": "Added",
|
|
34
41
|
"en": "create_page now sends a by_ai field in the create request body (default value \"mcp\") so the backend can stamp each MCP-generated page in its by_ai…",
|
|
35
42
|
"vi": "create_page nay gửi thêm trường by_ai trong body của request tạo trang (giá trị mặc định \"mcp\") để backend có thể đánh dấu từng trang được tạo qua…"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"v": "1.0.83",
|
|
39
|
-
"d": "16/06/2026",
|
|
40
|
-
"type": "Added",
|
|
41
|
-
"en": "The server web guide (GET /) now includes a bilingual video guides section with per-app installation walkthrough cards (Claude, Codex, Antigravity);…",
|
|
42
|
-
"vi": "Web guide của server (GET /) nay có thêm mục video hướng dẫn cài đặt song ngữ với các card theo từng ứng dụng (Claude, Codex, Antigravity); card có…"
|
|
43
43
|
}
|
|
44
44
|
]
|
|
@@ -338,6 +338,10 @@ export async function getPageSource(config, pageId) {
|
|
|
338
338
|
page_id: d.page_id,
|
|
339
339
|
name: d.name,
|
|
340
340
|
organization_id: d.organization_id ?? null,
|
|
341
|
+
// The page's currently-attached domain, when the record carries it — lets
|
|
342
|
+
// publish_page reuse it instead of dropping to a domain-less preview.
|
|
343
|
+
custom_domain: d.custom_domain ?? null,
|
|
344
|
+
custom_path: d.custom_path ?? null,
|
|
341
345
|
source: d.source,
|
|
342
346
|
};
|
|
343
347
|
}
|
|
@@ -1221,12 +1221,12 @@ export function registerPersistenceTools(server, domain) {
|
|
|
1221
1221
|
});
|
|
1222
1222
|
});
|
|
1223
1223
|
// 15) Publish page (go live) -------------------------------------------------
|
|
1224
|
-
server.tool("publish_page", "Publishes an EXISTING page LIVE via the editor's publish_html route: builds the rendered app on the Webcake build host (POST <buildBase>/render/build; prod default https://build.webcake.io, override with WEBCAKE_BUILD_BASE env / x-webcake-build-base header), then creates/updates the PagePublishedV2 record — the record ALL public serving reads. With custom_domain the page goes live at that domain (it must already point at Webcake). WITHOUT
|
|
1224
|
+
server.tool("publish_page", "Publishes an EXISTING page LIVE via the editor's publish_html route: builds the rendered app on the Webcake build host (POST <buildBase>/render/build; prod default https://build.webcake.io, override with WEBCAKE_BUILD_BASE env / x-webcake-build-base header), then creates/updates the PagePublishedV2 record — the record ALL public serving reads. With custom_domain the page goes live at that domain (it must already point at Webcake); OMIT custom_domain to reuse the page's currently-attached domain (mirrors the editor's publish modal — republishing keeps the page live at the same URL), falling back to a find_pages lookup by id. WITHOUT any domain (the page has none, or you pass custom_domain='') there is NO permanent public URL: the returned preview link (<previewBase>/preview/<page_id>) only renders for ~10 minutes after the publish, then shows 'Preview page is expired' — tell the user to attach a domain for a lasting URL. If no build host is configured or the build fails, falls back to the LEGACY source-only publish route with a warning (saves a version; nothing goes live; the page stays blank). DEFAULTS to dry_run=true (network-free: does NOT call the build host on dry_run). Needs WEBCAKE_API_BASE + WEBCAKE_JWT.", {
|
|
1225
1225
|
page_id: z.string().describe("The page id to publish (must be owned by the account)."),
|
|
1226
1226
|
custom_domain: z
|
|
1227
1227
|
.string()
|
|
1228
1228
|
.optional()
|
|
1229
|
-
.describe("Optional custom domain to serve the page at (e.g. 'shop.example.com' — must already point at Webcake).
|
|
1229
|
+
.describe("Optional custom domain to serve the page at (e.g. 'shop.example.com' — must already point at Webcake). OMIT to reuse the page's CURRENTLY-ATTACHED domain (so republishing keeps it live at the same URL, like the editor's publish modal); if the page has none it publishes domain-less (preview-host URL). Pass an empty string '' to force a domain-less publish even when the page has a domain."),
|
|
1230
1230
|
custom_path: z.string().optional().describe("Optional path under the custom domain (e.g. 'sale')."),
|
|
1231
1231
|
dry_run: z.boolean().optional().describe("Default TRUE — preview the request without sending. Does NOT call the build host. Set false to actually publish (build + publish)."),
|
|
1232
1232
|
}, { title: "Publish Webcake Page", readOnlyHint: false, destructiveHint: true, openWorldHint: true }, async ({ page_id, custom_domain, custom_path, dry_run }, extra) => {
|
|
@@ -1241,11 +1241,37 @@ export function registerPersistenceTools(server, domain) {
|
|
|
1241
1241
|
if (!res.ok || res.source == null) {
|
|
1242
1242
|
return text({ published: false, reason: "page_not_found", status: res.status, error: res.error ?? "No source on this page." });
|
|
1243
1243
|
}
|
|
1244
|
-
|
|
1244
|
+
// Resolve the domain to publish to the way the editor's publish modal does:
|
|
1245
|
+
// an explicit arg wins, otherwise reuse the page's CURRENTLY-ATTACHED domain
|
|
1246
|
+
// so a plain publish_page({ page_id }) keeps the page live at the same URL
|
|
1247
|
+
// instead of silently dropping to an ephemeral /preview. The page record from
|
|
1248
|
+
// getPageSource carries it when the backend returns it; if not, fall back to a
|
|
1249
|
+
// find_pages lookup by id (custom_path only comes from the record). Passing
|
|
1250
|
+
// custom_domain:'' explicitly opts OUT (publish domain-less on purpose).
|
|
1251
|
+
let effectiveDomain = custom_domain ?? res.custom_domain ?? undefined;
|
|
1252
|
+
let effectivePath = custom_path ?? res.custom_path ?? undefined;
|
|
1253
|
+
let domainInherited = false;
|
|
1254
|
+
if (custom_domain == null && (effectiveDomain == null || effectiveDomain === "")) {
|
|
1255
|
+
const found = await searchPages(config, { id: page_id, limit: 1 });
|
|
1256
|
+
const row = found.pages?.find((p) => `${p.id}` === `${page_id}`) ?? found.pages?.[0];
|
|
1257
|
+
if (row?.custom_domain) {
|
|
1258
|
+
effectiveDomain = row.custom_domain;
|
|
1259
|
+
domainInherited = true;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
else if (custom_domain == null && effectiveDomain) {
|
|
1263
|
+
domainInherited = true;
|
|
1264
|
+
}
|
|
1265
|
+
// Normalize an empty-string domain to "no domain" so downstream !! checks agree.
|
|
1266
|
+
if (!effectiveDomain)
|
|
1267
|
+
effectiveDomain = undefined;
|
|
1268
|
+
const opts = { customDomain: effectiveDomain, customPath: effectivePath };
|
|
1245
1269
|
const buildBase = config.buildBase;
|
|
1246
1270
|
// Only the preview window serves a domain-less publish, and only briefly.
|
|
1247
|
-
const previewExpiryNote =
|
|
1248
|
-
?
|
|
1271
|
+
const previewExpiryNote = effectiveDomain
|
|
1272
|
+
? domainInherited
|
|
1273
|
+
? `Reused the page's attached domain (${effectiveDomain}) — pass custom_domain to override, or custom_domain:'' to publish without one.`
|
|
1274
|
+
: undefined
|
|
1249
1275
|
: "No custom_domain — the page has NO permanent public URL. The preview link only renders for ~10 minutes after the publish, then shows 'Preview page is expired'. Attach a custom_domain (already pointed at Webcake) for a lasting URL.";
|
|
1250
1276
|
if (isDry) {
|
|
1251
1277
|
// dry_run is network-free — do NOT call the build host.
|
|
@@ -1253,8 +1279,8 @@ export function registerPersistenceTools(server, domain) {
|
|
|
1253
1279
|
dry_run: true,
|
|
1254
1280
|
page_id,
|
|
1255
1281
|
name: res.name,
|
|
1256
|
-
would_publish_to:
|
|
1257
|
-
? `https://${
|
|
1282
|
+
would_publish_to: effectiveDomain
|
|
1283
|
+
? `https://${effectiveDomain}${effectivePath ? `/${effectivePath}` : ""}`
|
|
1258
1284
|
: toPreviewUrl(config, `/preview/${page_id}`),
|
|
1259
1285
|
build_step: buildBase
|
|
1260
1286
|
? { would_run: true, build_host: buildBase, note: "Build host will be called on dry_run=false to produce rendered app/app_css, then the page is published live via the editor's publish_html route." }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-landing-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
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",
|