@diviops/mcp-server 1.5.21 → 1.5.24
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 +5 -2
- package/dist/index.js +47 -2
- package/dist/schema-route.d.ts +2 -0
- package/dist/schema-route.js +7 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,11 +41,13 @@ claude mcp add diviops-mcp \
|
|
|
41
41
|
--env WP_URL=http://your-site.local \
|
|
42
42
|
--env WP_USER=your-wp-username \
|
|
43
43
|
--env WP_APP_PASSWORD=xxxxXXXXxxxxXXXXxxxxXXXX \
|
|
44
|
-
-- npx @diviops/mcp-server
|
|
44
|
+
-- npx -y --package @diviops/mcp-server diviops-mcp
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
Then ask Claude: **"List the pages on my site."** Claude calls `diviops_page_list` and renders the result. You're authoring with the suite.
|
|
48
48
|
|
|
49
|
+
For Claude Desktop JSON, use `"command": "npx"` with args `["-y", "--package", "@diviops/mcp-server", "diviops-mcp"]`. The package also ships `diviops-preset`, so the explicit package/bin form is required; `npx @diviops/mcp-server` cannot reliably infer which bin to run.
|
|
50
|
+
|
|
49
51
|
For a deeper walkthrough (containerized environments, WP-CLI configuration, troubleshooting installation), see [setup-guide.md](../docs/setup-guide.md).
|
|
50
52
|
|
|
51
53
|
## Example workflow
|
|
@@ -64,7 +66,7 @@ The skill enforces the Divi block format, the design system, and the response co
|
|
|
64
66
|
|
|
65
67
|
## Tools at a glance
|
|
66
68
|
|
|
67
|
-
The server exposes **
|
|
69
|
+
The server exposes **74 always-on tools** across the categories below. Each category links to representative tools; the full table lives in [server-reference.md](../docs/server-reference.md).
|
|
68
70
|
|
|
69
71
|
| Category | Use case | Tool prefixes |
|
|
70
72
|
|----------|----------|---------------|
|
|
@@ -219,6 +221,7 @@ The server connects via standard WordPress REST API and works with any environme
|
|
|
219
221
|
Common quick fixes — full reference in [troubleshooting.md](../docs/troubleshooting.md).
|
|
220
222
|
|
|
221
223
|
- **"Missing required environment variable(s)"** — ensure `WP_URL`, `WP_USER`, `WP_APP_PASSWORD` are all set on `claude mcp add`.
|
|
224
|
+
- **`npx @diviops/mcp-server` fails with "could not determine executable to run"** — use `npx -y --package @diviops/mcp-server diviops-mcp`; this explicitly selects the MCP server bin.
|
|
222
225
|
- **"Connection failed"** — verify the plugin is active by visiting `{WP_URL}/wp-json/diviops/v1/schema/settings`; test the credentials with `curl -u "user:pass" …`.
|
|
223
226
|
- **"This tool requires plugin capability"** — the plugin doesn't advertise the capability this tool needs. Update the plugin to the latest release.
|
|
224
227
|
- **Preset edits not visible on the frontend** — Divi serves frontend CSS from `wp-content/et-cache/{post_id}/`, which `wp cache flush` doesn't touch. Use `diviops_meta_flush_cache` after preset writes.
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ import { WPClient } from "./wp-client.js";
|
|
|
15
15
|
import { MissingCapabilityError } from "./compatibility.js";
|
|
16
16
|
import { ErrorCodes, envelopeMap, recordIdempotent, serializeEnvelope, withCode, wrapResponse, } from "./envelope.js";
|
|
17
17
|
import { optimizeSchema } from "./schema-optimizer.js";
|
|
18
|
+
import { schemaModuleRoute } from "./schema-route.js";
|
|
18
19
|
import { createWpCli } from "./wp-cli.js";
|
|
19
20
|
import { findForeignVarRefs, scanAttrsForForeignVarRefs, isolationErrorResult, } from "./validate-attrs.js";
|
|
20
21
|
import { readFileSync, readdirSync } from "fs";
|
|
@@ -347,7 +348,7 @@ registerPluginTool("diviops_schema_get_module", {
|
|
|
347
348
|
content: [{ type: "text", text: serializeEnvelope(failure, "diviops_schema_get_module") }],
|
|
348
349
|
};
|
|
349
350
|
}
|
|
350
|
-
const result = await wp.requestEnveloped(
|
|
351
|
+
const result = await wp.requestEnveloped(schemaModuleRoute(module_name));
|
|
351
352
|
const projected = envelopeMap(result, (data) => raw ? data : optimizeSchema(data));
|
|
352
353
|
return {
|
|
353
354
|
content: [
|
|
@@ -1773,6 +1774,50 @@ registerPluginTool("diviops_tb_layout_update", {
|
|
|
1773
1774
|
],
|
|
1774
1775
|
};
|
|
1775
1776
|
});
|
|
1777
|
+
registerPluginTool("diviops_tb_layout_block_insert", {
|
|
1778
|
+
description: "Insert one or more serialized Divi blocks into an existing Theme Builder layout without replacing the whole layout. Target a unique parent with `parent_selector` (for example `divi/group[adminLabel=\"Legal Col\"]`, or `divi/group` only when it is unique) or an explicit zero-based `parent_path` from the parsed block tree such as `0.1.2`. `position=append|prepend` inserts as children of the target block; `position=before|after` inserts beside the target within its parent. Ambiguous selectors return ok:false with code 'invalid_input'; missing targets return 'not_found'. The route parses and validates the inserted blocks, rejects malformed pseudo-escapes such as bare `u003c`, validates the final serialized layout before saving, and returns a no-op when the exact requested block sequence already exists at the insertion point." +
|
|
1779
|
+
DRY_RUN_DESC_SUFFIX,
|
|
1780
|
+
inputSchema: {
|
|
1781
|
+
layout_id: z.number().int().describe("Theme Builder layout post ID to mutate"),
|
|
1782
|
+
parent_selector: z
|
|
1783
|
+
.string()
|
|
1784
|
+
.optional()
|
|
1785
|
+
.describe('Unique selector such as `divi/group[adminLabel="Legal Col"]` or `divi/column`. Provide exactly one of parent_selector or parent_path.'),
|
|
1786
|
+
parent_path: z
|
|
1787
|
+
.string()
|
|
1788
|
+
.optional()
|
|
1789
|
+
.describe('Zero-based parsed-tree path such as `0`, `0.1`, or `0.1.2`. Provide exactly one of parent_selector or parent_path.'),
|
|
1790
|
+
position: z
|
|
1791
|
+
.enum(["append", "prepend", "before", "after"])
|
|
1792
|
+
.optional()
|
|
1793
|
+
.default("append")
|
|
1794
|
+
.describe("Where to insert relative to the target block."),
|
|
1795
|
+
content: z.string().describe("One or more serialized Divi blocks to insert"),
|
|
1796
|
+
dry_run: DRY_RUN_FIELD,
|
|
1797
|
+
},
|
|
1798
|
+
annotations: { idempotentHint: false },
|
|
1799
|
+
_meta: { idempotent: "conditional" },
|
|
1800
|
+
}, async ({ layout_id, parent_selector, parent_path, position, content, dry_run }) => {
|
|
1801
|
+
const body = {
|
|
1802
|
+
content,
|
|
1803
|
+
position: position ?? "append",
|
|
1804
|
+
};
|
|
1805
|
+
if (parent_selector !== undefined)
|
|
1806
|
+
body.parent_selector = parent_selector;
|
|
1807
|
+
if (parent_path !== undefined)
|
|
1808
|
+
body.parent_path = parent_path;
|
|
1809
|
+
if (dry_run)
|
|
1810
|
+
body.dry_run = true;
|
|
1811
|
+
const result = await wp.requestEnveloped(`/theme-builder/layout/block-insert/${layout_id}`, {
|
|
1812
|
+
method: "POST",
|
|
1813
|
+
body,
|
|
1814
|
+
});
|
|
1815
|
+
return {
|
|
1816
|
+
content: [
|
|
1817
|
+
{ type: "text", text: serializeEnvelope(result, "diviops_tb_layout_block_insert") },
|
|
1818
|
+
],
|
|
1819
|
+
};
|
|
1820
|
+
});
|
|
1776
1821
|
registerPluginTool("diviops_tb_template_create", {
|
|
1777
1822
|
description: "Create a Theme Builder template with custom header and/or footer. Automatically creates layout posts, sets conditions, and links to Theme Builder. Pass condition=\"default\" (case-insensitive) or an empty string to register the template as the catch-all Default Website Template — the route writes the `_et_default = '1'` flag with an empty `_et_use_on`, matching the meta shape Divi's TB router gates the default route on; any other condition string lands in `_et_use_on` unchanged. Default Website Template is a singleton scoped to the active Theme Builder master: if the active master's `_et_template` linked list already names an et_template carrying `_et_default = '1'` (regardless of `_et_enabled` status — the router resolves by linked-list position before checking the enable-gate, so a disabled existing default linked ahead of the new one would still shadow it), the route rejects with code `tb_template.default_already_exists` (HTTP 409) and `error.data.existing_default_id` + `error.data.master_post_id`. Templates outside the active master's linked list (orphan defaults, library-cloned-master defaults) cannot shadow the router's pick and DO NOT block creation. Caller resolves a real conflict by trashing the existing default (diviops_tb_template_trash) or pinning this template to a specific condition; the route never silently flips the existing default's flag or proceeds with non-deterministic router state. If the Theme Builder master post is missing (fresh substrate that never opened Divi → Theme Builder in WP Admin), the route auto-bootstraps one with the same shape Divi creates on first admin visit and returns `data.master_post_bootstrapped: true` so callers can audit the side-effect. Returns the standardized envelope { ok, data?, error: { code, message, hint? } }; failures during master-post bootstrap or template/layout insert surface the underlying WP_Error code (commonly `db_insert_error`, `db_update_error`, or other slugs from the WordPress vocabulary), not a generic `wp_error` — branch on `error.code` against the WP slug, not against a hard-coded string. The literal `wp_error` slug only surfaces when the upstream WP_Error has an empty code." +
|
|
1778
1823
|
DRY_RUN_DESC_SUFFIX,
|
|
@@ -2046,7 +2091,7 @@ registerLocalTool("diviops_meta_wp_cli", {
|
|
|
2046
2091
|
}, async ({ command }) => {
|
|
2047
2092
|
const response = await wrapResponse(async () => {
|
|
2048
2093
|
if (!wpCli) {
|
|
2049
|
-
withCode("meta_wp_cli.not_configured", "WP-CLI not configured.", 'Set the WP_PATH environment variable to your WordPress installation path. Example: claude mcp add diviops-mcp --
|
|
2094
|
+
withCode("meta_wp_cli.not_configured", "WP-CLI not configured.", 'Set the WP_PATH environment variable to your WordPress installation path. Example: claude mcp add diviops-mcp --env WP_URL=http://site.local --env WP_USER=admin --env WP_APP_PASSWORD=xxxx --env "WP_PATH=/Users/you/Local Sites/your-site/app/public" -- npx -y --package @diviops/mcp-server diviops-mcp. Local site ID is auto-detected from WP_PATH; set LOCAL_SITE_ID explicitly if needed.');
|
|
2050
2095
|
}
|
|
2051
2096
|
const result = await wpCli.run(command);
|
|
2052
2097
|
if (!result.success) {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function normalizeSchemaModuleName(moduleName) {
|
|
2
|
+
const trimmed = moduleName.trim();
|
|
3
|
+
return trimmed.startsWith("divi/") ? trimmed.slice("divi/".length) : trimmed;
|
|
4
|
+
}
|
|
5
|
+
export function schemaModuleRoute(moduleName) {
|
|
6
|
+
return `/schema/module/${encodeURIComponent(normalizeSchemaModuleName(moduleName))}`;
|
|
7
|
+
}
|