@ufira/vibma 0.3.1 → 0.3.2-rc.2

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/README.md CHANGED
@@ -14,11 +14,13 @@ modify styles, and build entire design systems through conversation.
14
14
 
15
15
  ---
16
16
 
17
- ## Prerequisites
17
+ ## Model Recommendations
18
18
 
19
- Vibma works with any LLM that supports MCP, but only **Claude Opus 4.6**
20
- consistently achieves the demonstrated results. GPT-5.3-Codex comes close
21
- but makes occasional mistakes.
19
+ Vibma works with any LLM that supports MCP. Based on our [benchmark](https://github.com/ufira-ai/vibma-benchmark):
20
+
21
+ - **Cheap one-shot builds:** GPT-5.3 Codex (medium reasoning) — proper components, all variables bound, clean output for under $1. Degrades on follow-up tasks.
22
+ - **Iterative design work:** GPT-5.3 Codex (xhigh), Gemini 3.1 Pro, or Claude Opus 4.6 — these maintain quality as context grows and handle multi-pass workflows.
23
+ - **Avoid:** Models that skip figma components building (e.g. Cursor Auto, Kimi K2.5) produce frames that look right but aren't structurally usable — no instances, no variants, no library.
22
24
 
23
25
  ## Setup
24
26
 
package/dist/mcp.cjs CHANGED
@@ -268,7 +268,10 @@ var sectionItem = import_zod6.z.object({
268
268
  y: yPos,
269
269
  width: import_zod6.z.coerce.number().optional().describe("Width (default: 500)"),
270
270
  height: import_zod6.z.coerce.number().optional().describe("Height (default: 500)"),
271
- parentId
271
+ parentId,
272
+ fillColor: flexJson(colorRgba).optional().describe("Fill color. Default: no fill (transparent)."),
273
+ fillStyleName: import_zod6.z.string().optional().describe("Apply a fill paint style by name (case-insensitive)."),
274
+ fillVariableId: import_zod6.z.string().optional().describe("Bind a color variable to the fill.")
272
275
  });
273
276
  var svgItem = import_zod6.z.object({
274
277
  svg: import_zod6.z.string().describe("SVG markup string"),
@@ -280,7 +283,7 @@ var svgItem = import_zod6.z.object({
280
283
  var tools5 = [
281
284
  {
282
285
  name: "create_section",
283
- description: "Create section nodes to organize content on the canvas.",
286
+ description: "Create section nodes to organize content on the canvas. Default: no fill (transparent).",
284
287
  schema: { items: flexJson(import_zod6.z.array(sectionItem)).describe("Array of sections to create"), depth },
285
288
  tier: "create"
286
289
  },
@@ -377,8 +380,8 @@ var textItem = import_zod8.z.object({
377
380
  var tools7 = [
378
381
  {
379
382
  name: "create_text",
380
- description: "Create text nodes. Max 10 per batch. Prefer textStyleName for typography and fontColorStyleName or fontColorVariableId for color \u2014 hardcoded values skip design tokens. Supports custom fonts via fontFamily.",
381
- schema: { items: flexJson(import_zod8.z.array(textItem).max(10)).describe("Array of text nodes to create (max 10)"), depth },
383
+ description: "Create text nodes. Prefer textStyleName for typography and fontColorStyleName or fontColorVariableId for color \u2014 hardcoded values skip design tokens. Supports custom fonts via fontFamily.",
384
+ schema: { items: flexJson(import_zod8.z.array(textItem)).describe("Array of text nodes to create"), depth },
382
385
  tier: "create"
383
386
  }
384
387
  ];
@@ -441,8 +444,9 @@ var patchNodeItem = import_zod10.z.object({
441
444
  // Appearance (nested)
442
445
  fill: flexJson(import_zod10.z.object({
443
446
  color: flexJson(colorRgba).optional(),
444
- styleName: import_zod10.z.string().optional().describe("Paint style name (preferred over color)")
445
- })).optional().describe("Fill color or style"),
447
+ styleName: import_zod10.z.string().optional().describe("Paint style name (preferred over color)"),
448
+ clear: flexBool(import_zod10.z.boolean()).optional().describe("Set true to remove all fills")
449
+ })).optional().describe("Fill color, style, or clear"),
446
450
  stroke: flexJson(import_zod10.z.object({
447
451
  color: flexJson(colorRgba).optional(),
448
452
  weight: import_zod10.z.coerce.number().positive().optional().describe("Stroke weight"),
@@ -903,7 +907,8 @@ var componentItem = import_zod17.z.object({
903
907
  itemSpacing: import_zod17.z.coerce.number().optional().describe("Spacing between children (default: 0)")
904
908
  });
905
909
  var fromNodeItem = import_zod17.z.object({
906
- nodeId
910
+ nodeId,
911
+ exposeText: flexBool(import_zod17.z.boolean()).default(true).describe("Auto-expose text children as editable TEXT properties and bind them (default: true). Set false to skip.")
907
912
  });
908
913
  var combineItem = import_zod17.z.object({
909
914
  componentIds: flexJson(import_zod17.z.array(import_zod17.z.string())).describe("Component IDs to combine (min 2)"),
@@ -941,16 +946,16 @@ var tools15 = [
941
946
  description: `CRUD endpoint for components.
942
947
  create \u2192 {type, items, depth?} \u2192 {results: [{id}, ...]}
943
948
  type 'component': create from scratch with layout/style params
944
- type 'from_node': convert existing nodes to components
949
+ type 'from_node': convert existing nodes to components. Text children are auto-exposed as editable properties by default (exposeText: true) \u2014 instances can set text directly via properties.
945
950
  type 'variant_set': combine components into variant sets
946
951
  get \u2192 {id, fields?} \u2192 component object (full detail, field-filterable)
947
952
  list \u2192 {name?, setsOnly?, fields?, offset?, limit?} \u2192 paginated stubs
948
- update \u2192 {items: [{id, propertyName, type, defaultValue}]} \u2192 {results: ['ok', ...]}`,
953
+ update \u2192 {items: [{id, propertyName, type, defaultValue}]} \u2192 creates property AND binds matching text node automatically`,
949
954
  schema: (caps2) => endpointSchema(
950
955
  ["create", "get", "list", "update"],
951
956
  caps2,
952
957
  {
953
- items: flexJson(import_zod17.z.array(import_zod17.z.any())).optional().describe("create (component): [{name, parentId?, ...layout}]. create (from_node): [{nodeId}]. create (variant_set): [{componentIds, name?}]. update: [{id, propertyName, type, defaultValue}]."),
958
+ items: flexJson(import_zod17.z.array(import_zod17.z.any())).optional().describe("create (component): [{name, parentId?, ...layout}]. create (from_node): [{nodeId, exposeText?}]. create (variant_set): [{componentIds, name?}]. update: [{id, propertyName, type, defaultValue}]."),
954
959
  type: import_zod17.z.enum(["component", "from_node", "variant_set"]).optional().describe("Create type. Required for create: 'component' (from scratch), 'from_node' (convert existing), 'variant_set' (combine as variants)."),
955
960
  depth,
956
961
  name: import_zod17.z.string().optional().describe("Filter list by name (case-insensitive substring)."),
@@ -1229,6 +1234,45 @@ Transfer content overrides from a source instance to target instances.
1229
1234
  description: "Strategy for transferring overrides between component instances in Figma"
1230
1235
  })
1231
1236
  );
1237
+ server2.registerPrompt(
1238
+ "missing_tools",
1239
+ { description: "Why create or edit tools are missing and how to fix it" },
1240
+ () => ({
1241
+ messages: [{
1242
+ role: "assistant",
1243
+ content: {
1244
+ type: "text",
1245
+ text: `# Missing Create / Edit Tools
1246
+
1247
+ If the user asks you to create or modify something in Figma but you cannot find tools like \`create_frame\`, \`create_text\`, \`patch_nodes\`, \`delete_node\`, or \`set_text_content\`, the MCP server was started without the correct access tier flag.
1248
+
1249
+ Vibma filters tools at startup based on CLI flags passed in the MCP config \`args\` array:
1250
+
1251
+ | Flag | Tools available |
1252
+ |------|----------------|
1253
+ | _(none)_ | Read-only (inspect, search, export) |
1254
+ | \`--create\` | Read + creation tools |
1255
+ | \`--edit\` | All tools (read + create + edit + delete) |
1256
+
1257
+ Ask the user to add \`--edit\` (or \`--create\`) to their MCP config args:
1258
+
1259
+ \`\`\`json
1260
+ {
1261
+ "mcpServers": {
1262
+ "Vibma": {
1263
+ "command": "npx",
1264
+ "args": ["-y", "@ufira/vibma", "--edit"]
1265
+ }
1266
+ }
1267
+ }
1268
+ \`\`\`
1269
+
1270
+ After updating, the user must restart their AI tool or reload MCP servers \u2014 stdio-based servers cannot hot-reload.`
1271
+ }
1272
+ }],
1273
+ description: "Why create or edit tools are missing and how to fix it"
1274
+ })
1275
+ );
1232
1276
  }
1233
1277
 
1234
1278
  // src/tools/mcp-registry.ts
@@ -1266,6 +1310,13 @@ try {
1266
1310
  VIBMA_VERSION = pkg.version;
1267
1311
  break;
1268
1312
  }
1313
+ if (pkg.workspaces) {
1314
+ try {
1315
+ VIBMA_VERSION = JSON.parse((0, import_fs.readFileSync)((0, import_path.join)(dir, "packages/core/package.json"), "utf8")).version;
1316
+ } catch {
1317
+ }
1318
+ break;
1319
+ }
1269
1320
  } catch {
1270
1321
  continue;
1271
1322
  }