webcake-storefront-mcp 1.11.0 → 1.11.1

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/api.js CHANGED
@@ -76,11 +76,12 @@ export class WebcakeCmsApi {
76
76
  createSite(params) {
77
77
  return this.request("POST", `/api/v1/dashboard/site/create`, { body: params, timeout: 60000 });
78
78
  }
79
- /** Duplicate an existing site (its settings AND all pages/page-sources) into a NEW site
80
- * owned by the current account. Used to spin up a site FROM a marketplace template
81
- * (pass the template's source site id). Body: { site_id (source), name, slug? }. */
82
- duplicateSite(params) {
83
- return this.request("POST", `/api/v1/dashboard/site/duplicate`, { body: params, timeout: 90000 });
79
+ /** Create a NEW site from a marketplace TEMPLATE by its theme id — the dedicated
80
+ * "use this template" API. Clones the template's pages, global sections, cart, popups,
81
+ * styles and fonts into a fresh account-owned site. Body: { id: <theme_id>, name, slug }.
82
+ * Returns { data: { site: { id, ... } } }. (403 if the free 4-site quota is reached, prod.) */
83
+ importStoreToTheme(params) {
84
+ return this.request("POST", `/api/v1/dashboard/site/import_store_to_theme`, { body: params, timeout: 120000 });
84
85
  }
85
86
  getSiteInfo() {
86
87
  return this.request("GET", `/api/v1/site/${this.siteId}/`);
@@ -1,4 +1,11 @@
1
1
  [
2
+ {
3
+ "v": "1.11.1",
4
+ "d": "24/06/2026",
5
+ "type": "Fixed",
6
+ "en": "create_site_from_template now calls the dedicated import_store_to_theme API instead of the generic site-duplicate endpoint, correctly cloning the…",
7
+ "vi": "create_site_from_template nay gọi đúng API import_store_to_theme thay vì endpoint nhân bản site thông thường, giúp clone đầy đủ các trang, global…"
8
+ },
2
9
  {
3
10
  "v": "1.11.0",
4
11
  "d": "24/06/2026",
@@ -33,12 +40,5 @@
33
40
  "type": "Changed",
34
41
  "en": "The web guide landing page (served via the serve command) is reframed to lead on full-storefront creation: the hero, meta description, \"What you…",
35
42
  "vi": "Trang web guide (phục vụ qua lệnh serve) được viết lại để làm nổi bật việc xây dựng toàn bộ cửa hàng: hero, meta description, thư viện \"Bạn dựng…"
36
- },
37
- {
38
- "v": "1.6.0",
39
- "d": "23/06/2026",
40
- "type": "Added",
41
- "en": "get_element now returns an attributes field with a curated per-element reference covering the meaningful specials, config, events, and bindings keys…",
42
- "vi": "get_element nay trả về trường attributes chứa tài liệu tham chiếu theo từng loại element, bao gồm các key có ý nghĩa của specials, config, events và…"
43
43
  }
44
44
  ]
@@ -52,7 +52,6 @@ async function getThemeCatalog(force = false) {
52
52
  preview_url: t.preview_url || "",
53
53
  thumbnail: t.thumbnail || "",
54
54
  categories: (t.categories || []).map((c) => c.name).filter(Boolean),
55
- site_id: (t.site && t.site.id) || undefined,
56
55
  });
57
56
  }
58
57
  if (themes.length < limit)
@@ -146,7 +145,6 @@ export function registerSiteStyleTools(server, api, handle) {
146
145
  const desc = parseThemeDescription(te && te.description);
147
146
  return {
148
147
  theme_id: themeId,
149
- template_site_id: info.site_id || null, // pass to create_site_from_template
150
148
  score: typeof score === "number" ? Number(score.toFixed(4)) : null,
151
149
  name: info.name || null,
152
150
  preview_url: info.preview_url || null,
@@ -163,50 +161,31 @@ export function registerSiteStyleTools(server, api, handle) {
163
161
  hint: "Pick one and call create_site_from_template with its theme_id (or template_site_id) to clone it into a new editable site.",
164
162
  };
165
163
  }));
