mcp-figma-toolkit 1.0.9 → 1.0.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/plugin/plugin.js +98 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-figma-toolkit",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "MCP server that enables AI agents to manipulate Figma documents - create shapes, text, styles, components, variables, and more",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
package/plugin/plugin.js CHANGED
@@ -53,6 +53,22 @@ function serializeEffects(effects) {
53
53
  base.hex = rgbToHex(e.color);
54
54
  base.opacity = e.color.a != null ? e.color.a : 1;
55
55
  }
56
+ if (e.boundVariables) {
57
+ var ebv = {};
58
+ var ebvKeys = ["radius", "spread", "color", "offsetX", "offsetY"];
59
+ for (var ei = 0; ei < ebvKeys.length; ei++) {
60
+ var ek = ebvKeys[ei];
61
+ try {
62
+ var eb = e.boundVariables[ek];
63
+ if (eb && eb.id) {
64
+ ebv[ek] = { type: eb.type, id: eb.id };
65
+ var ev = figma.variables.getVariableById(eb.id);
66
+ if (ev) { ebv[ek].name = ev.name; ebv[ek].resolvedType = ev.resolvedType; }
67
+ }
68
+ } catch (_) {}
69
+ }
70
+ if (Object.keys(ebv).length > 0) base.boundVariables = ebv;
71
+ }
56
72
  return base;
57
73
  });
58
74
  }
@@ -718,6 +734,45 @@ function getNodeInfo({ nodeId }) {
718
734
  try { info.effects = serializeEffects(node.effects); } catch (_) {}
719
735
  }
720
736
 
737
+ // Constraints
738
+ if ("constraints" in node) {
739
+ info.constraints = {
740
+ horizontal: node.constraints.horizontal,
741
+ vertical: node.constraints.vertical
742
+ };
743
+ }
744
+
745
+ // Clips content (for frames)
746
+ if ("clipsContent" in node) info.clipsContent = node.clipsContent;
747
+
748
+ // Layout positioning within auto-layout parent
749
+ if ("layoutAlign" in node) info.layoutAlign = node.layoutAlign;
750
+ if ("layoutGrow" in node) info.layoutGrow = node.layoutGrow;
751
+ if ("layoutPositioning" in node) info.layoutPositioning = node.layoutPositioning;
752
+
753
+ // Style IDs (paint styles, text styles, effect styles)
754
+ if ("fillStyleId" in node && node.fillStyleId && node.fillStyleId !== "") {
755
+ info.fillStyleId = node.fillStyleId;
756
+ }
757
+ if ("strokeStyleId" in node && node.strokeStyleId && node.strokeStyleId !== "") {
758
+ info.strokeStyleId = node.strokeStyleId;
759
+ }
760
+ if ("effectStyleId" in node && node.effectStyleId && node.effectStyleId !== "") {
761
+ info.effectStyleId = node.effectStyleId;
762
+ }
763
+ if ("textStyleId" in node && node.textStyleId && node.textStyleId !== "") {
764
+ info.textStyleId = node.textStyleId;
765
+ }
766
+
767
+ // Mask
768
+ if ("isMask" in node) info.isMask = node.isMask;
769
+
770
+ // Min/max size
771
+ if ("minWidth" in node && node.minWidth != null) info.minWidth = node.minWidth;
772
+ if ("maxWidth" in node && node.maxWidth != null) info.maxWidth = node.maxWidth;
773
+ if ("minHeight" in node && node.minHeight != null) info.minHeight = node.minHeight;
774
+ if ("maxHeight" in node && node.maxHeight != null) info.maxHeight = node.maxHeight;
775
+
721
776
  // Auto-layout properties
722
777
  if ("layoutMode" in node && node.layoutMode !== "NONE") {
723
778
  info.autoLayout = {
@@ -731,7 +786,8 @@ function getNodeInfo({ nodeId }) {
731
786
  primaryAxisAlignItems: node.primaryAxisAlignItems,
732
787
  counterAxisAlignItems: node.counterAxisAlignItems,
733
788
  layoutSizingHorizontal: node.layoutSizingHorizontal,
734
- layoutSizingVertical: node.layoutSizingVertical
789
+ layoutSizingVertical: node.layoutSizingVertical,
790
+ layoutWrap: node.layoutWrap
735
791
  };
736
792
  }
737
793
 
@@ -783,10 +839,25 @@ function getNodeInfo({ nodeId }) {
783
839
  try {
784
840
  var bv = node.boundVariables;
785
841
  var bvResult = {};
786
- for (var key in bv) {
787
- var binding = bv[key];
842
+ var knownBVKeys = [
843
+ "fills", "strokes", "effects",
844
+ "layoutGrids", "componentProperties",
845
+ "fontSize", "fontFamily", "fontStyle", "fontWeight",
846
+ "lineHeight", "letterSpacing", "paragraphSpacing", "paragraphIndent",
847
+ "textCase", "textDecoration",
848
+ "visible", "opacity",
849
+ "topLeftRadius", "topRightRadius", "bottomLeftRadius", "bottomRightRadius",
850
+ "itemSpacing", "counterAxisSpacing",
851
+ "paddingLeft", "paddingRight", "paddingTop", "paddingBottom",
852
+ "strokeWeight", "strokeTopWeight", "strokeBottomWeight", "strokeLeftWeight", "strokeRightWeight",
853
+ "width", "height",
854
+ "minWidth", "maxWidth", "minHeight", "maxHeight",
855
+ "characters"
856
+ ];
857
+
858
+ function extractBinding(binding) {
788
859
  if (Array.isArray(binding)) {
789
- bvResult[key] = binding.map(function(b) {
860
+ return binding.map(function(b) {
790
861
  var entry = { type: b.type, id: b.id };
791
862
  try {
792
863
  var v = figma.variables.getVariableById(b.id);
@@ -795,10 +866,31 @@ function getNodeInfo({ nodeId }) {
795
866
  return entry;
796
867
  });
797
868
  } else if (binding && binding.id) {
798
- bvResult[key] = { type: binding.type, id: binding.id };
869
+ var single = { type: binding.type, id: binding.id };
799
870
  try {
800
871
  var v2 = figma.variables.getVariableById(binding.id);
801
- if (v2) { bvResult[key].name = v2.name; bvResult[key].resolvedType = v2.resolvedType; }
872
+ if (v2) { single.name = v2.name; single.resolvedType = v2.resolvedType; }
873
+ } catch (_) {}
874
+ return single;
875
+ }
876
+ return null;
877
+ }
878
+
879
+ // First try for...in (catches any enumerable keys)
880
+ for (var key in bv) {
881
+ var result = extractBinding(bv[key]);
882
+ if (result != null) bvResult[key] = result;
883
+ }
884
+ // Supplement with explicit key access (Figma proxies may not enumerate all keys)
885
+ for (var ki = 0; ki < knownBVKeys.length; ki++) {
886
+ var bvKey = knownBVKeys[ki];
887
+ if (!(bvKey in bvResult)) {
888
+ try {
889
+ var val = bv[bvKey];
890
+ if (val != null) {
891
+ var r = extractBinding(val);
892
+ if (r != null) bvResult[bvKey] = r;
893
+ }
802
894
  } catch (_) {}
803
895
  }
804
896
  }