@yashwant.dharmdas/elementor-mcp 3.0.0 → 3.2.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/dist/index.js +147 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -939,6 +939,153 @@ function createMcpServer(sites) {
|
|
|
939
939
|
return { content: [{ type: "text", text: `Error: ${e.response?.data?.message || e.message}` }], isError: true };
|
|
940
940
|
}
|
|
941
941
|
});
|
|
942
|
+
// ── Group 8: Page Creation & Publishing ──────────────────────────────────
|
|
943
|
+
server.tool("create-page", "Create a new WordPress page, optionally publish it immediately, and enable the Elementor editor. Returns the page ID and direct Elementor edit URL.", {
|
|
944
|
+
title: z.string().describe("Page title"),
|
|
945
|
+
status: z.enum(["draft", "publish", "private", "pending"]).optional().describe("Page status — default: draft"),
|
|
946
|
+
page_template: z.string().optional().describe("WordPress page template filename (e.g. 'elementor_canvas'). Leave blank for default."),
|
|
947
|
+
enable_elementor: z.boolean().optional().describe("Initialize the Elementor editor on this page (default: true)"),
|
|
948
|
+
site: siteParam,
|
|
949
|
+
}, async ({ title, status, page_template, enable_elementor, site }) => {
|
|
950
|
+
try {
|
|
951
|
+
const { wpUrl, authHeader } = resolveSite(sites, site);
|
|
952
|
+
const body = {
|
|
953
|
+
title,
|
|
954
|
+
status: status ?? "draft",
|
|
955
|
+
enable_elementor: enable_elementor ?? true,
|
|
956
|
+
};
|
|
957
|
+
if (page_template)
|
|
958
|
+
body.page_template = page_template;
|
|
959
|
+
const r = await axios.post(`${wpUrl}/wp-json/erc/v1/pages`, body, {
|
|
960
|
+
headers: { Authorization: authHeader, "Content-Type": "application/json" },
|
|
961
|
+
});
|
|
962
|
+
return { content: [{ type: "text", text: JSON.stringify(r.data, null, 2) }] };
|
|
963
|
+
}
|
|
964
|
+
catch (error) {
|
|
965
|
+
return { content: [{ type: "text", text: `Error creating page: ${error.response?.data?.message || error.message}` }], isError: true };
|
|
966
|
+
}
|
|
967
|
+
});
|
|
968
|
+
server.tool("publish-page", "Change the publish status of a WordPress page (publish, draft, private, pending, trash).", {
|
|
969
|
+
page_id: z.string().describe("WordPress Page ID"),
|
|
970
|
+
status: z.enum(["publish", "draft", "private", "pending", "trash"]).describe("Target status"),
|
|
971
|
+
site: siteParam,
|
|
972
|
+
}, async ({ page_id, status, site }) => {
|
|
973
|
+
try {
|
|
974
|
+
const { wpUrl, authHeader } = resolveSite(sites, site);
|
|
975
|
+
const r = await axios.patch(`${wpUrl}/wp-json/erc/v1/pages/${page_id}/status`, { status }, { headers: { Authorization: authHeader, "Content-Type": "application/json" } });
|
|
976
|
+
return { content: [{ type: "text", text: JSON.stringify(r.data, null, 2) }] };
|
|
977
|
+
}
|
|
978
|
+
catch (error) {
|
|
979
|
+
return { content: [{ type: "text", text: `Error updating page status: ${error.response?.data?.message || error.message}` }], isError: true };
|
|
980
|
+
}
|
|
981
|
+
});
|
|
982
|
+
server.tool("enable-elementor", "Enable the Elementor editor on an existing WordPress page that was not originally built with Elementor. Returns the direct Elementor edit URL.", {
|
|
983
|
+
page_id: z.string().describe("WordPress Page ID"),
|
|
984
|
+
site: siteParam,
|
|
985
|
+
}, async ({ page_id, site }) => {
|
|
986
|
+
try {
|
|
987
|
+
const { wpUrl, authHeader } = resolveSite(sites, site);
|
|
988
|
+
const r = await axios.post(`${wpUrl}/wp-json/erc/v1/pages/${page_id}/enable-elementor`, {}, { headers: { Authorization: authHeader } });
|
|
989
|
+
return { content: [{ type: "text", text: JSON.stringify(r.data, null, 2) }] };
|
|
990
|
+
}
|
|
991
|
+
catch (error) {
|
|
992
|
+
return { content: [{ type: "text", text: `Error enabling Elementor: ${error.response?.data?.message || error.message}` }], isError: true };
|
|
993
|
+
}
|
|
994
|
+
});
|
|
995
|
+
// ── Group 9: Screenshot ──────────────────────────────────────────────────────
|
|
996
|
+
server.tool("screenshot-page", "Take a full-page screenshot of a published WordPress page using the system-installed Google Chrome browser. Returns the screenshot as an image so you can visually review design, layout, and content. Requires the page to be publicly accessible (status: publish).", {
|
|
997
|
+
page_id: z.string().describe("WordPress Page ID"),
|
|
998
|
+
full_page: z.boolean().optional().describe("Capture the full scrollable page height (default: true)"),
|
|
999
|
+
width: z.number().optional().describe("Viewport width in pixels (default: 1440)"),
|
|
1000
|
+
site: siteParam,
|
|
1001
|
+
}, async ({ page_id, full_page, width, site }) => {
|
|
1002
|
+
try {
|
|
1003
|
+
const { wpUrl, authHeader } = resolveSite(sites, site);
|
|
1004
|
+
// ── 1. Resolve the page's public URL from WP REST API ──────────────
|
|
1005
|
+
const pageRes = await axios.get(`${wpUrl}/wp-json/wp/v2/pages/${page_id}`, {
|
|
1006
|
+
headers: { Authorization: authHeader },
|
|
1007
|
+
});
|
|
1008
|
+
const pageUrl = pageRes.data.link;
|
|
1009
|
+
if (!pageUrl)
|
|
1010
|
+
throw new Error("Could not resolve public URL for this page.");
|
|
1011
|
+
// ── 2. Detect system Chrome ──────────────────────────────────────
|
|
1012
|
+
const chromePaths = [
|
|
1013
|
+
// Windows
|
|
1014
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
1015
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
1016
|
+
// macOS
|
|
1017
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
1018
|
+
// Linux
|
|
1019
|
+
"/usr/bin/google-chrome",
|
|
1020
|
+
"/usr/bin/google-chrome-stable",
|
|
1021
|
+
"/usr/bin/chromium-browser",
|
|
1022
|
+
"/usr/bin/chromium",
|
|
1023
|
+
];
|
|
1024
|
+
let executablePath;
|
|
1025
|
+
for (const p of chromePaths) {
|
|
1026
|
+
if (fs.existsSync(p)) {
|
|
1027
|
+
executablePath = p;
|
|
1028
|
+
break;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
if (!executablePath) {
|
|
1032
|
+
throw new Error("Google Chrome not found on this machine.\n" +
|
|
1033
|
+
"Install Chrome from https://www.google.com/chrome/ and ensure it is in a standard location.\n" +
|
|
1034
|
+
"Checked paths:\n" + chromePaths.map(p => ` • ${p}`).join("\n"));
|
|
1035
|
+
}
|
|
1036
|
+
// ── 3. Launch puppeteer-core with system Chrome ─────────────────
|
|
1037
|
+
let puppeteer;
|
|
1038
|
+
try {
|
|
1039
|
+
puppeteer = await import("puppeteer-core");
|
|
1040
|
+
}
|
|
1041
|
+
catch {
|
|
1042
|
+
throw new Error("puppeteer-core is not installed. Run: npm install puppeteer-core\n" +
|
|
1043
|
+
"(or reinstall @yashwant.dharmdas/elementor-mcp — it is bundled as a dependency)");
|
|
1044
|
+
}
|
|
1045
|
+
const browser = await puppeteer.launch({
|
|
1046
|
+
executablePath,
|
|
1047
|
+
headless: true,
|
|
1048
|
+
args: [
|
|
1049
|
+
"--no-sandbox",
|
|
1050
|
+
"--disable-setuid-sandbox",
|
|
1051
|
+
"--disable-dev-shm-usage",
|
|
1052
|
+
"--disable-gpu",
|
|
1053
|
+
],
|
|
1054
|
+
});
|
|
1055
|
+
try {
|
|
1056
|
+
const page = await browser.newPage();
|
|
1057
|
+
await page.setViewport({ width: width ?? 1440, height: 900, deviceScaleFactor: 1 });
|
|
1058
|
+
await page.goto(pageUrl, { waitUntil: "networkidle2", timeout: 30_000 });
|
|
1059
|
+
// Small pause to let JS-heavy pages finish rendering
|
|
1060
|
+
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
1061
|
+
const screenshotBuffer = await page.screenshot({
|
|
1062
|
+
fullPage: full_page ?? true,
|
|
1063
|
+
type: "png",
|
|
1064
|
+
});
|
|
1065
|
+
const base64 = Buffer.isBuffer(screenshotBuffer)
|
|
1066
|
+
? screenshotBuffer.toString("base64")
|
|
1067
|
+
: Buffer.from(screenshotBuffer).toString("base64");
|
|
1068
|
+
return {
|
|
1069
|
+
content: [
|
|
1070
|
+
{
|
|
1071
|
+
type: "image",
|
|
1072
|
+
data: base64,
|
|
1073
|
+
mimeType: "image/png",
|
|
1074
|
+
},
|
|
1075
|
+
],
|
|
1076
|
+
};
|
|
1077
|
+
}
|
|
1078
|
+
finally {
|
|
1079
|
+
await browser.close();
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
catch (error) {
|
|
1083
|
+
return {
|
|
1084
|
+
content: [{ type: "text", text: `Error taking screenshot: ${error.message}` }],
|
|
1085
|
+
isError: true,
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
});
|
|
942
1089
|
return server;
|
|
943
1090
|
}
|
|
944
1091
|
// ─── Entry Point ──────────────────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yashwant.dharmdas/elementor-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"description": "MCP server for controlling Elementor via Claude — supports multiple WordPress sites",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
20
20
|
"ajv": "^8.12.0",
|
|
21
21
|
"axios": "^1.6.0",
|
|
22
|
+
"puppeteer-core": "^22.15.0",
|
|
22
23
|
"zod": "^3.22.4"
|
|
23
24
|
},
|
|
24
25
|
"devDependencies": {
|