@noleemits/vision-builder-control-mcp 4.5.6 → 4.5.10
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 +117 -6
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -94,7 +94,8 @@ process.on('SIGINT', () => {
|
|
|
94
94
|
// CONFIG
|
|
95
95
|
// ================================================================
|
|
96
96
|
|
|
97
|
-
const VERSION = '4.5.
|
|
97
|
+
const VERSION = '4.5.10';
|
|
98
|
+
const MIN_PLUGIN_VERSION = '4.5.10'; // Minimum WP plugin version required by this MCP server
|
|
98
99
|
|
|
99
100
|
// ================================================================
|
|
100
101
|
// PARAMETER HELPERS
|
|
@@ -1727,6 +1728,18 @@ function getToolDefinitions() {
|
|
|
1727
1728
|
}
|
|
1728
1729
|
}
|
|
1729
1730
|
},
|
|
1731
|
+
{
|
|
1732
|
+
name: 'fix_trailing_slashes',
|
|
1733
|
+
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.',
|
|
1734
|
+
inputSchema: {
|
|
1735
|
+
type: 'object',
|
|
1736
|
+
properties: {
|
|
1737
|
+
post_id: { type: 'number', description: 'Fix only this specific post ID. Omit to scan all posts.' },
|
|
1738
|
+
post_type: { type: 'string', description: 'Filter by post type (e.g. "page", "post", "treatment"). Omit for all public post types.' },
|
|
1739
|
+
dry_run: { type: 'boolean', description: 'Preview changes without saving. Default: true (safe). Set false to apply.' }
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
},
|
|
1730
1743
|
{
|
|
1731
1744
|
name: 'fix_links',
|
|
1732
1745
|
description: 'Auto-fix link targets across all Elementor pages. Internal links → same tab, external → new tab. Supports dry_run mode. Use include_templates to also fix library templates.',
|
|
@@ -1794,11 +1807,27 @@ function getToolDefinitions() {
|
|
|
1794
1807
|
},
|
|
1795
1808
|
{
|
|
1796
1809
|
name: 'check_links',
|
|
1797
|
-
description: 'Check all URLs on Elementor pages for broken links (404, 500, timeout).
|
|
1810
|
+
description: 'Check all URLs on Elementor pages for broken links (404, 500, timeout). Results are cached per-URL for 24 hours — subsequent calls are instant for already-checked URLs. Use force_refresh=true to re-fetch everything.',
|
|
1811
|
+
inputSchema: {
|
|
1812
|
+
type: 'object',
|
|
1813
|
+
properties: {
|
|
1814
|
+
page_id: { type: 'number', description: 'Optional: check only this page.' },
|
|
1815
|
+
force_refresh: { type: 'boolean', description: 'If true, bypass cache and re-fetch all URLs. Default: false.' }
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
},
|
|
1819
|
+
{
|
|
1820
|
+
name: 'clear_link_cache',
|
|
1821
|
+
description: 'Clear the persistent link status cache. Use when you know URLs have changed and want the next check_links call to re-fetch everything from scratch.',
|
|
1822
|
+
inputSchema: { type: 'object', properties: {} }
|
|
1823
|
+
},
|
|
1824
|
+
{
|
|
1825
|
+
name: 'warm_link_cache',
|
|
1826
|
+
description: 'Pre-warm the link status cache by fetching the site\'s XML sitemap, extracting all URLs, and HEAD-checking each one. Handles staging environments automatically — sitemap URLs with a different domain are normalized to the current site URL. Run this once to make subsequent check_links calls instant. Supports sitemap index files (fetches all child sitemaps).',
|
|
1798
1827
|
inputSchema: {
|
|
1799
1828
|
type: 'object',
|
|
1800
1829
|
properties: {
|
|
1801
|
-
|
|
1830
|
+
force_refresh: { type: 'boolean', description: 'Re-check even URLs already in cache. Default: false (skips fresh entries).' }
|
|
1802
1831
|
}
|
|
1803
1832
|
}
|
|
1804
1833
|
},
|
|
@@ -2428,13 +2457,31 @@ async function handleToolCall(name, args) {
|
|
|
2428
2457
|
case 'health_check': {
|
|
2429
2458
|
try {
|
|
2430
2459
|
const r = await apiCall('/health');
|
|
2460
|
+
|
|
2461
|
+
// Compare plugin version against minimum required
|
|
2462
|
+
const versionOk = (pluginVer, minVer) => {
|
|
2463
|
+
const p = pluginVer.split('.').map(Number);
|
|
2464
|
+
const m = minVer.split('.').map(Number);
|
|
2465
|
+
for (let i = 0; i < 3; i++) {
|
|
2466
|
+
if ((p[i] || 0) > (m[i] || 0)) return true;
|
|
2467
|
+
if ((p[i] || 0) < (m[i] || 0)) return false;
|
|
2468
|
+
}
|
|
2469
|
+
return true; // equal is fine
|
|
2470
|
+
};
|
|
2471
|
+
|
|
2472
|
+
const compatible = versionOk(r.version, MIN_PLUGIN_VERSION);
|
|
2473
|
+
const compatLine = compatible
|
|
2474
|
+
? `Compatibility: OK`
|
|
2475
|
+
: `⚠️ Compatibility: Plugin v${r.version} is below required v${MIN_PLUGIN_VERSION}.\n Some tools may fail. Please update the WordPress plugin.`;
|
|
2476
|
+
|
|
2431
2477
|
return ok(
|
|
2432
2478
|
`Vision Builder Control: ACTIVE\n` +
|
|
2433
2479
|
`Plugin: v${r.version}\n` +
|
|
2434
2480
|
`Elementor: ${r.elementor ? 'Active' : 'NOT ACTIVE'}\n` +
|
|
2435
2481
|
`Components: ${r.components}\n` +
|
|
2436
2482
|
`Shortcodes: ${r.shortcodes ? 'Enabled' : 'Disabled'}\n` +
|
|
2437
|
-
`MCP Server: v${VERSION} (${httpMode ? 'HTTP/SSE' : 'stdio'})`
|
|
2483
|
+
`MCP Server: v${VERSION} (${httpMode ? 'HTTP/SSE' : 'stdio'})\n` +
|
|
2484
|
+
compatLine
|
|
2438
2485
|
);
|
|
2439
2486
|
} catch (e) {
|
|
2440
2487
|
return ok(`Vision Builder Control: NOT RESPONDING\nError: ${e.message}\n\nMake sure:\n1. Noleemits Vision Builder Control plugin is activated\n2. Elementor is installed and activated\n3. WP_URL, WP_USER, WP_APP_PASSWORD are correct`);
|
|
@@ -2803,6 +2850,35 @@ async function handleToolCall(name, args) {
|
|
|
2803
2850
|
return ok(msg);
|
|
2804
2851
|
}
|
|
2805
2852
|
|
|
2853
|
+
case 'fix_trailing_slashes': {
|
|
2854
|
+
const body = { dry_run: args.dry_run !== false };
|
|
2855
|
+
if (args.post_id) body.post_id = args.post_id;
|
|
2856
|
+
if (args.post_type) body.post_type = args.post_type;
|
|
2857
|
+
const r = await apiCall('/fix-trailing-slashes', 'POST', body);
|
|
2858
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error || 'Unknown error'}`);
|
|
2859
|
+
|
|
2860
|
+
const mode = r.dry_run ? 'DRY RUN — no changes saved' : 'APPLIED';
|
|
2861
|
+
let msg = `=== TRAILING SLASH FIX (${mode}) ===\nPosts scanned: ${r.posts_scanned}\nPosts with changes: ${r.posts_fixed}\nTotal URLs to fix: ${r.total_changes}\n`;
|
|
2862
|
+
|
|
2863
|
+
if (r.total_changes === 0) {
|
|
2864
|
+
msg += '\nAll internal URLs already have trailing slashes.';
|
|
2865
|
+
} else {
|
|
2866
|
+
r.results.forEach(p => {
|
|
2867
|
+
msg += `\n--- ${p.title} [${p.post_type}] (ID: ${p.post_id}) — ${p.count} change(s) ---\n`;
|
|
2868
|
+
p.changes.forEach(c => {
|
|
2869
|
+
const loc = c.source === 'elementor'
|
|
2870
|
+
? `[${c.widget}] ${c.field}`
|
|
2871
|
+
: c.source === 'elementor_html'
|
|
2872
|
+
? `[${c.widget}] HTML`
|
|
2873
|
+
: '[post_content]';
|
|
2874
|
+
msg += ` ${loc}: ${c.old} → ${c.new}\n`;
|
|
2875
|
+
});
|
|
2876
|
+
});
|
|
2877
|
+
if (r.dry_run) msg += '\n(Dry run — run again with dry_run=false to apply changes.)';
|
|
2878
|
+
}
|
|
2879
|
+
return ok(msg);
|
|
2880
|
+
}
|
|
2881
|
+
|
|
2806
2882
|
case 'fix_links': {
|
|
2807
2883
|
const body = {};
|
|
2808
2884
|
if (args.page_id) body.page_id = args.page_id;
|
|
@@ -2957,13 +3033,19 @@ async function handleToolCall(name, args) {
|
|
|
2957
3033
|
|
|
2958
3034
|
case 'check_links': {
|
|
2959
3035
|
const params = new URLSearchParams();
|
|
2960
|
-
if (args.page_id)
|
|
3036
|
+
if (args.page_id) params.set('page_id', args.page_id);
|
|
3037
|
+
if (args.force_refresh) params.set('force_refresh', '1');
|
|
2961
3038
|
const qs = params.toString() ? `?${params.toString()}` : '';
|
|
2962
3039
|
const r = await apiCall(`/check-links${qs}`);
|
|
2963
3040
|
if (r.code || r.error) return ok(`Failed: ${r.message || r.error || 'Unknown error'}`);
|
|
2964
3041
|
|
|
3042
|
+
const cacheNote = r.from_cache > 0
|
|
3043
|
+
? `${r.from_cache} from cache (${r.cache_ttl_hours}h TTL), ${r.freshly_fetched} freshly fetched`
|
|
3044
|
+
: `${r.freshly_fetched} freshly fetched (cache empty)`;
|
|
3045
|
+
|
|
2965
3046
|
let msg = `=== BROKEN LINK CHECK ===\n`;
|
|
2966
|
-
msg += `
|
|
3047
|
+
msg += `Pages scanned: ${r.pages_scanned} | URLs checked: ${r.urls_checked} | Broken: ${r.broken_count}\n`;
|
|
3048
|
+
msg += `Cache: ${cacheNote}\n`;
|
|
2967
3049
|
|
|
2968
3050
|
if (r.broken_count === 0) {
|
|
2969
3051
|
msg += '\nAll links are working!';
|
|
@@ -2980,6 +3062,35 @@ async function handleToolCall(name, args) {
|
|
|
2980
3062
|
return ok(msg);
|
|
2981
3063
|
}
|
|
2982
3064
|
|
|
3065
|
+
case 'clear_link_cache': {
|
|
3066
|
+
const r = await apiCall('/link-cache', 'DELETE');
|
|
3067
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error || 'Unknown error'}`);
|
|
3068
|
+
return ok(r.message);
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
case 'warm_link_cache': {
|
|
3072
|
+
const body = {};
|
|
3073
|
+
if (args.force_refresh) body.force_refresh = true;
|
|
3074
|
+
const r = await apiCall('/warm-link-cache', 'POST', body);
|
|
3075
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error || 'Unknown error'}`);
|
|
3076
|
+
if (!r.success) return ok(`Could not warm cache: ${r.message}`);
|
|
3077
|
+
|
|
3078
|
+
let msg = `=== LINK CACHE WARMED ===\n`;
|
|
3079
|
+
msg += `Sitemap: ${r.sitemap_url}\n`;
|
|
3080
|
+
msg += `URLs in sitemap: ${r.urls_in_sitemap}\n`;
|
|
3081
|
+
msg += `Freshly checked: ${r.warmed}\n`;
|
|
3082
|
+
msg += `Skipped (already cached): ${r.skipped_cached}\n`;
|
|
3083
|
+
msg += `Cache TTL: ${r.cache_ttl_hours}h\n`;
|
|
3084
|
+
if (r.broken_found > 0) {
|
|
3085
|
+
msg += `\n⚠️ ${r.broken_found} broken/unreachable URLs found:\n`;
|
|
3086
|
+
r.broken_urls.forEach(u => { msg += ` ${u}\n`; });
|
|
3087
|
+
} else {
|
|
3088
|
+
msg += `\nAll URLs returned 2xx/3xx — no broken links detected.`;
|
|
3089
|
+
}
|
|
3090
|
+
msg += `\nNext check_links call will use this cache and return instantly.`;
|
|
3091
|
+
return ok(msg);
|
|
3092
|
+
}
|
|
3093
|
+
|
|
2983
3094
|
// ── Posts CRUD ──
|
|
2984
3095
|
|
|
2985
3096
|
case 'list_posts': {
|
package/package.json
CHANGED