@noleemits/vision-builder-control-mcp 4.16.0 ā 4.18.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/index.js +89 -7
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -104,7 +104,7 @@ process.on('SIGINT', () => {
|
|
|
104
104
|
// CONFIG
|
|
105
105
|
// ================================================================
|
|
106
106
|
|
|
107
|
-
const VERSION = '4.
|
|
107
|
+
const VERSION = '4.18.1';
|
|
108
108
|
const MIN_PLUGIN_VERSION = '4.13.0'; // Minimum WP plugin version required by this MCP server
|
|
109
109
|
|
|
110
110
|
// ================================================================
|
|
@@ -2003,7 +2003,7 @@ function getToolDefinitions() {
|
|
|
2003
2003
|
},
|
|
2004
2004
|
{
|
|
2005
2005
|
name: 'fix_trailing_slashes',
|
|
2006
|
-
description: 'Add missing trailing slashes to internal URLs across ALL post types (pages, posts, CPTs). Scans both Elementor widget data and Gutenberg/classic post_content. Skips anchors (#), query strings (?), external URLs, and file extensions (.pdf etc). ALWAYS run with dry_run=true first to preview changes.',
|
|
2006
|
+
description: 'Add missing trailing slashes to internal URLs across ALL post types (pages, posts, CPTs). Scans both Elementor widget data and Gutenberg/classic post_content. Skips anchors (#), query strings (?), external URLs, and file extensions (.pdf etc). Never changes post_modified date. ALWAYS run with dry_run=true first to preview changes.',
|
|
2007
2007
|
inputSchema: {
|
|
2008
2008
|
type: 'object',
|
|
2009
2009
|
properties: {
|
|
@@ -2051,7 +2051,7 @@ function getToolDefinitions() {
|
|
|
2051
2051
|
},
|
|
2052
2052
|
{
|
|
2053
2053
|
name: 'find_replace',
|
|
2054
|
-
description: 'Global find & replace across all Elementor pages. Searches heading titles, text-editor HTML, button text, image-box titles/descriptions, icon-box titles/descriptions, icon-list items, toggle titles/content, and image alt text. Supports literal text or regex. Always preview with dry_run=true first.',
|
|
2054
|
+
description: 'Global find & replace across all Elementor pages. Searches heading titles, text-editor HTML, button text, image-box titles/descriptions, icon-box titles/descriptions, icon-list items, toggle titles/content, and image alt text. Supports literal text or regex. Never changes post_modified date (Elementor meta only). Always preview with dry_run=true first.',
|
|
2055
2055
|
inputSchema: {
|
|
2056
2056
|
type: 'object',
|
|
2057
2057
|
properties: {
|
|
@@ -2155,7 +2155,7 @@ function getToolDefinitions() {
|
|
|
2155
2155
|
},
|
|
2156
2156
|
{
|
|
2157
2157
|
name: 'update_post',
|
|
2158
|
-
description: 'Update any field on a WordPress post/page. Only provided fields are changed. Supports title, content, status, slug, excerpt, taxonomies, featured image, and RankMath SEO.',
|
|
2158
|
+
description: 'Update any field on a WordPress post/page. Only provided fields are changed. Supports title, content, status, slug, excerpt, taxonomies, featured image, and RankMath SEO. Pass preserve_modified_date=true to keep the original last-modified date.',
|
|
2159
2159
|
inputSchema: {
|
|
2160
2160
|
type: 'object',
|
|
2161
2161
|
properties: {
|
|
@@ -2168,7 +2168,8 @@ function getToolDefinitions() {
|
|
|
2168
2168
|
parent: { type: 'number', description: 'Parent post/page ID (for hierarchical types like pages). Changes URL structure.' },
|
|
2169
2169
|
taxonomies: { type: 'object', description: '{"category": [1,2]}' },
|
|
2170
2170
|
featured_image_id: { type: 'number', description: 'Attachment ID (omit to keep, pass null to remove)' },
|
|
2171
|
-
seo: { type: 'object', description: 'RankMath SEO fields to update' }
|
|
2171
|
+
seo: { type: 'object', description: 'RankMath SEO fields to update' },
|
|
2172
|
+
preserve_modified_date: { type: 'boolean', description: 'If true, keep the original last-modified date instead of updating it to now. Useful for content fixes that should not change the published "updated" date.' }
|
|
2172
2173
|
},
|
|
2173
2174
|
required: ['post_id']
|
|
2174
2175
|
}
|
|
@@ -2230,6 +2231,16 @@ function getToolDefinitions() {
|
|
|
2230
2231
|
}
|
|
2231
2232
|
}
|
|
2232
2233
|
},
|
|
2234
|
+
{
|
|
2235
|
+
name: 'audit_faq_schema',
|
|
2236
|
+
description: 'Audit all published posts/pages for FAQ schema issues: duplicate FAQPage markup (NVBC meta + RankMath block), orphaned NVBC schemas, unconverted plain FAQs, invalid JSON, empty Q&As, and encoding issues (bare u003c).',
|
|
2237
|
+
inputSchema: {
|
|
2238
|
+
type: 'object',
|
|
2239
|
+
properties: {
|
|
2240
|
+
post_type: { type: 'string', description: 'Optional: filter by post type (e.g., "page" or "post")' }
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
},
|
|
2233
2244
|
{
|
|
2234
2245
|
name: 'update_term_seo',
|
|
2235
2246
|
description: 'Update RankMath SEO fields on a taxonomy term (category, tag, custom taxonomy). Accepts any subset: title, description, focus_keyword, canonical_url, noindex (boolean convenience flag).',
|
|
@@ -2540,7 +2551,7 @@ function getToolDefinitions() {
|
|
|
2540
2551
|
},
|
|
2541
2552
|
{
|
|
2542
2553
|
name: 'replace_post_content',
|
|
2543
|
-
description: 'Bulk find-replace in WordPress post_content (Gutenberg/classic editor). Use for migrating URLs, fixing domains, replacing shortcodes. Always dry_run=true first to preview. Works on published posts and pages.',
|
|
2554
|
+
description: 'Bulk find-replace in WordPress post_content (Gutenberg/classic editor). Use for migrating URLs, fixing domains, replacing shortcodes. Always dry_run=true first to preview. Works on published posts and pages. Never changes post_modified date (uses direct DB write).',
|
|
2544
2555
|
inputSchema: {
|
|
2545
2556
|
type: 'object',
|
|
2546
2557
|
properties: {
|
|
@@ -2579,6 +2590,18 @@ function getToolDefinitions() {
|
|
|
2579
2590
|
required: ['posts']
|
|
2580
2591
|
}
|
|
2581
2592
|
},
|
|
2593
|
+
{
|
|
2594
|
+
name: 'convert_faq_to_rankmath',
|
|
2595
|
+
description: 'Scan post_content for plain Q/A FAQ sections and convert them to wp:rank-math/faq-block Gutenberg blocks. Detects H2 "FAQs" / "Frequently Asked Questions" headings followed by H3+paragraph Q/A pairs. Strips Q:/A: prefixes and entities. Never changes post_modified date (direct DB write). ALWAYS dry_run=true first.',
|
|
2596
|
+
inputSchema: {
|
|
2597
|
+
type: 'object',
|
|
2598
|
+
properties: {
|
|
2599
|
+
post_id: { type: 'number', description: 'Convert only this specific post ID. Omit to scan all posts.' },
|
|
2600
|
+
post_type: { type: 'string', description: 'Filter by post type: "post", "page", etc. Omit for all types.' },
|
|
2601
|
+
dry_run: { type: 'boolean', description: 'Preview extracted Q&As without saving (default: true). Set false to apply conversion.' }
|
|
2602
|
+
}
|
|
2603
|
+
}
|
|
2604
|
+
},
|
|
2582
2605
|
{
|
|
2583
2606
|
name: 'get_global_styles',
|
|
2584
2607
|
description: 'Read Elementor global colors and fonts from the active kit. Returns system colors (Primary, Secondary, Text, Accent), custom colors, system typography, and custom typography with all properties.',
|
|
@@ -3774,7 +3797,9 @@ async function handleToolCall(name, args) {
|
|
|
3774
3797
|
const { post_id, ...fields } = args;
|
|
3775
3798
|
const r = await apiCall(`/posts/${post_id}`, 'PUT', fields);
|
|
3776
3799
|
if (!r.success) return ok(`Failed: ${r.message || 'Unknown error'}`);
|
|
3777
|
-
|
|
3800
|
+
let out = `Post updated!\nID: ${r.id} | Status: ${r.status}\nTitle: ${r.title}\nUpdated: ${r.updated_fields.join(', ')}\nURL: ${r.url}`;
|
|
3801
|
+
if (r.modified_date_preserved) out += `\nš Modified date preserved: ${r.post_modified}`;
|
|
3802
|
+
return ok(out);
|
|
3778
3803
|
}
|
|
3779
3804
|
|
|
3780
3805
|
case 'delete_post': {
|
|
@@ -3839,6 +3864,36 @@ async function handleToolCall(name, args) {
|
|
|
3839
3864
|
return ok(out);
|
|
3840
3865
|
}
|
|
3841
3866
|
|
|
3867
|
+
case 'audit_faq_schema': {
|
|
3868
|
+
const params = new URLSearchParams();
|
|
3869
|
+
if (args.post_type) params.set('post_type', args.post_type);
|
|
3870
|
+
const qs = params.toString() ? `?${params.toString()}` : '';
|
|
3871
|
+
const r = await apiCall(`/audit-faq-schema${qs}`);
|
|
3872
|
+
if (!r.success) return ok(`Failed: ${r.message || 'Unknown error'}`);
|
|
3873
|
+
const s = r.summary;
|
|
3874
|
+
let out = `=== FAQ SCHEMA AUDIT ===\n`;
|
|
3875
|
+
out += `Total published: ${s.total_posts}\n`;
|
|
3876
|
+
out += `With RankMath FAQ block: ${s.has_rankmath_block}\n`;
|
|
3877
|
+
out += `With NVBC plugin schema: ${s.has_nvbc_schema}\n`;
|
|
3878
|
+
out += `Clean (no issues): ${s.clean}\n\n`;
|
|
3879
|
+
out += `--- Issues ---\n`;
|
|
3880
|
+
out += `Duplicate FAQ (both sources): ${s.duplicate_faq}\n`;
|
|
3881
|
+
out += `Plain FAQ unconverted: ${s.plain_faq_unconverted}\n`;
|
|
3882
|
+
out += `Invalid JSON: ${s.invalid_json}\n`;
|
|
3883
|
+
out += `Empty questions: ${s.empty_questions}\n`;
|
|
3884
|
+
out += `Encoding issues (bare u003c): ${s.encoding_issues}\n`;
|
|
3885
|
+
if (r.issues.length) {
|
|
3886
|
+
out += `\n--- POSTS WITH ISSUES (${r.issues.length}) ---\n`;
|
|
3887
|
+
r.issues.forEach(p => {
|
|
3888
|
+
out += ` [${p.id}] ${p.title} (${p.type}/${p.editor})`;
|
|
3889
|
+
out += `\n Issues: ${p.issues.join(', ')}\n`;
|
|
3890
|
+
});
|
|
3891
|
+
} else {
|
|
3892
|
+
out += '\nNo issues found ā all FAQ schemas are clean!';
|
|
3893
|
+
}
|
|
3894
|
+
return ok(out);
|
|
3895
|
+
}
|
|
3896
|
+
|
|
3842
3897
|
case 'update_term_seo': {
|
|
3843
3898
|
const { term_id, taxonomy, ...seoFields } = args;
|
|
3844
3899
|
const body = { ...seoFields };
|
|
@@ -4481,6 +4536,33 @@ async function handleToolCall(name, args) {
|
|
|
4481
4536
|
return ok(out);
|
|
4482
4537
|
}
|
|
4483
4538
|
|
|
4539
|
+
case 'convert_faq_to_rankmath': {
|
|
4540
|
+
const body = {};
|
|
4541
|
+
if (args.post_id) body.post_id = args.post_id;
|
|
4542
|
+
if (args.post_type) body.post_type = args.post_type;
|
|
4543
|
+
if (args.dry_run !== undefined) body.dry_run = args.dry_run;
|
|
4544
|
+
const r = await apiCall('/convert-faq-to-rankmath', 'POST', body);
|
|
4545
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
4546
|
+
let out = r.dry_run ? `=== CONVERT FAQ TO RANKMATH (DRY RUN) ===\n` : `=== CONVERT FAQ TO RANKMATH ===\n`;
|
|
4547
|
+
out += `Posts scanned: ${r.posts_scanned} | Converted: ${r.posts_converted} | Total Q&As: ${r.total_questions}\n`;
|
|
4548
|
+
if (r.results?.length) {
|
|
4549
|
+
r.results.forEach(p => {
|
|
4550
|
+
out += `\nš [${p.post_id}] ${p.title} (${p.post_type}) ā ${p.sections} section(s), ${p.questions} Q&A(s)${p.duplicates_removed ? ` [${p.duplicates_removed} duplicate(s) removed]` : ''}\n`;
|
|
4551
|
+
if (p.preview) {
|
|
4552
|
+
p.preview.forEach(sec => {
|
|
4553
|
+
out += ` Section: "${sec.heading}"\n`;
|
|
4554
|
+
sec.qa_pairs.forEach((qa, i) => {
|
|
4555
|
+
out += ` ${i + 1}. Q: ${qa.question}\n`;
|
|
4556
|
+
out += ` A: ${qa.answer}\n`;
|
|
4557
|
+
});
|
|
4558
|
+
});
|
|
4559
|
+
}
|
|
4560
|
+
});
|
|
4561
|
+
}
|
|
4562
|
+
out += `\n${r.note}`;
|
|
4563
|
+
return ok(out);
|
|
4564
|
+
}
|
|
4565
|
+
|
|
4484
4566
|
case 'get_global_styles': {
|
|
4485
4567
|
const r = await apiCall('/global-styles');
|
|
4486
4568
|
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noleemits/vision-builder-control-mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.18.1",
|
|
4
4
|
"description": "Vision Builder Control MCP server - design token-driven page builder tools for WordPress/Elementor websites",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|