166
- server.tool("create_site_from_template", `Create a NEW site by CLONING a marketplace template (all its pages + settings), so the
167
- customer starts from a finished design and then edits it. Resolve a template with
168
- semantic_search_themes / list_template_themes first, then pass its theme_id (or
169
- template_site_id). After cloning, switch to the new site and edit layout/content with
170
- update_page_element(s), colours/typography with the site-style tools, and republish.`, {
164
+ server.tool("create_site_from_template", `Create a NEW site from a marketplace TEMPLATE (the dedicated "use this template" API).
165
+ Clones the template's pages, global sections, cart, popups, styles and fonts into a fresh
166
+ site. Pick a template with semantic_search_themes / list_template_themes, then pass its
167
+ theme_id here. Switches to the new site so you can immediately edit layout/content with
168
+ update_page_element(s), colours/fonts via the site-style tools, then publish_site.`, {
171
169
  name: z.string().describe("Name for the new site"),
172
- theme_id: z.string().optional().describe("Marketplace theme id (from semantic_search_themes / list_template_themes)"),
173
- template_site_id: z.string().optional().describe("The template's source site id (alternative to theme_id; semantic_search_themes returns it as template_site_id)"),
170
+ theme_id: z.string().describe("Marketplace theme id (from semantic_search_themes / list_template_themes)"),
174
171
  slug: z.string().optional().describe("URL-safe slug for the new site (auto-generated if omitted)"),
175
- switch_to: z.boolean().default(true).describe("Switch the session to the new site after cloning (saved for next session)"),
176
- }, ({ name, theme_id, template_site_id, slug, switch_to }) => handle(async () => {
177
- // Resolve the template's source site id.
178
- let sourceSiteId = template_site_id;
179
- if (!sourceSiteId && theme_id) {
180
- const catalog = await getThemeCatalog().catch(() => new Map());
181
- sourceSiteId = catalog.get(theme_id)?.site_id;
182
- }
183
- if (!sourceSiteId) {
184
- throw new Error("Could not resolve the template's source site. Pass template_site_id, or a theme_id that exists in the marketplace (list_template_themes / semantic_search_themes).");
185
- }
186
- // The duplicate endpoint returns success-only (no id), so snapshot the site list
187
- // first, clone, then resolve the new site by diff.
188
- const listIds = async () => {
189
- const r = await api.listMySites({ page: 1, limit: 100 }).catch(() => null);
190
- const arr = r?.data?.sites || r?.data || [];
191
- return Array.isArray(arr) ? arr : [];
192
- };
193
- const before = await listIds();
194
- const beforeIds = new Set(before.map((s) => s.id));
172
+ switch_to: z.boolean().default(true).describe("Switch the session to the new site after creating it (saved for next session)"),
173
+ }, ({ name, theme_id, slug, switch_to }) => handle(async () => {
174
+ let res;
195
175
  try {
196
- await api.duplicateSite({ site_id: sourceSiteId, name, ...(slug ? { slug } : {}) });
176
+ res = await api.importStoreToTheme({ id: theme_id, name, ...(slug ? { slug } : {}) });
197
177
  }
198
178
  catch (e) {
199
179
  const msg = e instanceof Error ? e.message : String(e);
200
180
  if (msg.includes("403"))
201
181
  throw new Error("Cannot create site: account site quota reached (free plan allows up to 4 sites).");
202
- throw new Error(`Cloning the template failed: ${msg}`);
182
+ throw new Error(`Creating the site from the template failed: ${msg}. Check the theme_id exists (list_template_themes / semantic_search_themes).`);
203
183
  }
204
- const after = await listIds();
205
- const fresh = after.filter((s) => !beforeIds.has(s.id));
206
- const newSite = fresh.find((s) => s.name === name) || fresh[0];
184
+ const data = res?.data || res;
185
+ const newSite = data?.site || data?.new_site || data;
207
186
  const newId = newSite?.id;
208
187
  if (!newId)
209
- throw new Error("Template was cloned but the new site could not be located in your site list — check list_my_sites.");
188
+ throw new Error("Site created from template but no id was returned.");
210
189
  let switched = false;
211
190
  let previewUrl = null;
212
191
  const previousSiteId = api.siteId;
@@ -221,11 +200,11 @@ update_page_element(s), colours/typography with the site-style tools, and republ
221
200
  success: true,
222
201
  site_id: newId,
223
202
  name: newSite?.name || name,
224
- from_template: { theme_id: theme_id || null, source_site_id: sourceSiteId },
203
+ from_template: theme_id,
225
204
  switched,
226
205
  ...(switched ? { current_site_id: api.siteId, previous_site_id: previousSiteId } : {}),
227
206
  preview_url: previewUrl,
228
- next_step: "Site cloned with all template pages. Edit content with search_page_elements + update_page_element(s), change colours/fonts via list_themes/site-style, then publish_site.",
207
+ next_step: "Site created from the template (pages, sections, popups, styles, fonts). Edit content with search_page_elements + update_page_element(s), colours/fonts via list_themes/site-style, then publish_site.",
229
208
  };
230
209
  }));
231
210
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webcake-storefront-mcp",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "description": "MCP server for the WebCake/StoreCake storefront builder — page CRUD, page authoring, products, orders, and more",
5
5
  "mcpName": "io.github.vuluu2k/webcake-storefront-mcp",
6
6
  "license": "MIT",