@refore-ai/html-to-figma-mcp 0.3.0 → 0.3.1
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/index.mjs +46 -15
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -18,25 +18,49 @@ import { Server } from "socket.io";
|
|
|
18
18
|
* 往这里加东西前先确认它满足这两条,否则放别处。
|
|
19
19
|
*/
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* 与同目录 `platform.ts` 的 `PLATFORM_NAME` 不是一回事 —— 那份给插件 UI 用,jsdesign 显示
|
|
24
|
-
* 「即时设计」,且末尾已按 `__PLATFORM__` 取过值,是单个字符串而非表。
|
|
21
|
+
* 平台叫法的唯一登记处:`name` 是英文主名,`zhName` 是中文名,`otherNames` 是其余写法。
|
|
22
|
+
* 下面几张表都从这里派生。
|
|
25
23
|
*/
|
|
26
|
-
const
|
|
27
|
-
figma: "Figma",
|
|
28
|
-
mastergo: "MasterGo",
|
|
29
|
-
jsdesign:
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const PLATFORM_NAMING = {
|
|
25
|
+
figma: { name: "Figma" },
|
|
26
|
+
mastergo: { name: "MasterGo" },
|
|
27
|
+
jsdesign: {
|
|
28
|
+
name: "JSDesign",
|
|
29
|
+
zhName: "即时设计",
|
|
30
|
+
otherNames: ["js.design"]
|
|
31
|
+
},
|
|
32
|
+
"pixso-china": { name: "Pixso" },
|
|
33
|
+
"pixso-world": { name: "Pixso" }
|
|
32
34
|
};
|
|
35
|
+
function mapPlatforms(pick) {
|
|
36
|
+
return Object.fromEntries(Object.entries(PLATFORM_NAMING).map(([platform, naming]) => [platform, pick(naming)]));
|
|
37
|
+
}
|
|
38
|
+
mapPlatforms((naming) => naming.name);
|
|
39
|
+
/**
|
|
40
|
+
* 平台展示名:有中文名的写成「JSDesign(即时设计)」。
|
|
41
|
+
*
|
|
42
|
+
* 凡是被读的正文都用这份 —— agent 侧的工具描述与 instructions、npm README 里的说明文字。
|
|
43
|
+
* 用户嘴里说的是中文名,只给英文名,读的人(和 agent)认不出说的是同一个平台。
|
|
44
|
+
*/
|
|
45
|
+
const MCP_PLATFORM_DISPLAY_NAMES = mapPlatforms((naming) => naming.zhName ? `${naming.name}(${naming.zhName})` : naming.name);
|
|
46
|
+
/**
|
|
47
|
+
* 平台的全部叫法,主名在前。路由用(server instructions 的触发词):用户说哪个叫法都要落到
|
|
48
|
+
* 同一台 MCP,检索语料里没有的那个叫法就等于没这台 MCP。
|
|
49
|
+
*/
|
|
50
|
+
const MCP_PLATFORM_ALL_NAMES = mapPlatforms((naming) => [
|
|
51
|
+
naming.name,
|
|
52
|
+
...naming.zhName ? [naming.zhName] : [],
|
|
53
|
+
...naming.otherNames ?? []
|
|
54
|
+
]);
|
|
33
55
|
//#endregion
|
|
34
56
|
//#region src/platform.ts
|
|
35
57
|
const MCP_PLATFORM = "figma";
|
|
36
58
|
/** 从源 package.json 的 version 由 tsdown define 注入;测试环境未注入 → 兜底 '0.0.0-dev' */
|
|
37
|
-
const MCP_SERVER_VERSION = "0.3.
|
|
38
|
-
/** 面向 agent
|
|
39
|
-
const MCP_PLATFORM_NAME =
|
|
59
|
+
const MCP_SERVER_VERSION = "0.3.1";
|
|
60
|
+
/** 面向 agent 的平台展示名(用于工具描述等),中文名一并带上 */
|
|
61
|
+
const MCP_PLATFORM_NAME = MCP_PLATFORM_DISPLAY_NAMES[MCP_PLATFORM];
|
|
62
|
+
/** 本平台的全部叫法,主名在前:路由用,不是展示用 */
|
|
63
|
+
const MCP_PLATFORM_TRIGGER_NAMES = MCP_PLATFORM_ALL_NAMES[MCP_PLATFORM];
|
|
40
64
|
/** 本 MCP server 的包名 / 日志前缀基名 */
|
|
41
65
|
const MCP_SERVER_NAME = `html-to-${MCP_PLATFORM}-mcp`;
|
|
42
66
|
/** stdout 归 MCP JSON-RPC 独占,本进程所有日志走 stderr */
|
|
@@ -664,7 +688,7 @@ actually open in the browser (no login state, no interaction state).
|
|
|
664
688
|
the taskId immediately), keep walking the flow and capture state N+1 while the plugin imports
|
|
665
689
|
(its task queue is serial), then wait_task(N) and verify state N — any failure costs at most one
|
|
666
690
|
wasted capture instead of N.
|
|
667
|
-
- Verification runs entirely on the
|
|
691
|
+
- Verification runs entirely on the ${MCP_PLATFORM_NAME} side (get_nodes + export_node_image) against
|
|
668
692
|
the baseline you froze at capture time — the browser never needs to navigate back. Take a
|
|
669
693
|
viewport screenshot of the page right when you capture it, as the comparison baseline. Check:
|
|
670
694
|
visibleAreaRatio is 1 and the root size matches the viewport; the exported image has no large
|
|
@@ -1004,8 +1028,15 @@ function registerTools(server, hub, options = {}) {
|
|
|
1004
1028
|
* 截断);Codex 把它渲染进 tool_search 的来源清单并计入 BM25 检索语料(plugin 形态只保留
|
|
1005
1029
|
* 前 1000 字节)。因此路由声明必须是第一句、全文不得超过 1000 字节(有测试锁定);中文
|
|
1006
1030
|
* 触发词是给 BM25 命中中文 query 用的——其余语料全是英文,纯中文搜索词否则一个都对不上。
|
|
1031
|
+
*
|
|
1032
|
+
* 中文触发词按 `triggerNames` 的每个叫法各写一遍,且写成「导入到X」的连写形态、当中不留
|
|
1033
|
+
* 空格,与用户的原句逐字一致:按空白切词的检索器会把「导入到 JSDesign」切成两个 token,
|
|
1034
|
+
* 连着写的 query 一个都对不上,语料里缺席的那个叫法就等于没这台 MCP。
|
|
1007
1035
|
*/
|
|
1008
|
-
|
|
1036
|
+
function buildServerInstructions(platformName, triggerNames) {
|
|
1037
|
+
return `Use this MCP whenever the user asks to import, convert or restore a web page, URL, or HTML into ${platformName} (中文指令如「把网页/URL/HTML ${triggerNames.map((name) => `导入到${name}`).join("/")}」,产品名「网页转设计」). A local HTML file the user hands you goes straight to import_html with source:"user-file" — no browser, no capture guide. For web pages, capturing is part of walking the flow, not a phase after it: call get_capture_guide BEFORE opening the first target page, then capture and import each page/state the moment you first reach it (submit with wait:false, keep walking while the plugin imports, then wait_task the previous submission). Never walk the whole flow to the end and only then start capturing — the second walk doubles the work and interaction states may not be reproducible on re-navigation.`;
|
|
1038
|
+
}
|
|
1039
|
+
const SERVER_INSTRUCTIONS = buildServerInstructions(MCP_PLATFORM_NAME, MCP_PLATFORM_TRIGGER_NAMES);
|
|
1009
1040
|
/** 工具面的组装只在这一处:本 MCP 自己的导入工具(含 dev 专属的 demo 导入)+ design-inspect 的组 + dev 组 */
|
|
1010
1041
|
function createServer$1(hub, options = {}) {
|
|
1011
1042
|
const server = new McpServer({
|