@diviops/mcp-server 1.2.0 → 1.3.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/README.md CHANGED
@@ -96,7 +96,7 @@ The server connects via standard WordPress REST API and works with any environme
96
96
 
97
97
  > **WP-CLI note:** `WP_PATH` keeps the existing Local by Flywheel behavior by running `wp` directly on the host filesystem. For Docker-based environments (DDEV, wp-env, DevKinsta, WordPress Studio), set `WP_CLI_CMD` to the wrapper command instead. When `WP_CLI_CMD` is set, the server executes the wrapper from `WP_PATH` if provided, otherwise from its current working directory. The MCP server still validates the requested WP-CLI subcommand against its allowlist before executing either path.
98
98
 
99
- ## Available Tools (65)
99
+ ## Available Tools (66)
100
100
 
101
101
  ### Read (30)
102
102
  | Tool | Description |
@@ -132,7 +132,7 @@ The server connects via standard WordPress REST API and works with any environme
132
132
  | `diviops_scf_field_group_list` | List all SCF/ACF field groups (post_name = ACF key, post_title, post_status, post_modified). Queries the `acf-field-group` post type via `wp post list` (works on SCF 6.8.4+ and older ACF) |
133
133
  | `diviops_scf_field_group_get` | Fetch a single SCF/ACF field-group post by ACF key (`group_abc123` → post_name) or numeric WP post ID. For the parsed/structured field tree, use `diviops_scf_export --field-groups=<key> --stdout` |
134
134
 
135
- ### Write (33)
135
+ ### Write (34)
136
136
  | Tool | Description |
137
137
  |------|-------------|
138
138
  | `diviops_page_create` | Create a new page with optional Divi content |
@@ -163,7 +163,8 @@ The server connects via standard WordPress REST API and works with any environme
163
163
  | `diviops_variable_create_fluid_system` | Batch-emit a fluid typography + spacing + radius variable set in one call. Mirrors Divi 5.4.0's Variable Generator Modal at the algorithm level (clamp() math is identical to `diviops_variable_create`'s fluid mode) but layers profile-selectable anchors over it: `divi-default` (360→1350) matches ET's defaults, `wide` (320→1920) matches the diviops convention, `custom` takes explicit anchors. Each category is independent and optional. Typography uses modular-scale chains (named ratios `major-third`/`perfect-fifth`/`golden`/etc., or raw numbers) — h1 = largest, hN = base. Spacing/radius support `linear` or `geometric` step distributions. `dry_run: true` returns the full plan without persisting; `overwrite: false` (default) skips existing IDs. Single atomic write to the registry — mid-batch failures roll back cleanly |
164
164
  | `diviops_variable_delete` | Delete a variable by ID. Returns HTTP 409 when live references exist unless `force=true` (use `diviops_variable_scan_orphans` to find reference locations). Returns HTTP 403 for Divi's customizer-bound defaults (`gcid-primary-color`, `gcid-secondary-color`, `gcid-heading-color`, `gcid-body-color`, `gcid-link-color` — managed via WP Customizer) |
165
165
  | `diviops_canvas_create` | Create a canvas page |
166
- | `diviops_canvas_update` | Update canvas content |
166
+ | `diviops_canvas_duplicate` | Deep-copy a canvas (content + canvas-specific meta). Default copy title `<source> (Copy)` auto-suffixes on collision (Copy 2, …); explicit `title` collisions return 409. Supports `dry_run` |
167
+ | `diviops_canvas_update` | Update canvas content and/or metadata. Pass any subset of fields — `{canvas_post_id, title}` renames without touching content |
167
168
  | `diviops_canvas_delete` | Delete a canvas page |
168
169
  | `diviops_scf_export` | Export SCF schema (field groups, post types, taxonomies, options pages) as JSON to a directory under the safe-root, or to stdout. Wraps `wp scf json export` |
169
170
  | `diviops_scf_import` | Import SCF schema from a JSON file (mutates DB; idempotent — existing items are updated). Wraps `wp scf json import <file>` |
package/dist/index.js CHANGED
@@ -1376,7 +1376,7 @@ registerPluginTool("diviops_canvas_get", {
1376
1376
  };
1377
1377
  });
1378
1378
  registerPluginTool("diviops_canvas_update", {
1379
- description: "Update a canvas's content and/or metadata. Content replaces the entire canvas.",
1379
+ description: "Update a canvas's content and/or metadata. Pass any subset of fields — e.g. `{canvas_post_id, title}` to rename without touching content. `content` replaces the entire canvas when present. At least one of content/title/append_to_main/z_index is required.",
1380
1380
  inputSchema: {
1381
1381
  canvas_post_id: z.number().describe("Canvas post ID"),
1382
1382
  content: z
@@ -1410,6 +1410,34 @@ registerPluginTool("diviops_canvas_update", {
1410
1410
  ],
1411
1411
  };
1412
1412
  });
1413
+ registerPluginTool("diviops_canvas_duplicate", {
1414
+ description: "Deep-copy a canvas (post_content + canvas-specific meta: parent page, append_to_main, z_index). Source canvas untouched. Default copy title is `<source title> (Copy)` with auto-suffix on collision (Copy 2, Copy 3, …) — use this for repeat-clone workflows. Pass an explicit `title` for a deliberate name; collisions return 409 instead of silently auto-suffixing. Pass `dry_run: true` to preview without mutating.",
1415
+ inputSchema: {
1416
+ canvas_post_id: z.number().describe("Source canvas post ID"),
1417
+ title: z
1418
+ .string()
1419
+ .optional()
1420
+ .describe("Optional explicit title for the duplicate. Omit to auto-derive `<source> (Copy [N])`. Explicit collisions return 409."),
1421
+ dry_run: z
1422
+ .boolean()
1423
+ .optional()
1424
+ .default(false)
1425
+ .describe("When true, return the change plan without creating the canvas."),
1426
+ },
1427
+ }, async ({ canvas_post_id, title, dry_run }) => {
1428
+ const body = { dry_run: dry_run ?? false };
1429
+ if (title !== undefined)
1430
+ body.title = title;
1431
+ const result = await wp.request(`/canvas/duplicate/${canvas_post_id}`, {
1432
+ method: "POST",
1433
+ body,
1434
+ });
1435
+ return {
1436
+ content: [
1437
+ { type: "text", text: JSON.stringify(result) },
1438
+ ],
1439
+ };
1440
+ });
1413
1441
  registerPluginTool("diviops_canvas_delete", {
1414
1442
  description: "Delete a canvas. This permanently removes the canvas post.",
1415
1443
  inputSchema: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diviops/mcp-server",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "MCP server exposing Divi 5 Visual Builder as tools for Claude",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",