Skip to main content
Glama
vuluu2k

WebCake Landing MCP

by vuluu2k

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
WEBCAKE_ENVNoEnvironment preset: local, staging, or prod. Automatically fills in base URLs.
WEBCAKE_JWTNoYour WebCake JWT token for authentication. Required for persistence tools.
WEBCAKE_ORG_IDNoOrganization ID for multi-org accounts.
WEBCAKE_API_BASENoCustom API base URL. Overrides the environment preset.
WEBCAKE_APP_BASENoCustom app base URL. Overrides the environment preset.
WEBCAKE_BUILD_BASENoCustom build host URL for publishing. Required for publish_page to work.

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
get_generation_guideA

Returns the page-building conventions reference: output shape, the absolute-positioning coordinate system, event vocabulary, and the recommended workflow.

list_elementsA

List every supported element type, grouped by category, with a one-line summary and whether it is a container (can hold children).

get_elementA

Returns detailed usage for one element type — or for many in a single call (BATCH MODE): summary, when to use it, key specials fields, a SPARSE skeleton node (the exact shape to emit — the server hydrates omitted boilerplate), and (for common types) a filled example. Pass types: [...] to fetch a whole section's worth of element types at once (e.g. ['section','text-block','image-block','button']) — returns { elements: { [type]: details } } and saves a round-trip per type. type (single) returns the doc directly for backward compatibility.

get_page_schemaA

Returns the full JSON Schema (Draft 2020-12) of a Webcake page source object { page: [...], settings: {...} } for structural reference and validation.

new_elementA

