Summary
Add a bulk property-replace tool to the FrameSmith MCP so a single call can update a property across many nodes at once — analogous to Pencil's replace_all_matching_properties.
Motivation
Today batch_design only edits nodes by explicit id (U("nodeId", {...})). When you need the same change across many nodes there's no shortcut — you hand-write one U(...) per node.
Concrete example from real use: making a ~17-row data table fill its container meant setting width: "100%" on every cell of 4 columns — 68 individual U() ops in one batch, after manually gathering all 68 node ids. A single "set width→100% on all nodes currently width:110" call would have been one line.
canvas_autofix covers the mechanical spacing/scale subset, but there's no general "find nodes matching property X, set property Y" primitive.
Proposed API
A new tool, e.g. replace_matching_properties:
replace_matching_properties({
canvasId,
match: { width: 110 }, // property/value predicate (AND across keys)
set: { width: "100%" }, // properties to write
scope?: "nodeId", // optional subtree to limit to (default: whole doc)
type?: "text" | "frame" | ... // optional node-type filter
dryRun?: true // return the matched node ids + count without writing
})
Returns the list of affected node ids and a count (mirrors batch_design's result shape).
Notes / niceties
dryRun is valuable for safety — preview the match set before committing, since a value like width: 150 can match more nodes than intended.
- A
type and/or scope filter avoids collateral hits (e.g. only table cells, not the whole canvas).
- Matching on token references (e.g.
fill: "$secondary-container") as well as literals would be handy.
- Pencil's MCP already ships
replace_all_matching_properties / search_all_unique_properties — worth looking at for prior art (the search companion that enumerates the distinct values in use pairs naturally with this).
Workaround today
Enumerate the node ids and emit one U(...) per node in a batch_design call. Works, but is O(n) to author and error-prone for large tables.
Summary
Add a bulk property-replace tool to the FrameSmith MCP so a single call can update a property across many nodes at once — analogous to Pencil's
replace_all_matching_properties.Motivation
Today
batch_designonly edits nodes by explicit id (U("nodeId", {...})). When you need the same change across many nodes there's no shortcut — you hand-write oneU(...)per node.Concrete example from real use: making a ~17-row data table fill its container meant setting
width: "100%"on every cell of 4 columns — 68 individualU()ops in one batch, after manually gathering all 68 node ids. A single "set width→100% on all nodes currently width:110" call would have been one line.canvas_autofixcovers the mechanical spacing/scale subset, but there's no general "find nodes matching property X, set property Y" primitive.Proposed API
A new tool, e.g.
replace_matching_properties:Returns the list of affected node ids and a count (mirrors
batch_design's result shape).Notes / niceties
dryRunis valuable for safety — preview the match set before committing, since a value likewidth: 150can match more nodes than intended.typeand/orscopefilter avoids collateral hits (e.g. only table cells, not the whole canvas).fill: "$secondary-container") as well as literals would be handy.replace_all_matching_properties/search_all_unique_properties— worth looking at for prior art (the search companion that enumerates the distinct values in use pairs naturally with this).Workaround today
Enumerate the node ids and emit one
U(...)per node in abatch_designcall. Works, but is O(n) to author and error-prone for large tables.