| name | pencil-mcp-api |
| description | Pencil MCP API reference — tool list, batch_design/batch_get API, design patterns, icon specs, colors, common pitfalls. Referenced by pencil-design skill. |
Pencil MCP API Reference
本 Skill 为 pencil-design 的技术参考子模块,包含 MCP 工具列表、API 详解、设计模式、图标规范、颜色变量、常见陷阱等。不需要直接调用,由 pencil-design 按需引用。
一、MCP 工具列表
| 工具名称 | 用途 |
|---|
mcp__pencil__get_editor_state | 获取当前画布编辑状态、用户选择、.pen schema |
mcp__pencil__get_guidelines | 加载设计指南 (guide) 和样式规范 (style) |
mcp__pencil__batch_get | 批量读取节点信息(支持搜索模式和节点 ID 查询) |
mcp__pencil__batch_design | 批量执行设计操作(核心工具,JS 代码片段) |
mcp__pencil__snapshot_layout | 检查布局结构、定位重叠/裁剪问题 |
mcp__pencil__get_screenshot | 获取节点截图(用于视觉验证) |
mcp__pencil__get_variables | 获取 .pen 文件的设计变量和主题 |
mcp__pencil__set_variables | 设置/更新 .pen 文件的设计变量 |
mcp__pencil__export_nodes | 导出节点为 PNG/JPEG/WEBP/PDF |
关键参数:所有工具(除 get_editor_state 外)都需要 filePath 参数指定 .pen 文件路径。始终使用绝对路径。
二、batch_design API 详解
batch_design 是核心操作工具,接收一段 JS 代码片段在文档上执行修改。
2.1 可用函数
const document: string;
Insert(parent: string, nodeData: Schema.Child): string;
Copy(path: string, parent: string, copyNodeData: Schema.Child): string;
Update(path: string, updateData: Schema.Child): void;
Replace(path: string, nodeData: Schema.Child): string;
Move(path: string, parent: string | undefined, index?: number): void;
Delete(path: string): void;
Generate(nodeId: string, type: "ai" | "stock", prompt: string): void;
FindEmptySpace(input: {
width: number; height: number;
direction?: "top" | "right" | "bottom" | "left";
padding?: number;
nodeId?: string;
}): { x: number; y: number; parentId?: string };
2.2 path 参数
Copy、Update、Replace、Move、Delete 的 path 参数:
- 普通节点:直接使用节点 ID,如
"abc123"
- 组件实例内子节点:使用斜杠路径,如
"instanceId/childId"
- 斜杠仅用于组件实例嵌套,普通层级关系不可用斜杠
2.3 关键约束
- 每个
batch_design 调用在独立作用域执行,local 变量不跨批次共享
- 同一批次内用
bindingName = Insert(...) 创建的 binding 可在后续同批次操作中使用
- 批次返回后 binding 失效,后续批次须使用返回结果中的实际 node ID
- 绝对不可在创建节点时手动设置
id 属性 — Pencil 自动生成唯一 ID
- 每个节点必须设置
name 属性(可读名称),返回结果会包含 name→id 映射
- 建议每批次不超过 25 个操作
padding 属性只在 type: "frame" 上有效,不能给 text、rectangle 等设置 padding
- 当父容器使用
layout: "vertical" 或 "horizontal" 时,子节点的 x/y 属性完全被忽略
三、batch_get 详解
用于读取节点信息,是理解现有设计结构的核心工具。
3.1 参数
| 参数 | 说明 |
|---|
filePath | .pen 文件绝对路径 |
nodeIds | 按 ID 读取的节点列表 |
patterns | 搜索模式数组:{name?, type?, reusable?} |
readDepth | 读取深度(默认 1,即只含直接子节点) |
searchDepth | 搜索深度限制 |
resolveInstances | 展开组件实例(默认 false) |
resolveVariables | 显示变量计算值而非引用名(默认 false) |
includePathGeometry | 包含 path 节点的完整几何数据(默认 false) |
3.2 常用模式
batch_get({filePath, nodeIds: ["abc123"], readDepth: 2})
batch_get({filePath, patterns: [{reusable: true}], readDepth: 2, searchDepth: 3})
batch_get({filePath, patterns: [{type: "frame", name: "Button"}], readDepth: 2})
四、核心设计模式
4.1 布局转换模式(absolute → flexbox)
将旧式 layout: "none" + 绝对定位的布局改为现代 flexbox 布局:
batch_get({filePath, nodeIds: ["parentId"], readDepth: 3})
Update("parentId", {layout: "vertical", alignItems: "center", gap: 6, width: "fit_content", height: "fit_content"})
newBg = Replace("oldChildId", {type: "frame", name: "NewBg", width: 48, height: 48, cornerRadius: 14, fill: "#E8EDF5", justifyContent: "center", alignItems: "center"})
Insert(newBg, {type: "icon", name: "Icon", library: "lucide", icon: "star", width: 24, height: 24, fill: "#2D3E5F"})
Update("oldTextId", {fill: "#777777", textGrowth: "auto"})
关键点:
- 父容器从
layout: "none" 改为 layout: "vertical" 后,子节点的 x/y 自动被忽略
- 原来
textGrowth: "fixed-width-height" 的文本需改为 textGrowth: "auto" 以适应 flexbox
- 使用
Replace + Insert 两连击来创建嵌套结构(如带背景的图标)
4.2 批量属性替换模式
适用场景:统一修改多个同级节点的颜色、字体等属性:
Update("icon1Id", {fill: "#2D3E5F"})
Update("icon2Id", {fill: "#2D3E5F"})
Update("icon3Id", {fill: "#2D3E5F"})
Update("icon4Id", {fill: "#2D3E5F"})
4.3 组件实例模式(ref)
创建可复用组件并用 ref 实例化:
card = Insert(document, {type: "frame", name: "Card", reusable: true, layout: "vertical", gap: 8, ...})
cardTitle = Insert(card, {type: "text", name: "Title", ...})
cardDesc = Insert(card, {type: "text", name: "Desc", ...})
Insert(row, {type: "ref", ref: "returnedCardId", name: "Card Instance", width: "fill_container",
descendants: {
"returnedTitleId": {content: "自定义标题"},
"returnedDescId": {content: "自定义描述"}
}
})
4.4 Copy+Replace 页面创建模式
快速基于已有页面创建新页面:
pos = FindEmptySpace({width: 375, height: 812, padding: 80})
newPage = Copy("sourcePageId", document, {name: "新页面", x: pos.x, y: pos.y, placeholder: true,
descendants: {
"oldTitleId": {content: "新标题"},
"oldIconId": {fill: "#2D3E5F"}
}
})
Update(newPage, {placeholder: false})
4.5 模态框/弹窗模式
弹窗必须创建为 document 的直接子节点,不可嵌套在页面 frame 内:
overlay = Insert(document, {type: "rectangle", name: "Overlay", x: pageX, y: 0, width: 375, height: 812, fill: "#000000", opacity: 0.5})
dialog = Insert(document, {type: "frame", name: "Dialog", layout: "vertical", gap: 16, width: 320, fill: "#FFFFFF", cornerRadius: 16, padding: 24, x: pageX + 27, y: 200})
五、图标使用规范
5.1 Lucide 图标
Pencil 支持 lucide 图标库。使用前须确认图标名在 lucide 中存在。
已验证可用的图标:
trophy, rotate-ccw, star, house, book-open, user, chart-column, settings, search, plus, check, x, chevron-right, chevron-left, arrow-right, bell, calendar, clock, edit, trash, share, download, upload, heart, bookmark, flag, map-pin, phone, mail, lock, unlock
已验证不可用的图标:
bar-chart → 改用 chart-column
图标节点格式:
{type: "icon", name: "IconName", library: "lucide", icon: "trophy", width: 24, height: 24, fill: "#2D3E5F"}
5.2 图标最佳实践
- 图标应放在带背景色的圆角容器中(现代设计规范)
- 容器典型尺寸:44-48px,cornerRadius: 12-14
- 图标典型尺寸:22-24px(在容器中居中)
- 容器使用 flexbox:
justifyContent: "center", alignItems: "center"
5.3 素材图片/ICON 生成流程(强制)
强制规则:所有素材图片和 ICON 不得使用 emoji,必须由 AI 生成后经去背景处理。emoji 在不同设备/系统上表现不一致,不可用于设计稿。
完整流程(三步):
步骤 1:AI 生图
使用 Generate 函数在 Pencil 中生成 icon 图片。背景色统一使用绿色(#7FB77E)或白色(#FFFFFF),色值固定:
Generate("targetNodeId", "ai", "a simple flat icon of [具体描述], on a pure #FFFFFF white background, centered, vector clipart style")
Generate("targetNodeId", "ai", "a simple flat icon of [具体描述], on a pure #7FB77E green background, centered, vector clipart style")
约束:
- 统一使用
#7FB77E(绿色)或 #FFFFFF(白色)作为生图背景色,不可使用其他颜色
- 提示词中明确写死色值,不要写 "green" 或 "white" 这种模糊描述
- 不要尝试在 AI 生图阶段要求透明背景 — AI 生图工具不支持直接生成透明 PNG,棋盘格背景实质是白色填充
步骤 2:导出 PNG 并去背景
- 使用
export_nodes 将节点导出为 PNG 文件到 doc/images/ 目录
- 使用通用去背景脚本去除白色/绿色背景,生成带 alpha 通道的透明 PNG
使用通用去背景脚本(位于 .trae/skills/pencil-mcp/pencil-mcp-api/remove_bg.py):
python3 .trae/skills/pencil-mcp/pencil-mcp-api/remove_bg.py --dir ./doc/images
python3 .trae/skills/pencil-mcp/pencil-mcp-api/remove_bg.py --dir ./doc/images --color green --threshold 40
python3 .trae/skills/pencil-mcp/pencil-mcp-api/remove_bg.py --dir ./doc/images --pattern "icon-*.png"
python3 .trae/skills/pencil-mcp/pencil-mcp-api/remove_bg.py --dir ./doc/images --threshold 15
参数说明:
| 参数 | 必填 | 默认值 | 说明 |
|---|
--dir | 是 | - | 图片目录路径 |
--pattern | 否 | *.png | 文件名 glob 匹配模式 |
--color | 否 | white | 要去除的背景色:white 或 green |
--threshold | 否 | 25 | 颜色容差 0-255 |
颜色对照表:
| 目标背景色 | RGB 值 | threshold 建议 |
|---|
白色 #FFFFFF | (255, 255, 255) | 10-30 |
绿色 #7FB77E | (127, 183, 126) | 40-60 |
threshold 调优:去背景后边缘有残留 → 降低 threshold;图标主体被误删 → 提高 threshold。
步骤 3:重新应用到 .pen 文件
Update("iconNodeId", {
fill: { type: "image", enabled: true, url: "./images/icon-name-transparent.png", mode: "fill" }
})
注意事项:
- AI 生图是异步的,生成后需等待图片出现再导出
- 如果 AI 生图效果不理想,应重新生成而非放弃,调整提示词细化描述即可
- 同一组 icon 应在同一批次生成,确保风格一致
- 去背景后的透明 PNG 建议统一命名:
icon-{类型}-transparent.png
六、颜色与变量
6.1 设计变量
通过 get_variables(filePath) 获取。变量名带 $ 前缀:
{"$primary": {"type": "color", "value": "#2D3E5F"}, ...}
6.2 变量引用(谨慎使用)
在 batch_design 中可使用 "$primary" 引用变量,但在新版本 MCP 中解析不稳定。
推荐做法:直接从 get_variables 获取 hex 值,使用硬编码颜色:
Update("nodeId", {fill: "#2D3E5F"})
6.3 颜色约束
fill: "transparent" 不支持 → 用 "#00000000"
fill: "none" 不支持 → 用 "#00000000"
- 颜色格式:
#RGB, #RRGGBB, #RRGGBBAA
七、常见陷阱
| # | 现象 | 原因 | 解决 |
|---|
| 0 | 多个顶层 frame 堆叠重叠 | 新建 frame 默认坐标均为 (0,0),未手动设置位置 | 分批使用 FindEmptySpace → Update:每批只处理一个 frame,因为 FindEmptySpace 会考虑已放置的节点,分批执行才能确保每批找到不同位置。完成后用 snapshot_layout({maxDepth: 0}) 验证坐标无重叠。 |
| 1 | fill: "$primary" 显示为 "#000000" | 变量引用无声失败 | 使用硬编码 hex 值 |
| 2 | fill: "transparent" 报错 | 非法 fill 值 | 使用 "#00000000" |
| 3 | 图标显示为方块/缺失 | lucide 图标名不存在 | 参考 §5.1 已验证列表 |
| 4 | 布局坍塌/元素消失 | fit_content + fill_container 循环依赖 | 父容器设置显式尺寸 |
| 5 | batch_design 返回空 | 操作 >25 个 / 非法属性值 | 拆分为更小批次 |
| 6 | Node 'xxx' not found! | 多轮修改后节点 ID 变化 | 重新 batch_get 获取最新 ID |
| 7 | path/ellipse 元素不能应用图片 fill | 装饰元素类型不支持 | 用 Replace 改为 frame 类型 |
| 8 | 文本不换行 / 溢出 | textGrowth 设置不当 | 换行用 "fixed-width" |
| 9 | x/y 设置无效 | 父容器是 flexbox 布局 | 不要同时设置 flexbox + x/y |
| 10 | padding 设置无效 | 节点类型非 frame | padding 仅 frame 可用 |
八、layout 检查清单
每轮设计修改后,用 snapshot_layout 验证:
- 布局未坍塌:所有节点都有合理的 width/height(非 0)
- 内容未被裁剪:无
"problems": "clipped" 标记
- 间距合理:相邻区块间距一致(通常 8-16px)
- 无重叠:同级节点位置无冲突
- 页面高度匹配:内容不超过页面 frame 高度(clip: true 时会被裁掉)
九、效率建议
- 先读后写:每次修改前用
batch_get 了解当前结构,避免盲操作
- 批量操作:每批 15-25 个操作,减少工具调用轮次
- 先验证再继续:每轮修改后用
batch_get 确认属性,必要时用 get_screenshot 看视觉效果
- 设计 token 先获取:
get_variables 拿到颜色/间距值后直接硬编码,避免变量引用问题
- 图标先验证:不确定图标名是否存在时,先用单次
Insert 试错再批量操作
- 布局转换一次性完成:将 absolute → flexbox 的所有操作放在同一个
batch_design 中
- 弹窗放 document 根:弹窗/叠层必须是 document 直接子节点,不可嵌套在页面 frame 内
- 素材复用:同类卡片/背景共用同一张图片素材,避免风格不一致
十、文件存放规范
project/
├── doc/
│ ├── UXDesign/
│ │ ├── design.pen # 主设计稿
│ │ ├── demo.pen # 设计样图/试稿
│ │ └── images/ # 图片素材目录
│ │ ├── icon-xxx.png
│ │ ├── icon-xxx-transparent.png
│ │ ├── bg_xxx.png
│ │ └── deco_xxx.png
│ └── interaction-design.md # 交互设计文稿
图片引用使用相对于 .pen 文件的路径:./images/icon-name-transparent.png