Returns a default element node for a type in the SPARSE authoring shape (fresh id, both breakpoints' seeded styles, seeded specials). Emit elements exactly like this — fill in specials + top/left coordinates; OMIT properties/runtime/empty events/config (the server hydrates them from factory defaults on validate/persist).

new_page_skeletonA

Returns an empty but complete top-level page source { page:[], popup:[], settings:{...defaults}, options:{...}, cartConfigs:{} } matching the real editor shape. Pass desktopWidth/mobileWidth to set the canvas width (settings.width_section) up front — pick desktop 1200 for wide/multi-column/editorial pages or when cloning a reference wider than 960 (e.g. Google Stitch ~1280), else 960; then place every element's coords in that width's space.

validate_pageA

Validates a page source against the schema + semantic rules (unique ids, dangling event targets, children only on containers, missing field_name, top-level types) plus form-data bindings (duplicate field_name within one form, dangling option-event promoId / connectedSurvey / connectedForm / set_field_value targets). FIRST auto-fixes the layout defects that can be resolved deterministically (off-canvas boxes pulled on-canvas; elements below wrapped text pushed down to clear the spill — the same corrections create_page/add_section apply on save) and reports them in auto_fixed. Then returns errors (blocking — fix before persisting) and warnings (visible design defects — fix these too and re-validate to an empty list; only a demonstrably false positive may remain).

layoutA

Computes EXACT on-canvas coordinates (top/left/width/height) for a group of elements, for BOTH breakpoints, following the guide's layout math — so you NEVER hand-compute left/top (the #1 source of off-center defects) or write a script to do it. Drop the returned boxes straight into each element's responsive..styles (results are in the same order you passed items). Four modes: 'center' (one box centered on the canvas); 'row' (N boxes in a horizontally-centered row on desktop that STACK into a single mobile column — feature cards / stats / logo strip); 'grid' (N uniform cells in cols columns, block centered; stacks on mobile); 'stack' (a vertical list down the shared content column on both breakpoints). Honours the page-margin axis (content column 80..880 desktop / 20..400 mobile by default). Pure math — no env, no network. notes flags off-canvas / over-wide inputs.

search_imagesA

Searches Pexels stock photos (see https://www.pexels.com/api/) by short English subject queries. Returns hotlinkable URLs at several sizes, avg_color for matching section backgrounds, plus photographer name and attribution URL. PICK BY SIZE, NOT JUST TOPIC: each photo carries a sizes map (delivered WxH px per variant) and the response includes a size_guide — match the variant width to the slot's rendered width (hero/banner → src.large ~940px or src.large2x ~1880px retina; card/thumb → src.medium ~350px; avatar → src.tiny), because a too-small variant stretched across a big slot pixelates ('vỡ ảnh') and src.original / an oversized variant in a small card bloats the page ('nặng trang'). BATCH MODE: pass queries: [...] to fetch multiple subjects in PARALLEL — e.g. ['fresh coffee cup','barista pouring','interior cafe'] for hero + about + gallery — returns { queries: { [q]: result } } so the caller picks one image per slot in a single round-trip; default pick='best' returns only the top photo per query (compact, drop-in for specials.src), pick='all' returns the full list. query (single) returns the full result like before. Works out of the box via a shared hosted proxy; set PEXELS_API_KEY env or x-pexels-key header to use your own quota. ONLY for image slots with NO source image: when the user supplied images or the reference HTML/URL contains image URLs (ingest AST images/background_images/og_image), re-host THOSE via upload_images instead of searching stock photos.

get_icon_svgA

Resolves icon-font NAMES into real inline SVG markup via the public Iconify API — so a clone reproduces a reference's icons (esp. Google Stitch, which renders icons with a Material Symbols / Font Awesome CLASS, not an image). ingest_html/ingest_url surface those icons as block.icon "ms:" (Material Symbols) / "fa:" (Font Awesome); pass them here to get the SVG. ACCEPTS: "ms:verified", "fa:chart-line", a real Iconify id ("mdi:home"), or a bare name (assumed Material Symbols); underscores are normalized to hyphens, and Material Symbols resolve to the OUTLINED variant (the Stitch look) with a filled fallback. Returns { icons: { "": { ok, svg, iconify } } }. RENDER each svg as Webcake's native icon element — a RECTANGLE: put the svg in BOTH responsive.desktop.config.svgMask AND responsive.mobile.config.svgMask, set styles.background = the icon color, and keep the box SQUARE (width === height). The svg is only a MASK (its own fill is ignored), so the icon is BLANK without a solid styles.background; the renderer reads each breakpoint's svgMask separately (no fallback) and forces preserveAspectRatio='none' (a non-square box stretches it). No Webcake credentials needed.

render_previewA

Renders a PUBLIC URL to a PNG and returns it as an image so the model can SEE the result and compare it visually to the reference — the fidelity-check step of the clone loop (build → see → patch_page → re-check). Pass page_id to shoot a created page's preview (/preview/) or url for any public page (e.g. the reference you're cloning). full_page defaults to true (whole scrollable page). AGENT-FIRST: if YOU already have a screenshot/browser capability (a shell + headless browser, or a screenshot tool), screenshot the preview URL YOURSELF instead — it's fresh and unlimited; use this tool only when you cannot. ENGINE: zero-config via Microlink's free tier (rate-limited ~50/day PER IP, so heavy looping can hit HTTP 429 — then this returns ok:false and you should SKIP the visual check that round, not fail); a host can set RENDER_SCREENSHOT_BASE (or the x-render-screenshot-base header) to a keyed proxy, or MICROLINK_API_KEY / x-microlink-key for a higher quota. NOTE: a no-domain preview only renders for ~10 minutes after the last publish — call this promptly after create_page/publish_page, and re-publish before re-checking a stale page. TALL PAGES: pass tiles:true to get the page as a STACK of top→bottom band images (each readable at full detail) instead of one full-page image squished small — needs a self-hosted Playwright host (RENDER_SCREENSHOT_BASE); falls back to a single image otherwise.

upload_imagesA

Converts external image URLs (typically collected from ingest_html/ingest_url results), data: URIs, or LOCAL FILE PATHS from the user's computer into Webcake-hosted URLs (statics.pancake.vn) by reading/downloading each image and re-uploading it to the Webcake backend via multipart upload (200 MB backend limit). Use this whenever the page is built from a reference HTML/URL (BOTH intents — adapt AND clone), the user supplies their own image URLs, OR the user provides local image files from their machine — pass the path directly in urls; NEVER upload a user's local file to a third-party host (catbox, imgur, transfer.sh…) to obtain a URL first. The returned URLs go directly into specials.src — same as search_images results. Processes up to 20 entries per call in parallel, with a 200 MB per-image cap. UPLOAD TARGET: with Webcake credentials (WEBCAKE_JWT) AND an organization, each image is filed into that ORG's MEDIA COLLECTION (bộ sưu tập) — the same library the editor's media picker reads — so the user can re-pick it later; the response marks those entries collection:true with their asset_id. THE ORG IS REQUIRED and must be the same one the page is created in: pass organization_id, or set WEBCAKE_ORG_ID / x-webcake-org-id; it is auto-selected only when the account has exactly ONE org. With 2+ orgs and none chosen this returns ok:false + reason:'organization_required' and the org list — settle the org (ask the user) and re-call, exactly as with create_page. WITHOUT credentials it falls back to the public CDN endpoint: the URLs still work and the page still renders, but the images do NOT appear in any collection (collection:false). UPLOADS BY DEFAULT (dry_run defaults to FALSE — unlike the page-persistence tools, this touches no page data, so the default is the real upload): the call downloads/reads each entry, uploads it, and returns the images map (original URL → hosted URL); WAIT for that map before assembling the page and never fall back to a placeholder for a slot whose upload succeeded. Pass dry_run:true only to preview what would be processed without any network/filesystem activity. Use search_images instead when you need stock photos. Local file paths are only permitted when the MCP server runs locally (stdio mode); on the remote HTTP transport they are rejected per-entry.

ingest_htmlA

Parses an HTML string into a reference AST: title, description, og_image, language, and sections classified by role (header, hero, features, about, form, cta, gallery, testimonials, pricing, faq, footer, unknown) with headings, subheadings, paragraphs, images, ctas, links, form fields, and a size_hint (desktop section height in px — from the source CSS when explicit, else a content-volume estimate; set the rebuilt section's desktop height from it) — plus top colors, fonts, palette, and background_images. The palette is pulled from CSS custom-properties AND, for Tailwind-CDN pages (Google Stitch output), from the page's tailwind.config — which also yields design_tokens (the resolved spacing grid, corner radii, and type scale) so the rebuild matches the source's exact sizing and colors instead of guessing. Returns ~2-5KB (compact) or up to ~25KB (full). Use detail:'full' for clone-faithful rebuilds — it adds per-section blocks (cards/tiles/steps), li lists, gradients, images as { src, alt } objects, and widgets (the source HTML + CSS of composite mockups, to paste into ONE html-box). ABSOLUTE-CANVAS builder exports (LadiPage-family pages / Webcake-published HTML — bare positioned divs whose layout lives in per-id CSS rules) are AUTO-DETECTED and converted DETERMINISTICALLY into a ready-to-save Webcake source (folded into the response as source + clone_notes + clone_notice): a faithful 1:1 clone on the matching 420/960 canvas — save it straight to create_page instead of hand-rebuilding. The heavy per-element geometry is summarized to canvas_summary { builder, width, mobile_only, element_count, sections:[{id,height,elements}], popups }. External images in source are auto-hosted on save (no upload_images needed); clone_notes lists the few lossy approximations to patch_page afterward. Garbled Vietnamese mojibake (UTF-8 mis-read as Latin-1) is auto-repaired with a warning.

ingest_urlA

Fetches a public webpage (GET, 10s timeout, 2MB cap) and parses it into the same reference AST as ingest_html (including per-section size_hint desktop heights). Returns a warning when the page appears client-rendered (empty ) so the caller can fall back to a screenshot — Claude can analyze a screenshot natively without this tool. Does not execute JavaScript; sites built with React/Vue/Next.js may return little content. Use detail:'full' for clone-faithful rebuilds — adds CSS palette, background_images, per-section blocks, lists, images as { src, alt } objects, and widgets (source HTML + CSS of composite mockups for html-box rebuilds). ABSOLUTE-CANVAS builder exports (LadiPage-family / Webcake-published pages) are auto-detected the same way as ingest_html and converted DETERMINISTICALLY into a ready-to-save source (+ clone_notes + clone_notice, with the per-element geometry summarized to canvas_summary) — save it straight to create_page; external images auto-host on save. Image URLs in the result are the user's assets — re-host them via upload_images and reuse them for BOTH intents; use search_images only for slots with no source image.

list_organizationsA

Returns the account's Webcake organizations (id, name, is_default). The default org (type===1, usually the personal workspace) is where pages normally go. Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

create_pageA

Persists a page source to the configured Webcake backend: creates a NEW page, saves the source, then AUTO-PUBLISHES it (builds the rendered app on the build host + publishes via the editor's publish_html route) so the preview renders immediately — set publish:false to skip, and note the no-domain preview link still expires ~10 minutes after each publish (publish_page with custom_domain gives a permanent URL). A failed auto-publish never fails the create (result.publish says how to retry). Auto-fixes the deterministically-resolvable layout defects first (off-canvas boxes pulled on-canvas; elements below wrapped text pushed down to clear the spill; containers grown to fit) and reports them in auto_fixed — so the saved tree is corrected without a patch round-trip. Then validates. DEFAULTS to dry_run=true (validates, caches the source as draft_id, returns the HTTP request it WOULD send, token masked); dry_run=false to actually create. Accepts draft_id from a previous call (validation failure, dry_run, or a timed-out create) — re-runs from the cached source without re-sending the full JSON. Organization resolution on the real run (dry_run=false): (1) explicit organization_id wins; pass the string 'personal' to save without any org. (2) WEBCAKE_ORG_ID env / x-webcake-org-id header wins. (3) Otherwise list_organizations is called: 0 orgs or lookup fails → personal (no org); exactly 1 org → used automatically (result includes organization_auto_selected:true); 2+ orgs → returns ok:false with the org list and asks the caller to re-call with organization_id. Real writes need WEBCAKE_API_BASE + WEBCAKE_JWT.

list_pagesA

Lists the pages owned by the account (id, name, organization_id, updated_at), most-recent first. Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

find_pagesA

Searches the account's pages by name, domain, and/or page id so you can locate the page to edit, then pass its id to get_page → update_page/add_section. Filters are AND-combined (e.g. name='sale' + domain='shop.com'). Each result includes id, name, organization_id, custom_domain, default_domain, updated_at. With no filters it returns the most-recent pages (like list_pages). Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

get_pageA

Fetches an existing page's decoded source tree { page, popup, settings, options, cartConfigs } plus name and organization_id. By DEFAULT the source is COMPACTED: boilerplate every element shares (properties/runtime/empty events+children/per-breakpoint config + factory-default style keys) is stripped, leaving the sparse authoring shape — edit it and send it back as-is; update_page/patch_page re-hydrate from factory defaults. Pass compact:false for the raw stored tree. Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

update_pageA

Overwrites an EXISTING page's source with an edited tree (source-only; re-render in the editor for preview/publish). Validates first. DEFAULTS to dry_run=true (validates, caches the source as draft_id, previews the request, token masked); dry_run=false to actually save. Accepts draft_id from a previous call (dry_run, or a timed-out/failed update) — re-runs from the cached source without re-sending the full JSON. Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

add_sectionA

Appends one or more SECTIONS to an existing page WITHOUT re-sending the whole source — the incremental-build path that avoids large create_page payloads. The backend appends section(s) to the END of page server-side and rejects duplicate element ids, so the caller sends only the new section(s) (no whole-source get+put). DEFAULTS to dry_run=true (validates the section(s) + previews the request; caches the payload as draft_id so you never have to re-send sections between dry-run → real call); dry_run=false to actually append. On validation failure also returns a draft_id — call patch_page({ draft_id, patches, dry_run:false }) to fix ONLY the bad elements without rebuilding the batch. Needs WEBCAKE_API_BASE + WEBCAKE_JWT.

patch_pageA

Edits a page by element id WITHOUT re-sending the whole source — the surgical-edit and fix-after-error path. Targets EITHER a live page (page_id) OR a cached draft source (draft_id). Draft sources come from: (a) create_page — failed validation or timed-out network call → patched/committed tree is CREATED as a new page once valid; (b) add_section dry_run or validation/network failure → patched/committed shell is APPENDED to the stored page once valid; (c) update_page or live-page patch_page — timed-out/failed network call → re-committed via updatePageSource. Send only a list of per-element ops; the MCP loads the source, applies them, validates the WHOLE merged tree (blocks on errors), and saves. Ops: {op:'update',id,type?,specials?,styles?:{desktop?,mobile?},config?:{desktop?,mobile?},events?,properties?} (shallow-merges; op defaults to 'update'; type fixes a wrong element type; update CANNOT delete an existing/stray key — schema 'additional properties' errors need op:'replace'), {op:'replace',id,element}, {op:'remove',id}, {op:'add',parent_id,element}. EMPTY/OMITTED patches with a draft_id = commit the cached draft as-is (skip apply, still validate, then honor dry_run) — this is the RETRY PATH after a timeout. Use this to fix the elements a failed create_page/update_page/add_section reported instead of rebuilding. DEFAULTS to dry_run=true (loads + merges + validates + previews, no write); dry_run=false to save. Needs WEBCAKE_API_BASE + WEBCAKE_JWT (a draft_id sections-patch only needs creds to actually append; a page_id patch reads the live page so needs creds even on dry_run).

publish_pageA

Publishes an EXISTING page LIVE via the editor's publish_html route: builds the rendered app on the Webcake build host (POST /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 (/preview/) 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.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/vuluu2k/webcake-landing-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server