@noleemits/vision-builder-control-mcp 4.44.0 → 4.45.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/index.js +248 -10
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Noleemits Vision Builder Control MCP Server
|
|
4
4
|
*
|
|
5
5
|
* Provides 69 tools for building and managing WordPress/Elementor sites.
|
|
6
|
+
* v4.45.0: patch_kit_global_css — surgical CSS operations (remove_rule, remove_selector_from_rules, find_replace) without full-payload round-trip; solves 30k-token MCP param-size barrier for large kits.
|
|
6
7
|
* v4.42.0: audit_text + replace_text — unified search/replace across Elementor + post columns with literal/regex/fuzzy modes. Fuzzy mode tolerates NBSP, curly quotes/dashes, ideographic punctuation — fixes the "copy-pasted needle won't match" bug.
|
|
7
8
|
* v4.35.0: PixelVault image integration — pixelvault_status, find_images, generate_image, get_batch_status, insert_image tools; proxy REST endpoints at /nvbc/v1/pixelvault/*.
|
|
8
9
|
* v4.34.0: Design tokens auto-inject as CSS custom properties (--nvbc-color-*, --nvbc-fs-*, --nvbc-space-*) site-wide via wp_head; kit global CSS tools (get_kit_global_css, set_kit_global_css); get_kit_settings formatter handles gap-style objects.
|
|
@@ -108,7 +109,7 @@ process.on('SIGINT', () => {
|
|
|
108
109
|
// CONFIG
|
|
109
110
|
// ================================================================
|
|
110
111
|
|
|
111
|
-
const VERSION = '4.
|
|
112
|
+
const VERSION = '4.45.0';
|
|
112
113
|
const MIN_PLUGIN_VERSION = '4.13.0'; // Minimum WP plugin version required by this MCP server
|
|
113
114
|
|
|
114
115
|
// ================================================================
|
|
@@ -155,6 +156,25 @@ function deepStripCDATA(obj) {
|
|
|
155
156
|
return obj;
|
|
156
157
|
}
|
|
157
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Render custom_css anti-pattern warnings (from the v4.44.1 analyzer) as a
|
|
161
|
+
* trailing block on tool output. Returns an empty string when there are none.
|
|
162
|
+
* Each warning includes selector, rule, suggestion, and (when surfaced from
|
|
163
|
+
* update_element_recursive) the element_id the CSS was written to.
|
|
164
|
+
*/
|
|
165
|
+
function formatCssWarnings(warnings) {
|
|
166
|
+
if (!Array.isArray(warnings) || warnings.length === 0) return '';
|
|
167
|
+
let out = `\n\nWARNING — ${warnings.length} custom_css pattern(s) have a native Elementor equivalent:\n`;
|
|
168
|
+
warnings.forEach((w, i) => {
|
|
169
|
+
const where = w.element_id ? ` [element ${w.element_id}]` : '';
|
|
170
|
+
out += ` ${i + 1}. ${w.rule}${where} on "${w.selector || '?'}"\n`;
|
|
171
|
+
out += ` Native: ${w.native || '(see suggestion)'}\n`;
|
|
172
|
+
if (w.suggestion) out += ` Tip: ${w.suggestion}\n`;
|
|
173
|
+
});
|
|
174
|
+
out += ` The write was applied; consider switching approach so the layout stays editable in the WYSIWYG.`;
|
|
175
|
+
return out;
|
|
176
|
+
}
|
|
177
|
+
|
|
158
178
|
const CONFIG = {
|
|
159
179
|
wordpressUrl: process.env.WP_URL || 'http://localhost',
|
|
160
180
|
username: process.env.WP_USER || '',
|
|
@@ -3223,8 +3243,29 @@ function getToolDefinitions() {
|
|
|
3223
3243
|
},
|
|
3224
3244
|
{
|
|
3225
3245
|
name: 'get_kit_global_css',
|
|
3226
|
-
description: 'Read the active kit\'s custom_css (Elementor "Custom CSS" field). This CSS is output site-wide via Elementor\'s own stylesheet pipeline. Use to inspect site-wide CSS variables, base styles, etc.',
|
|
3227
|
-
inputSchema: {
|
|
3246
|
+
description: 'Read the active kit\'s custom_css (Elementor "Custom CSS" field). This CSS is output site-wide via Elementor\'s own stylesheet pipeline. Use to inspect site-wide CSS variables, base styles, etc. v4.44.4+: pass start_line + end_line to read a slice (kit CSS often exceeds 60k chars and overflows context — slice + search_kit_global_css solve that).',
|
|
3247
|
+
inputSchema: {
|
|
3248
|
+
type: 'object',
|
|
3249
|
+
properties: {
|
|
3250
|
+
start_line: { type: 'number', description: 'First line (1-indexed) of the slice to read. Omit with end_line to read the whole file.' },
|
|
3251
|
+
end_line: { type: 'number', description: 'Last line (inclusive) of the slice. Pair with start_line.' }
|
|
3252
|
+
}
|
|
3253
|
+
}
|
|
3254
|
+
},
|
|
3255
|
+
{
|
|
3256
|
+
name: 'search_kit_global_css',
|
|
3257
|
+
description: 'Pattern-match against the kit\'s custom_css. Returns each hit with line number + surrounding context. Cheap "is .walcc-grid--3 already defined?" lookup that avoids shipping the full 60k+ kit CSS through the context window. Supports regex via regex=true. v4.44.4+.',
|
|
3258
|
+
inputSchema: {
|
|
3259
|
+
type: 'object',
|
|
3260
|
+
properties: {
|
|
3261
|
+
pattern: { type: 'string', description: 'String to find (literal by default; pass regex=true to treat as regex).' },
|
|
3262
|
+
regex: { type: 'boolean', description: 'Treat pattern as a regex. Default: false.' },
|
|
3263
|
+
case_sensitive: { type: 'boolean', description: 'Default: false (case-insensitive).' },
|
|
3264
|
+
context: { type: 'number', description: 'Lines of context above + below each hit. Default: 1.' },
|
|
3265
|
+
max_matches: { type: 'number', description: 'Cap on returned hits. Default: 50.' }
|
|
3266
|
+
},
|
|
3267
|
+
required: ['pattern']
|
|
3268
|
+
}
|
|
3228
3269
|
},
|
|
3229
3270
|
{
|
|
3230
3271
|
name: 'set_kit_global_css',
|
|
@@ -3239,6 +3280,57 @@ function getToolDefinitions() {
|
|
|
3239
3280
|
required: ['css']
|
|
3240
3281
|
}
|
|
3241
3282
|
},
|
|
3283
|
+
{
|
|
3284
|
+
name: 'patch_kit_global_css',
|
|
3285
|
+
description: 'Surgically patch the active kit\'s custom_css with operations (remove_rule, remove_selector_from_rules, find_replace). Avoids the full-payload round-trip of set_kit_global_css. Always dry_run=true first. v4.45.0+.',
|
|
3286
|
+
inputSchema: {
|
|
3287
|
+
type: 'object',
|
|
3288
|
+
required: ['operations'],
|
|
3289
|
+
properties: {
|
|
3290
|
+
operations: {
|
|
3291
|
+
type: 'array',
|
|
3292
|
+
items: { type: 'object' },
|
|
3293
|
+
description: 'Array of operation objects. Each must have a `type` field. remove_rule: {type, selector} — drop every rule block whose every selector matches the root class (word-boundary). remove_selector_from_rules: {type, selector} — remove matching selector from compound selector lists; drop rule if empty. find_replace: {type, find, replace, regex} — literal or regex find/replace on the full CSS string.'
|
|
3294
|
+
},
|
|
3295
|
+
dry_run: {
|
|
3296
|
+
type: 'boolean',
|
|
3297
|
+
description: 'Preview without saving (default: true). Set false to apply.'
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
},
|
|
3302
|
+
{
|
|
3303
|
+
name: 'audit_unused_kit_css',
|
|
3304
|
+
description: 'Find class selectors in the kit\'s custom_css that aren\'t referenced via css_classes/_css_classes on any element across every Elementor page and template. Pure read-only — no writes. Returns: defined/referenced/unused class counts, estimated bytes wasted, and prune_candidates (each with the rules that define them — selector, line, snippet, byte length). Use to clean up dead utility CSS before adding new rules. v4.44.2+.',
|
|
3305
|
+
inputSchema: {
|
|
3306
|
+
type: 'object',
|
|
3307
|
+
properties: {
|
|
3308
|
+
ignore_prefixes: {
|
|
3309
|
+
type: 'string',
|
|
3310
|
+
description: 'Comma-separated class-name prefixes to skip (e.g. "elementor-,e-,wp-"). Useful for framework classes the kit CSS overrides but doesn\'t define.'
|
|
3311
|
+
}
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
},
|
|
3315
|
+
{
|
|
3316
|
+
name: 'list_widget_types',
|
|
3317
|
+
description: 'Enumerate every registered Elementor widget and element type on this site. Returns name, title, and an is_atomic flag (atomic V4 widgets like e-heading vs classic widgets like heading). Use before get_widget_schema to find the right widget name. v4.44.3+.',
|
|
3318
|
+
inputSchema: { type: 'object', properties: {} }
|
|
3319
|
+
},
|
|
3320
|
+
{
|
|
3321
|
+
name: 'get_widget_schema',
|
|
3322
|
+
description: 'Read the full settings schema for one widget or element type — every accepted control with type, label, default, options, responsive flag, and section grouping. For atomic V4 widgets, returns the serialized props_schema instead (different system). Use to avoid having to read Elementor source. Pass section to scope to one control section, search to filter by control-name substring, or keys_only=true for just the names. v4.44.3+.',
|
|
3323
|
+
inputSchema: {
|
|
3324
|
+
type: 'object',
|
|
3325
|
+
properties: {
|
|
3326
|
+
widget_type: { type: 'string', description: 'Widget or element name (e.g. "heading", "e-heading", "container", "image", "button"). Use list_widget_types to enumerate.' },
|
|
3327
|
+
section: { type: 'string', description: 'Restrict to controls inside this control section (e.g. "section_title_style").' },
|
|
3328
|
+
search: { type: 'string', description: 'Substring filter on control name.' },
|
|
3329
|
+
keys_only: { type: 'boolean', description: 'Return only control name + type per entry (slim payload). Default: false.' }
|
|
3330
|
+
},
|
|
3331
|
+
required: ['widget_type']
|
|
3332
|
+
}
|
|
3333
|
+
},
|
|
3242
3334
|
// ── PixelVault image generation (v4.35.0) ──
|
|
3243
3335
|
{
|
|
3244
3336
|
name: 'pixelvault_status',
|
|
@@ -4183,7 +4275,9 @@ async function handleToolCall(name, args) {
|
|
|
4183
4275
|
}
|
|
4184
4276
|
const r = await apiCall(`/pages/${args.page_id}/update-element`, 'POST', body);
|
|
4185
4277
|
if (r.code || r.error) return ok(`Failed: ${r.message || r.error || 'Unknown error'}`);
|
|
4186
|
-
|
|
4278
|
+
let out = `Element ${r.element_id} updated on page ${r.page_id}.\nUpdated keys: ${r.updated_keys.join(', ')}`;
|
|
4279
|
+
out += formatCssWarnings(r.css_warnings);
|
|
4280
|
+
return ok(out);
|
|
4187
4281
|
} catch (err) {
|
|
4188
4282
|
return ok(`Failed: ${err.message}`);
|
|
4189
4283
|
}
|
|
@@ -4913,10 +5007,11 @@ async function handleToolCall(name, args) {
|
|
|
4913
5007
|
const r = await apiCall(`/templates/${args.template_id}/patch`, 'POST', { ops: args.ops });
|
|
4914
5008
|
const okLines = r.applied.map(a => ` ✓ #${a.index} ${a.type}`);
|
|
4915
5009
|
const errLines = (r.errors || []).map(e => ` ✗ #${e.index} ${e.type}: ${e.error}`);
|
|
4916
|
-
|
|
5010
|
+
let out =
|
|
4917
5011
|
`Patched template ${r.template_id}: ${r.applied.length} op(s) applied${r.errors?.length ? ', ' + r.errors.length + ' failed' : ''}\n` +
|
|
4918
|
-
okLines.concat(errLines).join('\n')
|
|
4919
|
-
);
|
|
5012
|
+
okLines.concat(errLines).join('\n');
|
|
5013
|
+
out += formatCssWarnings(r.css_warnings);
|
|
5014
|
+
return ok(out);
|
|
4920
5015
|
}
|
|
4921
5016
|
|
|
4922
5017
|
case 'migrate_extracted_md': {
|
|
@@ -5153,6 +5248,9 @@ async function handleToolCall(name, args) {
|
|
|
5153
5248
|
out += ` [${x.index}] ${x.error}\n`;
|
|
5154
5249
|
});
|
|
5155
5250
|
}
|
|
5251
|
+
// Aggregate custom_css anti-pattern warnings across all results
|
|
5252
|
+
const allWarnings = r.results.reduce((acc, x) => x.css_warnings ? acc.concat(x.css_warnings) : acc, []);
|
|
5253
|
+
out += formatCssWarnings(allWarnings);
|
|
5156
5254
|
return ok(out);
|
|
5157
5255
|
}
|
|
5158
5256
|
|
|
@@ -5707,10 +5805,48 @@ async function handleToolCall(name, args) {
|
|
|
5707
5805
|
}
|
|
5708
5806
|
|
|
5709
5807
|
case 'get_kit_global_css': {
|
|
5710
|
-
const
|
|
5808
|
+
const params = new URLSearchParams();
|
|
5809
|
+
if (args.start_line) params.set('start_line', String(args.start_line));
|
|
5810
|
+
if (args.end_line) params.set('end_line', String(args.end_line));
|
|
5811
|
+
const qs = params.toString() ? `?${params.toString()}` : '';
|
|
5812
|
+
const r = await apiCall(`/kit-global-css${qs}`);
|
|
5711
5813
|
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5712
|
-
let
|
|
5713
|
-
|
|
5814
|
+
let header = `=== KIT GLOBAL CSS ===\nKit ID: ${r.kit_id}\n`;
|
|
5815
|
+
if (r.start_line) {
|
|
5816
|
+
header += `Lines ${r.start_line}-${r.end_line} of ${r.total_lines} (slice = ${r.length} bytes; total = ${r.total_length} bytes)\n\n`;
|
|
5817
|
+
} else {
|
|
5818
|
+
header += `Length: ${r.length} bytes (${r.total_lines} lines)\n`;
|
|
5819
|
+
if (r.length > 30000) {
|
|
5820
|
+
header += `Tip: payload is large — use start_line+end_line for slices or search_kit_global_css for lookups.\n`;
|
|
5821
|
+
}
|
|
5822
|
+
header += `\n`;
|
|
5823
|
+
}
|
|
5824
|
+
return ok(header + (r.css || '(empty)'));
|
|
5825
|
+
}
|
|
5826
|
+
|
|
5827
|
+
case 'search_kit_global_css': {
|
|
5828
|
+
const params = new URLSearchParams({ pattern: args.pattern || '' });
|
|
5829
|
+
if (args.regex) params.set('regex', '1');
|
|
5830
|
+
if (args.case_sensitive) params.set('case_sensitive', '1');
|
|
5831
|
+
if (args.context !== undefined) params.set('context', String(args.context));
|
|
5832
|
+
if (args.max_matches !== undefined) params.set('max_matches', String(args.max_matches));
|
|
5833
|
+
const r = await apiCall(`/search-kit-global-css?${params.toString()}`);
|
|
5834
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5835
|
+
let out =
|
|
5836
|
+
`=== KIT CSS SEARCH ===\n` +
|
|
5837
|
+
`Kit ID: ${r.kit_id} | Lines: ${r.total_lines}\n` +
|
|
5838
|
+
`Pattern: ${r.is_regex ? '/' : '"'}${r.pattern}${r.is_regex ? '/' : '"'}\n` +
|
|
5839
|
+
`Matches: ${r.match_count}${r.truncated ? ' (truncated — pass higher max_matches)' : ''}\n`;
|
|
5840
|
+
if (r.match_count === 0) return ok(out + `\nNo matches.`);
|
|
5841
|
+
out += `\n`;
|
|
5842
|
+
r.matches.forEach((m, i) => {
|
|
5843
|
+
out += `--- Match ${i + 1} @ L${m.line} ---\n`;
|
|
5844
|
+
m.context.forEach((line, idx) => {
|
|
5845
|
+
const ln = m.context_start_line + idx;
|
|
5846
|
+
const marker = ln === m.line ? '>' : ' ';
|
|
5847
|
+
out += ` ${marker} ${String(ln).padStart(5)} | ${line}\n`;
|
|
5848
|
+
});
|
|
5849
|
+
});
|
|
5714
5850
|
return ok(out);
|
|
5715
5851
|
}
|
|
5716
5852
|
|
|
@@ -5727,6 +5863,108 @@ async function handleToolCall(name, args) {
|
|
|
5727
5863
|
return ok(out);
|
|
5728
5864
|
}
|
|
5729
5865
|
|
|
5866
|
+
case 'patch_kit_global_css': {
|
|
5867
|
+
const body = { operations: args.operations ?? [] };
|
|
5868
|
+
if (args.dry_run !== undefined) body.dry_run = args.dry_run;
|
|
5869
|
+
const r = await apiCall('/kit-global-css/patch', 'POST', body);
|
|
5870
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5871
|
+
let out = r.dry_run
|
|
5872
|
+
? `=== PATCH KIT GLOBAL CSS (DRY RUN) ===\n`
|
|
5873
|
+
: `=== PATCH KIT GLOBAL CSS ===\n`;
|
|
5874
|
+
out += `Kit ID: ${r.kit_id}\n`;
|
|
5875
|
+
out += `${r.summary}\n`;
|
|
5876
|
+
if (r.operations_applied && r.operations_applied.length) {
|
|
5877
|
+
out += `\nOperations applied (${r.operations_applied.length}):\n`;
|
|
5878
|
+
r.operations_applied.forEach((op, i) => {
|
|
5879
|
+
const sel = op.selector ? ` "${op.selector}"` : op.find ? ` find="${op.find}"` : '';
|
|
5880
|
+
out += ` ${i + 1}. [${op.type}]${sel} matches=${op.matches} bytes_removed=${op.bytes_removed}\n`;
|
|
5881
|
+
});
|
|
5882
|
+
}
|
|
5883
|
+
out += `\n${r.note}`;
|
|
5884
|
+
return ok(out);
|
|
5885
|
+
}
|
|
5886
|
+
|
|
5887
|
+
case 'audit_unused_kit_css': {
|
|
5888
|
+
const qs = args.ignore_prefixes ? `?ignore_prefixes=${encodeURIComponent(args.ignore_prefixes)}` : '';
|
|
5889
|
+
const r = await apiCall(`/audit-unused-kit-css${qs}`);
|
|
5890
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5891
|
+
let out =
|
|
5892
|
+
`=== UNUSED KIT CSS AUDIT ===\n` +
|
|
5893
|
+
`Kit ID: ${r.kit_id}\n` +
|
|
5894
|
+
`Kit CSS: ${r.kit_css_bytes} bytes\n` +
|
|
5895
|
+
`Classes defined: ${r.defined_class_count}\n` +
|
|
5896
|
+
`Classes referenced: ${r.referenced_class_count}\n` +
|
|
5897
|
+
`Classes UNUSED: ${r.unused_class_count}\n` +
|
|
5898
|
+
`Estimated waste: ~${r.estimated_bytes_unused} bytes\n`;
|
|
5899
|
+
if (r.ignored_prefixes && r.ignored_prefixes.length) {
|
|
5900
|
+
out += `Ignored prefixes: ${r.ignored_prefixes.join(', ')}\n`;
|
|
5901
|
+
}
|
|
5902
|
+
if (r.unused_class_count === 0) {
|
|
5903
|
+
out += `\nNo unused classes — kit CSS is clean.`;
|
|
5904
|
+
return ok(out);
|
|
5905
|
+
}
|
|
5906
|
+
out += `\n--- Prune candidates ---\n`;
|
|
5907
|
+
r.prune_candidates.forEach((c, i) => {
|
|
5908
|
+
out += `\n${i + 1}. .${c.class}\n`;
|
|
5909
|
+
c.rules.forEach(rule => {
|
|
5910
|
+
out += ` L${rule.line} (${rule.bytes}b) ${rule.snippet}\n`;
|
|
5911
|
+
});
|
|
5912
|
+
});
|
|
5913
|
+
return ok(out);
|
|
5914
|
+
}
|
|
5915
|
+
|
|
5916
|
+
case 'list_widget_types': {
|
|
5917
|
+
const r = await apiCall('/widget-types');
|
|
5918
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5919
|
+
let out = `=== WIDGET / ELEMENT TYPES ===\nWidgets: ${r.widget_count} | Elements: ${r.element_count}\n\n`;
|
|
5920
|
+
out += `--- Widgets ---\n`;
|
|
5921
|
+
r.widgets.forEach(w => {
|
|
5922
|
+
const atomic = w.is_atomic ? ' [atomic]' : '';
|
|
5923
|
+
const cat = w.category ? ` (${w.category})` : '';
|
|
5924
|
+
out += ` ${w.name.padEnd(28)} ${w.title}${atomic}${cat}\n`;
|
|
5925
|
+
});
|
|
5926
|
+
out += `\n--- Elements ---\n`;
|
|
5927
|
+
r.elements.forEach(e => {
|
|
5928
|
+
const atomic = e.is_atomic ? ' [atomic]' : '';
|
|
5929
|
+
out += ` ${e.name.padEnd(28)} ${e.title}${atomic}\n`;
|
|
5930
|
+
});
|
|
5931
|
+
return ok(out);
|
|
5932
|
+
}
|
|
5933
|
+
|
|
5934
|
+
case 'get_widget_schema': {
|
|
5935
|
+
const params = new URLSearchParams({ widget_type: args.widget_type || '' });
|
|
5936
|
+
if (args.section) params.set('section', args.section);
|
|
5937
|
+
if (args.search) params.set('search', args.search);
|
|
5938
|
+
if (args.keys_only) params.set('keys_only', '1');
|
|
5939
|
+
const r = await apiCall(`/widget-schema?${params.toString()}`);
|
|
5940
|
+
if (r.code || r.error) return ok(`Failed: ${r.message || r.error}`);
|
|
5941
|
+
let out =
|
|
5942
|
+
`=== ${r.widget_type} (${r.kind}${r.is_atomic ? ', atomic V4' : ''}) ===\n` +
|
|
5943
|
+
`Title: ${r.title}\n`;
|
|
5944
|
+
if (r.is_atomic) {
|
|
5945
|
+
out += `Props: ${r.props_count}\n\n${r.note}\n\n--- Props Schema ---\n`;
|
|
5946
|
+
out += JSON.stringify(r.props_schema, null, 2);
|
|
5947
|
+
return ok(out);
|
|
5948
|
+
}
|
|
5949
|
+
out += `Controls: ${r.control_count}`;
|
|
5950
|
+
if (r.filter.section || r.filter.search || r.filter.keys_only) {
|
|
5951
|
+
out += ` (filtered)`;
|
|
5952
|
+
}
|
|
5953
|
+
out += `\n\n--- Controls ---\n`;
|
|
5954
|
+
for (const [name, c] of Object.entries(r.controls)) {
|
|
5955
|
+
const meta = [`type=${c.type}`];
|
|
5956
|
+
if (c.section) meta.push(`section=${c.section}`);
|
|
5957
|
+
if (c.responsive) meta.push('responsive');
|
|
5958
|
+
if (c.options) meta.push(`options=[${c.options.slice(0, 6).join(',')}${c.options.length > 6 ? '…' : ''}]`);
|
|
5959
|
+
if (c.range_units) meta.push(`units=[${c.range_units.join(',')}]`);
|
|
5960
|
+
if (c.size_units) meta.push(`size_units=[${c.size_units.join(',')}]`);
|
|
5961
|
+
const dflt = c.default !== undefined ? ` default=${typeof c.default === 'object' ? JSON.stringify(c.default).slice(0, 40) : c.default}` : '';
|
|
5962
|
+
out += ` ${name.padEnd(36)} ${meta.join(' | ')}${dflt}\n`;
|
|
5963
|
+
if (c.label && !args.keys_only) out += `${' '.repeat(38)}label: ${c.label}\n`;
|
|
5964
|
+
}
|
|
5965
|
+
return ok(out);
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5730
5968
|
// ── PixelVault image generation ──
|
|
5731
5969
|
|
|
5732
5970
|
case 'pixelvault_status': {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noleemits/vision-builder-control-mcp",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.45.0",
|
|
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",
|