zola-mcp 1.1.0 → 1.1.2

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "Zola wedding planning tools for Claude Code",
10
- "version": "1.1.0"
10
+ "version": "1.1.2"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "Zola",
16
16
  "source": "./",
17
17
  "description": "Zola wedding planning tools for Claude — vendors, budget, guests, seating, events, registry, inquiries, and more via MCP",
18
- "version": "1.1.0",
18
+ "version": "1.1.2",
19
19
  "author": {
20
20
  "name": "Chris Chall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "zola",
3
3
  "displayName": "Zola",
4
- "version": "1.1.0",
4
+ "version": "1.1.2",
5
5
  "description": "Zola wedding planning tools for Claude — vendors, budget, guests, seating, events, registry, inquiries, and more via MCP",
6
6
  "author": {
7
7
  "name": "Chris Chall",
package/dist/bundle.js CHANGED
@@ -31562,11 +31562,48 @@ async function updateCurrentTheme(args) {
31562
31562
  );
31563
31563
  return jsonResult(response.data);
31564
31564
  }
31565
+ var ALLOWED_BODY_FONT_FAMILY_IDS = [68, 198];
31566
+ var WEB_API_ONLY_FIELDS = ["header_color", "nav_font_color"];
31565
31567
  async function updateWebsiteCustomization(args) {
31568
+ for (const field of WEB_API_ONLY_FIELDS) {
31569
+ if (args[field] !== void 0) {
31570
+ throw new Error(
31571
+ `${field} is not writable via the mobile-api endpoint this MCP uses. The Zola web UI sets it via POST www.zola.com/web-api/v1/websiteCustomization/update (cookie + CSRF auth), which this MCP does not yet support. For now, change it in the Zola web UI under Website > Design.`
31572
+ );
31573
+ }
31574
+ }
31575
+ if (args.body_font_family_id !== void 0 && !ALLOWED_BODY_FONT_FAMILY_IDS.includes(args.body_font_family_id)) {
31576
+ throw new Error(
31577
+ `body_font_family_id must be one of [${ALLOWED_BODY_FONT_FAMILY_IDS.join(
31578
+ ", "
31579
+ )}] (68=Libre Baskerville, 198=Circular). The header font catalog does not apply to the body font.`
31580
+ );
31581
+ }
31582
+ let preserved;
31583
+ if (args.header_font_family_id !== void 0) {
31584
+ const current = await client.requestMobile(
31585
+ "GET",
31586
+ "/v3/websites/website-customizations/context"
31587
+ );
31588
+ preserved = current.data.current_style_customizations;
31589
+ }
31566
31590
  const body = {};
31591
+ if (preserved) {
31592
+ if (preserved.accent_color != null) body.accent_color = preserved.accent_color;
31593
+ if (preserved.background_color != null) body.background_color = preserved.background_color;
31594
+ if (preserved.body?.color != null) body.body_font = { color: preserved.body.color };
31595
+ if (preserved.navigation_customization?.background_color != null) {
31596
+ body.navigation_customization = {
31597
+ background_color: preserved.navigation_customization.background_color
31598
+ };
31599
+ }
31600
+ }
31567
31601
  if (args.accent_color !== void 0) body.accent_color = args.accent_color;
31568
31602
  if (args.background_color !== void 0) body.background_color = args.background_color;
31569
- if (args.body_font_color !== void 0) body.body_font = { color: args.body_font_color };
31603
+ if (args.body_font_color !== void 0) {
31604
+ const existing = body.body_font ?? {};
31605
+ body.body_font = { ...existing, color: args.body_font_color };
31606
+ }
31570
31607
  if (args.navigation_background_color !== void 0) {
31571
31608
  body.navigation_customization = { background_color: args.navigation_background_color };
31572
31609
  }
@@ -31611,14 +31648,16 @@ function registerWebsiteThemeTools(server2) {
31611
31648
  annotations: { destructiveHint: false }
31612
31649
  }, updateCurrentTheme);
31613
31650
  server2.registerTool("update_website_customization", {
31614
- description: "Update website colors and fonts. Provide only what changes \u2014 accepts a partial update. Colors are 6-char hex without #.",
31651
+ description: "Update website colors and fonts. Provide only what changes. Colors are 6-char hex without #. Note: when header_font_family_id changes, the wrapper auto-fetches current state and re-sends all active colors to defend against a Zola partial-update wipe bug. body_font_family_id is restricted to [68, 198]. header_color and nav_font_color exist on Zola's web-api endpoint but are NOT writable via the mobile-api this MCP uses \u2014 change them in the Zola web UI for now.",
31615
31652
  inputSchema: {
31616
31653
  accent_color: external_exports3.string().optional().describe("6-char hex (no #)"),
31617
31654
  background_color: external_exports3.string().optional(),
31618
31655
  body_font_color: external_exports3.string().optional(),
31619
31656
  navigation_background_color: external_exports3.string().optional(),
31620
31657
  header_font_family_id: external_exports3.number().optional().describe("Font family ID \u2014 call get_website_customizations to see available font_family_ids"),
31621
- body_font_family_id: external_exports3.number().optional()
31658
+ body_font_family_id: external_exports3.number().optional().describe("Restricted to 68 (Libre Baskerville) or 198 (Circular). Other IDs return a generic API error."),
31659
+ header_color: external_exports3.string().optional().describe("Writable only via Zola's web-api (cookie+CSRF), not the mobile-api this MCP uses. Passing this throws."),
31660
+ nav_font_color: external_exports3.string().optional().describe("Writable only via Zola's web-api (cookie+CSRF), not the mobile-api this MCP uses. Passing this throws.")
31622
31661
  },
31623
31662
  annotations: { destructiveHint: false }
31624
31663
  }, updateWebsiteCustomization);
@@ -31752,7 +31791,7 @@ function registerRegistryItemTools(server2) {
31752
31791
  // src/index.ts
31753
31792
  var server = new McpServer({
31754
31793
  name: "zola-mcp",
31755
- version: "1.1.0"
31794
+ version: "1.1.2"
31756
31795
  });
31757
31796
  registerVendorTools(server);
31758
31797
  registerBudgetTools(server);
package/dist/index.js CHANGED
@@ -13,7 +13,7 @@ import { registerWebsiteThemeTools } from './tools/website-theme.js';
13
13
  import { registerRegistryItemTools } from './tools/registry-items.js';
14
14
  const server = new McpServer({
15
15
  name: 'zola-mcp',
16
- version: '1.1.0',
16
+ version: '1.1.2',
17
17
  });
18
18
  registerVendorTools(server);
19
19
  registerBudgetTools(server);
@@ -26,14 +26,57 @@ export async function updateCurrentTheme(args) {
26
26
  const response = await client.requestMobile('PUT', '/v3/themes/current', body);
27
27
  return jsonResult(response.data);
28
28
  }
29
+ // Only these two font_family_id values work for the body font; sending any other
30
+ // (even ones valid for the header) yields a generic "tool execution failed" error.
31
+ // See docs/zola-api-quirks.md for the empirical evidence.
32
+ const ALLOWED_BODY_FONT_FAMILY_IDS = [68, 198];
33
+ // These fields exist on the web-api endpoint (POST www.zola.com/web-api/v1/
34
+ // websiteCustomization/update) but NOT on the mobile-api endpoint this MCP
35
+ // currently uses. Until web-api support is added, callers passing these get a
36
+ // clear pointer at the only paths that work today.
37
+ const WEB_API_ONLY_FIELDS = ['header_color', 'nav_font_color'];
29
38
  export async function updateWebsiteCustomization(args) {
39
+ for (const field of WEB_API_ONLY_FIELDS) {
40
+ if (args[field] !== undefined) {
41
+ throw new Error(`${field} is not writable via the mobile-api endpoint this MCP uses. ` +
42
+ `The Zola web UI sets it via POST www.zola.com/web-api/v1/websiteCustomization/update ` +
43
+ `(cookie + CSRF auth), which this MCP does not yet support. ` +
44
+ `For now, change it in the Zola web UI under Website > Design.`);
45
+ }
46
+ }
47
+ if (args.body_font_family_id !== undefined &&
48
+ !ALLOWED_BODY_FONT_FAMILY_IDS.includes(args.body_font_family_id)) {
49
+ throw new Error(`body_font_family_id must be one of [${ALLOWED_BODY_FONT_FAMILY_IDS.join(', ')}] (68=Libre Baskerville, 198=Circular). The header font catalog does not apply to the body font.`);
50
+ }
51
+ // Partial-update wipe defence: when header_font_family_id changes the server
52
+ // resets every other active customization to null unless we resend them.
53
+ let preserved;
54
+ if (args.header_font_family_id !== undefined) {
55
+ const current = await client.requestMobile('GET', '/v3/websites/website-customizations/context');
56
+ preserved = current.data.current_style_customizations;
57
+ }
30
58
  const body = {};
59
+ if (preserved) {
60
+ if (preserved.accent_color != null)
61
+ body.accent_color = preserved.accent_color;
62
+ if (preserved.background_color != null)
63
+ body.background_color = preserved.background_color;
64
+ if (preserved.body?.color != null)
65
+ body.body_font = { color: preserved.body.color };
66
+ if (preserved.navigation_customization?.background_color != null) {
67
+ body.navigation_customization = {
68
+ background_color: preserved.navigation_customization.background_color,
69
+ };
70
+ }
71
+ }
31
72
  if (args.accent_color !== undefined)
32
73
  body.accent_color = args.accent_color;
33
74
  if (args.background_color !== undefined)
34
75
  body.background_color = args.background_color;
35
- if (args.body_font_color !== undefined)
36
- body.body_font = { color: args.body_font_color };
76
+ if (args.body_font_color !== undefined) {
77
+ const existing = body.body_font ?? {};
78
+ body.body_font = { ...existing, color: args.body_font_color };
79
+ }
37
80
  if (args.navigation_background_color !== undefined) {
38
81
  body.navigation_customization = { background_color: args.navigation_background_color };
39
82
  }
@@ -74,14 +117,20 @@ export function registerWebsiteThemeTools(server) {
74
117
  annotations: { destructiveHint: false },
75
118
  }, updateCurrentTheme);
76
119
  server.registerTool('update_website_customization', {
77
- description: 'Update website colors and fonts. Provide only what changes — accepts a partial update. Colors are 6-char hex without #.',
120
+ description: 'Update website colors and fonts. Provide only what changes. Colors are 6-char hex without #. ' +
121
+ 'Note: when header_font_family_id changes, the wrapper auto-fetches current state and re-sends all active colors ' +
122
+ 'to defend against a Zola partial-update wipe bug. body_font_family_id is restricted to [68, 198]. ' +
123
+ 'header_color and nav_font_color exist on Zola\'s web-api endpoint but are NOT writable via the mobile-api ' +
124
+ 'this MCP uses — change them in the Zola web UI for now.',
78
125
  inputSchema: {
79
126
  accent_color: z.string().optional().describe('6-char hex (no #)'),
80
127
  background_color: z.string().optional(),
81
128
  body_font_color: z.string().optional(),
82
129
  navigation_background_color: z.string().optional(),
83
130
  header_font_family_id: z.number().optional().describe('Font family ID — call get_website_customizations to see available font_family_ids'),
84
- body_font_family_id: z.number().optional(),
131
+ body_font_family_id: z.number().optional().describe('Restricted to 68 (Libre Baskerville) or 198 (Circular). Other IDs return a generic API error.'),
132
+ header_color: z.string().optional().describe('Writable only via Zola\'s web-api (cookie+CSRF), not the mobile-api this MCP uses. Passing this throws.'),
133
+ nav_font_color: z.string().optional().describe('Writable only via Zola\'s web-api (cookie+CSRF), not the mobile-api this MCP uses. Passing this throws.'),
85
134
  },
86
135
  annotations: { destructiveHint: false },
87
136
  }, updateWebsiteCustomization);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zola-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "mcpName": "io.github.chrischall/zola-mcp",
5
5
  "description": "Zola wedding MCP server for Claude",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/chrischall/zola-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.1.0",
9
+ "version": "1.1.2",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "zola-mcp",
14
- "version": "1.1.0",
14
+ "version": "1.1.2",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },