@noleemits/vision-builder-control-mcp 4.96.0 → 4.98.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.
Files changed (2) hide show
  1. package/index.js +18 -5
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -111,7 +111,7 @@ process.on('SIGINT', () => {
111
111
  // CONFIG
112
112
  // ================================================================
113
113
 
114
- const VERSION = '4.96.0';
114
+ const VERSION = '4.98.0';
115
115
  const MIN_PLUGIN_VERSION = '4.13.0'; // Minimum WP plugin version required by this MCP server
116
116
 
117
117
  // ================================================================
@@ -4011,18 +4011,20 @@ function getToolDefinitions() {
4011
4011
  },
4012
4012
  {
4013
4013
  name: 'upsert_class',
4014
- description: 'Define or update a site CSS class — stores its metadata AND CSS body in the NVBC class registry. NVBC renders the CSS page-scoped (only on pages that use the class); it is NOT written to the Elementor Kit. The class appears in list_classes with source=[site] and in the editor Browse picker. Optional apply_to: attach the class to element IDs on specific pages in the same call. Call again with the same name to update (css is replaced). v4.76.0+. v4.92.0 adds scope (global vs page) and status (published vs draft): a page-scoped class only appears in the editor picker on its target pages; a draft class is hidden from the picker entirely until you flip status to published.',
4014
+ description: 'Define or update a site CSS class — stores its metadata AND CSS body in the NVBC class registry. NVBC renders the CSS page-scoped (only on pages that use the class); it is NOT written to the Elementor Kit. The class appears in list_classes with source=[site] and in the editor Browse picker. Optional apply_to: attach the class to element IDs on specific pages in the same call. Call again with the same name to update (css/rules are replaced). v4.76.0+. v4.92.0 adds scope (global vs page) and status (published vs draft). v4.97.0 adds specificity (auto|layout|utility) so layout/visual classes win against .elementor .e-con default styles instead of losing on specificity. v4.98.0 adds rules — the recommended way to author classes that need pseudo-elements, hover states, or any multi-rule structure (keeps the plugin the owner of all class CSS instead of forcing the user to drop ad-hoc CSS into Elementor).',
4015
4015
  inputSchema: {
4016
4016
  type: 'object',
4017
4017
  properties: {
4018
4018
  name: { type: 'string', description: 'CSS class name without leading dot. Lowercase, hyphens and underscores only. e.g. "ef-font-display"' },
4019
- css: { type: 'string', description: 'CSS property declarations for the class body no selector, no braces. e.g. "font-size: clamp(40px, 5vw, 72px); font-family: \'Cormorant Garamond\', serif;"' },
4019
+ css: { type: 'string', description: 'Single-rule shorthand — CSS property declarations for the class body, no selector, no braces. Equivalent to rules["&"]. Use this only when the class is one bare rule; for anything with pseudo-elements, :hover/:focus/:active, or child selectors, use `rules` instead. e.g. "font-size: clamp(40px, 5vw, 72px); font-family: \'Cormorant Garamond\', serif;"' },
4020
+ rules: { type: 'object', additionalProperties: { type: 'string' }, description: 'v4.98.0+. Map of selector templates to declaration bodies (no braces). `&` in the selector is replaced with the resolved class selector — so this is the way to express pseudo-elements, hover/focus states, attribute states, and child/descendant selectors WITHOUT dropping raw CSS into Elementor. The specificity heuristic runs per-rule on each body, so decorative rules with backgrounds get the `.elementor` wrap automatically. Example for a hero with a gold accent strip and radial glow: {"&": "position: relative; overflow: hidden;", "&::before": "content: \\\"\\\"; position: absolute; inset: 0 0 auto 0; height: 4px; background: var(--nvbc-color-accent);", "&::after": "content: \\\"\\\"; position: absolute; inset: 0; background: radial-gradient(circle at 30% 30%, rgba(255,200,100,0.18), transparent 60%); pointer-events: none;", "&:hover": "transform: translateY(-2px);"}. If both `css` and `rules` are supplied, `css` is merged in as rules["&"] unless rules already has an explicit "&" key. For @media / @supports / container queries, use `css` with full rule syntax — `rules` is selector-keyed only.' },
4020
4021
  description: { type: 'string', description: 'Human-readable description shown in list_classes output.' },
4021
4022
  category: { type: 'string', enum: ['hero', 'cards', 'layout', 'grid', 'spacing', 'typography', 'decorative', 'utility'], description: 'Category for list_classes grouping. Default: "utility".' },
4022
4023
  applies_to: { type: 'array', items: { type: 'string' }, description: 'Element types this class applies to. Default: ["any"].' },
4023
4024
  scope: { type: 'string', enum: ['global', 'page'], description: 'v4.92.0+. "global" (default) = appears in the editor picker on every page. "page" = only appears in the picker on the pages listed in scope_page_ids (or derived from apply_to). Render is unaffected: if the class is on an element, its CSS still emits — scope only filters editor-picker visibility.' },
4024
4025
  scope_page_ids: { type: 'array', items: { type: 'number' }, description: 'v4.92.0+. Required when scope=page (or supply apply_to with page_id entries and the server will derive these). WordPress page IDs the class belongs to.' },
4025
4026
  status: { type: 'string', enum: ['published', 'draft'], description: 'v4.92.0+. "published" (default) = appears in list_classes + editor picker. "draft" = hidden from both until promoted. Useful while iterating on a class.' },
4027
+ specificity: { type: 'string', enum: ['auto', 'layout', 'utility'], description: 'v4.97.0+. Controls how the class selector is emitted. "auto" (default) wraps as .elementor .{name} when the css body sets layout (display, grid-template-*, gap, padding) or visual (background, border, border-radius, box-shadow) properties — so the class beats .elementor .e-con instead of losing on specificity. "layout" forces the wrap. "utility" forces a bare .{name} for cases where you want the class overridable.' },
4026
4028
  apply_to: {
4027
4029
  type: 'array',
4028
4030
  description: 'Optional: attach this class to these elements in the same call. When scope=page and scope_page_ids is omitted, the page_ids here are used as scope_page_ids.',
@@ -7737,9 +7739,15 @@ async function handleToolCall(name, args) {
7737
7739
  applies_to: args.applies_to || ['any'],
7738
7740
  };
7739
7741
  if (args.css) regBody.css = args.css;
7742
+ // v4.98.0 — structured rules map (preferred for pseudo-elements, :hover, child selectors).
7743
+ if (args.rules && typeof args.rules === 'object' && !Array.isArray(args.rules)) {
7744
+ regBody.rules = args.rules;
7745
+ }
7740
7746
  // v4.92.0 — scope + status + scope_page_ids.
7741
7747
  if (args.scope) regBody.scope = args.scope;
7742
7748
  if (args.status) regBody.status = args.status;
7749
+ // v4.97.0 — specificity hint for the emit pipeline.
7750
+ if (args.specificity !== undefined) regBody.specificity = args.specificity;
7743
7751
  if (Array.isArray(args.scope_page_ids) && args.scope_page_ids.length) {
7744
7752
  regBody.scope_page_ids = args.scope_page_ids;
7745
7753
  }
@@ -7759,8 +7767,13 @@ async function handleToolCall(name, args) {
7759
7767
  if (r.class?.status === 'draft') {
7760
7768
  msg += `Status: DRAFT. The class is hidden from list_classes + the editor picker until you flip it to published.\n`;
7761
7769
  }
7762
- if (args.css) {
7763
- msg += `CSS stored on the class — renders page-scoped (only on pages that use .${args.name}).\n`;
7770
+ if (args.rules || args.css) {
7771
+ const ruleCount = args.rules ? Object.keys(args.rules).length : 0;
7772
+ if (ruleCount > 0) {
7773
+ msg += `CSS compiled from ${ruleCount} rule(s) (${Object.keys(args.rules).join(', ')}) and stored on the class — renders page-scoped (only on pages that use .${args.name}).\n`;
7774
+ } else {
7775
+ msg += `CSS stored on the class — renders page-scoped (only on pages that use .${args.name}).\n`;
7776
+ }
7764
7777
  }
7765
7778
 
7766
7779
  // 3. Attach to elements if apply_to provided
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noleemits/vision-builder-control-mcp",
3
- "version": "4.96.0",
3
+ "version": "4.98.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",