mta-mcp 3.11.0 → 3.12.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.
- package/agents/flutter.agent.md +36 -11
- package/dist/index.js +100 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/standards/workflows/sketch-pitfalls.md +2 -1
- package/ui/sketch/README.md +121 -0
- package/ui/sketch/artboard-measure.js +2708 -0
- package/ui/sketch/component-manifest.js +148 -0
- package/ui/sketch/layout-inspector.js +589 -0
- package/ui/sketch/sketch-tools.js +3534 -0
package/agents/flutter.agent.md
CHANGED
|
@@ -24,16 +24,23 @@
|
|
|
24
24
|
|
|
25
25
|
触发词:"设计稿"、"Sketch"、"还原"、"测量"、"间距"、"UI还原"
|
|
26
26
|
|
|
27
|
-
###
|
|
27
|
+
### 自动流程(v4.6.0 统一入口)
|
|
28
28
|
|
|
29
29
|
```
|
|
30
30
|
1. 检测设计稿意图 → 提醒用户在 Sketch 选中图层
|
|
31
|
-
2. 调用
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
2. 调用 mcp_mta_mta({ skill: "sketch_measure", params: { cmd: "measure" } })
|
|
32
|
+
→ 获取已注入 _SKETCH_CMD 的完整脚本(sketch-tools.js v4.6.0)
|
|
33
|
+
3. 将返回的 script 传入 mcp_sketch_run_code({ code: script })
|
|
34
|
+
→ 执行测量,获取完整 Layout Intent JSON
|
|
35
|
+
4. 基于测量数据中的 flutter* 字段精准生成代码
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
|
|
38
|
+
**注意:**
|
|
39
|
+
- 不要手动读取 artboard-measure.js(已废弃,合并进 sketch-tools.js)
|
|
40
|
+
- 不要手动拼接 _SKETCH_CMD(由 sketch_measure skill 自动处理)
|
|
41
|
+
- 测量结果中所有颜色均包含 `flutterColor: "Color(0xAARRGGBB)"` 格式,可直接使用
|
|
42
|
+
|
|
43
|
+
### 测量数据关键字段(v4.6.0 新增带★标记)
|
|
37
44
|
|
|
38
45
|
| 字段 | 用途 | Flutter 应用 |
|
|
39
46
|
|------|------|-------------|
|
|
@@ -45,8 +52,15 @@
|
|
|
45
52
|
| `iconContentBounds` | Icon 实际路径尺寸 | 渲染用 contentSize,占位用 containerSize |
|
|
46
53
|
| `tagStyle` | Tag/标签容器样式 | background, padding, cornerRadius |
|
|
47
54
|
| `siblingIconAlignment` | 同行 Icon 对齐 | 统一 SizedBox 插槽尺寸 |
|
|
55
|
+
| ★`flutterColor` | Flutter 颜色格式 | 直接粘贴 `Color(0xAARRGGBB)` |
|
|
56
|
+
| ★`flutterBoxShadow` | 完整阴影代码 | 直接粘贴 `BoxShadow(...)` |
|
|
57
|
+
| ★`flutterBorder` | 完整边框代码 | 直接粘贴 `Border.all(...)` |
|
|
58
|
+
| ★`flutterLinearGradient` | 完整渐变代码 | 直接粘贴 `LinearGradient(...)` |
|
|
59
|
+
| ★`flutterHint` | FILL→double.infinity | 禁止硬编码宽度 |
|
|
60
|
+
| ★`flutterSvgCode` | 完整 SVG 加载代码 | 直接粘贴 `SvgPicture.asset(...)` |
|
|
61
|
+
| ★`iconFillColor` | 图标填充色 | 已含 Flutter Color 格式 |
|
|
48
62
|
|
|
49
|
-
**禁止**:未测量就凭感觉还原、硬编码尺寸、忽略 layoutIntent
|
|
63
|
+
**禁止**:未测量就凭感觉还原、硬编码尺寸、忽略 layoutIntent、手动拼接颜色十六进制
|
|
50
64
|
|
|
51
65
|
---
|
|
52
66
|
|
|
@@ -278,14 +292,14 @@ get_standard_by_id({ ids: ['flutter', 'flutter-ui-system'] })
|
|
|
278
292
|
|
|
279
293
|
### ⚠️ 强制流程(最高优先级)
|
|
280
294
|
|
|
281
|
-
**在还原任何 Sketch 设计稿前,必须先调用
|
|
295
|
+
**在还原任何 Sketch 设计稿前,必须先调用 MTA 测量技能获取数据:**
|
|
282
296
|
|
|
283
297
|
```
|
|
284
298
|
1. 用户提供 Sketch 文件 → 先提醒:"需要先在 Sketch 中选中目标图层"
|
|
285
|
-
2. 调用
|
|
286
|
-
3.
|
|
287
|
-
4.
|
|
288
|
-
5.
|
|
299
|
+
2. 调用 mcp_mta_mta({ skill: "sketch_measure", params: { cmd: "measure" } })
|
|
300
|
+
3. 将返回的 script 传入 mcp_sketch_run_code 执行
|
|
301
|
+
4. 基于测量数据中的 flutter* 字段精准还原(flutterColor、flutterBoxShadow、flutterSvgCode 等)
|
|
302
|
+
5. FILL 类型尺寸使用 flutterHint 的 double.infinity,禁止硬编码宽度
|
|
289
303
|
```
|
|
290
304
|
|
|
291
305
|
### 测量数据必备字段
|
|
@@ -303,6 +317,13 @@ get_standard_by_id({ ids: ['flutter', 'flutter-ui-system'] })
|
|
|
303
317
|
| `tagStyle` | Tag 容器完整样式 | bg/padding/cornerRadius 精确还原 |
|
|
304
318
|
| `siblingIconAlignment` | 同行 Icon 统一尺寸 | maxSlotSize→统一 SizedBox |
|
|
305
319
|
| `fontName` | PostScript 字体名 | 正确映射 FontWeight(防合成加粗) |
|
|
320
|
+
| `flutterColor` | Flutter 颜色格式 | 直接粘贴 Color(0xAARRGGBB) |
|
|
321
|
+
| `flutterBoxShadow` | 完整阴影代码 | 直接粘贴 BoxShadow(...) |
|
|
322
|
+
| `flutterBorder` | 完整边框代码 | 直接粘贴 Border.all(...) |
|
|
323
|
+
| `flutterLinearGradient` | 完整渐变代码 | 直接粘贴 LinearGradient(...) |
|
|
324
|
+
| `flutterHint` | 自适应宽度提示 | double.infinity + MediaQuery |
|
|
325
|
+
| `flutterSvgCode` | 完整 SVG 代码 | 直接粘贴 SvgPicture.asset(...) + ColorFilter |
|
|
326
|
+
| `iconFillColor` | 图标填充色 | 已含 flutterColor 格式 |
|
|
306
327
|
|
|
307
328
|
### 还原检查清单
|
|
308
329
|
|
|
@@ -319,6 +340,10 @@ get_standard_by_id({ ids: ['flutter', 'flutter-ui-system'] })
|
|
|
319
340
|
- [ ] **Tag 容器使用测量的 padding/bg/cornerRadius**(防样式猜测)
|
|
320
341
|
- [ ] **字体权重检查平台可用性**(PingFang≤w600, Helvetica≤w700)
|
|
321
342
|
- [ ] **只还原测量数据中存在的元素**(防添加幽灵元素)
|
|
343
|
+
- [ ] **优先使用 flutter* 字段**(flutterColor、flutterBoxShadow、flutterLinearGradient 等直接粘贴)
|
|
344
|
+
- [ ] **图标使用 flutterSvgCode**(含精确颜色和尺寸,禁止用 Icons.xxx 替代自定义 SVG)
|
|
345
|
+
- [ ] **FILL 类型尺寸使用 flutterHint**(double.infinity,禁止硬编码固定宽度)
|
|
346
|
+
- [ ] **边框使用 flutterBorder**(禁止忽略 borders 数据)
|
|
322
347
|
|
|
323
348
|
### ⚠️ 常见陷阱(必读)
|
|
324
349
|
|
package/dist/index.js
CHANGED
|
@@ -6030,6 +6030,90 @@ function getSkillRegistry() {
|
|
|
6030
6030
|
return globalRegistry;
|
|
6031
6031
|
}
|
|
6032
6032
|
|
|
6033
|
+
// src/tools/sketchMeasure.ts
|
|
6034
|
+
import * as fs19 from "fs";
|
|
6035
|
+
import * as path19 from "path";
|
|
6036
|
+
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
6037
|
+
var __filename8 = fileURLToPath8(import.meta.url);
|
|
6038
|
+
var __dirname8 = path19.dirname(__filename8);
|
|
6039
|
+
var SKETCH_TOOLS_PATHS = [
|
|
6040
|
+
path19.resolve(__dirname8, "../ui/sketch/sketch-tools.js"),
|
|
6041
|
+
path19.resolve(__dirname8, "../../ui/sketch/sketch-tools.js")
|
|
6042
|
+
];
|
|
6043
|
+
var VALID_CMDS = ["measure", "layout", "style", "svg", "auto"];
|
|
6044
|
+
function findSketchTools() {
|
|
6045
|
+
for (const p of SKETCH_TOOLS_PATHS) {
|
|
6046
|
+
if (fs19.existsSync(p)) {
|
|
6047
|
+
return p;
|
|
6048
|
+
}
|
|
6049
|
+
}
|
|
6050
|
+
return null;
|
|
6051
|
+
}
|
|
6052
|
+
async function sketchMeasure(args) {
|
|
6053
|
+
const cmd = args.cmd || "measure";
|
|
6054
|
+
if (!VALID_CMDS.includes(cmd)) {
|
|
6055
|
+
return {
|
|
6056
|
+
content: [{
|
|
6057
|
+
type: "text",
|
|
6058
|
+
text: JSON.stringify({
|
|
6059
|
+
error: `\u65E0\u6548\u7684 cmd \u53C2\u6570: "${cmd}"`,
|
|
6060
|
+
validValues: VALID_CMDS,
|
|
6061
|
+
usage: 'mcp_mta_mta({ skill: "sketch_measure", params: { cmd: "measure" } })'
|
|
6062
|
+
}, null, 2)
|
|
6063
|
+
}]
|
|
6064
|
+
};
|
|
6065
|
+
}
|
|
6066
|
+
const toolPath = findSketchTools();
|
|
6067
|
+
if (!toolPath) {
|
|
6068
|
+
return {
|
|
6069
|
+
content: [{
|
|
6070
|
+
type: "text",
|
|
6071
|
+
text: JSON.stringify({
|
|
6072
|
+
error: "sketch-tools.js \u6587\u4EF6\u672A\u627E\u5230",
|
|
6073
|
+
searchedPaths: SKETCH_TOOLS_PATHS,
|
|
6074
|
+
solution: "\u8BF7\u786E\u8BA4 mcp-server/ui/sketch/sketch-tools.js \u6587\u4EF6\u5B58\u5728"
|
|
6075
|
+
}, null, 2)
|
|
6076
|
+
}]
|
|
6077
|
+
};
|
|
6078
|
+
}
|
|
6079
|
+
const scriptContent = fs19.readFileSync(toolPath, "utf-8");
|
|
6080
|
+
const versionMatch = scriptContent.match(/@version\s+([\d.]+)/);
|
|
6081
|
+
const version = versionMatch ? versionMatch[1] : "unknown";
|
|
6082
|
+
const cmdLine = `var _SKETCH_CMD = '${cmd}';`;
|
|
6083
|
+
const fullScript = cmdLine + "\n" + scriptContent;
|
|
6084
|
+
return {
|
|
6085
|
+
content: [{
|
|
6086
|
+
type: "text",
|
|
6087
|
+
text: JSON.stringify({
|
|
6088
|
+
status: "ready",
|
|
6089
|
+
version,
|
|
6090
|
+
cmd,
|
|
6091
|
+
scriptLength: fullScript.length,
|
|
6092
|
+
instruction: "\u5C06 script \u5B57\u6BB5\u7684\u5185\u5BB9\u4F20\u5165 mcp_sketch_run_code({ code: script }) \u6267\u884C\u3002\u6267\u884C\u524D\u8BF7\u786E\u8BA4\u7528\u6237\u5DF2\u5728 Sketch \u4E2D\u9009\u4E2D\u4E86\u76EE\u6807\u753B\u677F/\u56FE\u5C42\u3002",
|
|
6093
|
+
cmdDescription: {
|
|
6094
|
+
measure: "\u5B8C\u6574\u753B\u677F\u6D4B\u91CF - \u83B7\u53D6\u6240\u6709\u56FE\u5C42\u6837\u5F0F\u3001\u5C3A\u5BF8\u3001\u95F4\u8DDD\u3001\u989C\u8272\uFF08\u9009\u4E2D\u753B\u677F/Frame\uFF09",
|
|
6095
|
+
layout: "\u5E03\u5C40\u5206\u6790 - \u5206\u6790\u5BB9\u5668\u5B50\u5143\u7D20\u6392\u5217\uFF0C\u6216\u4E24\u4E2A\u56FE\u5C42\u7684\u76F8\u5BF9\u4F4D\u7F6E",
|
|
6096
|
+
style: "\u6837\u5F0F\u5FEB\u68C0 - \u5FEB\u901F\u68C0\u67E5\u9009\u4E2D\u7EC4\u4EF6\u7684\u586B\u5145\u8272\u3001\u9634\u5F71\u3001\u6587\u5B57\u6837\u5F0F",
|
|
6097
|
+
svg: "\u56FE\u6807\u5BFC\u51FA - \u5BFC\u51FA\u9009\u4E2D\u7684\u77E2\u91CF\u56FE\u4E3A SVG",
|
|
6098
|
+
auto: "\u81EA\u52A8\u6A21\u5F0F - \u6839\u636E\u9009\u4E2D\u5185\u5BB9\u81EA\u52A8\u9009\u62E9\u6D4B\u91CF\u6216\u6837\u5F0F\u6A21\u5F0F"
|
|
6099
|
+
}[cmd],
|
|
6100
|
+
v460Features: [
|
|
6101
|
+
"flutterColor - \u6240\u6709\u989C\u8272\u8F93\u51FA Flutter Color(0xAARRGGBB) \u683C\u5F0F\uFF0C\u53EF\u76F4\u63A5\u7C98\u8D34",
|
|
6102
|
+
"flutterBoxShadow - \u9634\u5F71\u8F93\u51FA\u5B8C\u6574 BoxShadow(...) \u4EE3\u7801",
|
|
6103
|
+
"flutterBorder - \u8FB9\u6846\u8F93\u51FA\u5B8C\u6574 Border.all(...) \u4EE3\u7801",
|
|
6104
|
+
"flutterLinearGradient - \u6E10\u53D8\u8F93\u51FA\u5B8C\u6574 LinearGradient(...) \u4EE3\u7801",
|
|
6105
|
+
"flutterHint - FILL/MATCH_PARENT \u5C3A\u5BF8\u8F93\u51FA double.infinity \u63D0\u793A",
|
|
6106
|
+
"flutterSvgCode - \u56FE\u6807\u8F93\u51FA\u5B8C\u6574 SvgPicture.asset(...) \u4EE3\u7801\uFF0C\u542B\u7CBE\u786E\u7684\u989C\u8272\u548C\u5C3A\u5BF8",
|
|
6107
|
+
"\u5168\u8986\u76D6\u5F62\u72B6\u6392\u9664 - \u80CC\u666F\u5706\u89D2\u77E9\u5F62\u4E0D\u518D\u88AB\u8BEF\u5224\u4E3A\u56FE\u6807"
|
|
6108
|
+
]
|
|
6109
|
+
}, null, 2)
|
|
6110
|
+
}, {
|
|
6111
|
+
type: "text",
|
|
6112
|
+
text: fullScript
|
|
6113
|
+
}]
|
|
6114
|
+
};
|
|
6115
|
+
}
|
|
6116
|
+
|
|
6033
6117
|
// src/tools/skillDefinitions.ts
|
|
6034
6118
|
function wrapAsContent(data) {
|
|
6035
6119
|
return {
|
|
@@ -6360,6 +6444,22 @@ var skillDefinitions = [
|
|
|
6360
6444
|
return wrapAsContent(await listTroubleshootingCases(params.framework));
|
|
6361
6445
|
}
|
|
6362
6446
|
}
|
|
6447
|
+
},
|
|
6448
|
+
// ==================== Sketch 设计稿工具类 ====================
|
|
6449
|
+
{
|
|
6450
|
+
name: "sketch_measure",
|
|
6451
|
+
category: "sketch",
|
|
6452
|
+
description: "\u83B7\u53D6 Sketch \u6D4B\u91CF\u811A\u672C\uFF08sketch-tools.js v4.6.0\uFF09\u3002\u8FD4\u56DE\u5DF2\u6CE8\u5165 _SKETCH_CMD \u7684\u5B8C\u6574\u811A\u672C\uFF0C\u53EF\u76F4\u63A5\u4F20\u5165 mcp_sketch_run_code \u6267\u884C\u3002\u652F\u6301 measure(\u5B8C\u6574\u753B\u677F\u6D4B\u91CF)\u3001layout(\u5E03\u5C40\u5206\u6790)\u3001style(\u6837\u5F0F\u5FEB\u68C0)\u3001svg(\u56FE\u6807\u5BFC\u51FA)\u3001auto(\u81EA\u52A8\u6A21\u5F0F)",
|
|
6453
|
+
paramHints: [
|
|
6454
|
+
{ name: "cmd", type: "string", description: "\u6267\u884C\u6A21\u5F0F: measure(\u9ED8\u8BA4\uFF0C\u5B8C\u6574\u753B\u677F) / layout(\u5E03\u5C40\u5206\u6790) / style(\u6837\u5F0F\u68C0\u67E5) / svg(\u56FE\u6807\u5BFC\u51FA) / auto(\u81EA\u52A8\u5224\u65AD)" },
|
|
6455
|
+
{ name: "outputPath", type: "string", description: "SVG \u8F93\u51FA\u8DEF\u5F84\uFF08\u4EC5 cmd=svg \u65F6\u4F7F\u7528\uFF09" }
|
|
6456
|
+
],
|
|
6457
|
+
handler: async (params) => {
|
|
6458
|
+
return sketchMeasure({
|
|
6459
|
+
cmd: params.cmd,
|
|
6460
|
+
outputPath: params.outputPath
|
|
6461
|
+
});
|
|
6462
|
+
}
|
|
6363
6463
|
}
|
|
6364
6464
|
];
|
|
6365
6465
|
|