@szc-ft/mcp-szcd-client 0.27.0 → 0.27.2

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.
@@ -125,8 +125,9 @@ queryNodes({ pageId, type: ["text", "rectangle", "group"], limit: 500 })
125
125
  | 优先级 | 来源 | 适用判定 | 渲染产物 |
126
126
  |---|---|---|---|
127
127
  | **P0** | **sketch 自带 bitmap** | 节点是 `type=bitmap` | `extractBitmaps` 返回的 `siblingsAfterMe + position + nodeSize` 三维判定渲染产物:区域背景图 / 行内图标 / 独立装饰插图(详见下方表 6) |
128
- | **P1** | **sketch 自带 shapePath(iconfont 命中)** | shapePath/shapeGroup 节点名能在 iconfont 库匹配到 | `matchIconFromName` → `<IconfontWapper type='icon-xxx' />` |
129
- | **P2** | **sketch 自带 shapePath(SVG 直出)** | 独立 shapePath(parent.type !== 'shapeGroup'),P1 未命中且 viewBox 校验通过 | `getShapePathData` → 内联 SVG |
128
+ | **P1** | **sketch 自带 shapePath(SVG 直出)** | 独立 shapePath(parent.type !== 'shapeGroup'),P1 未命中且 viewBox 校验通过 | `getShapePathData` → 内联 SVG |
129
+ | **P2** | **sketch 自带 shapePath(iconfont 命中)** | shapePath/shapeGroup 节点名能在 iconfont 库匹配到 | `matchIconFromName` → `<IconfontWapper type='icon-xxx' />` |
130
+
130
131
  | **P3** | **antd 图标语义匹配** | 上面三级都失败:shapeGroup 无法直出、节点名无 iconfont 匹配 | `<XxxOutlined />` 按 contextTable 选语义最近的 antd 图标 |
131
132
  | **P4** | **纯 CSS / div 渲染** | 上面四级全部失败,且元素是几何/色块(非图标语义) | `<div style={{...}}>` |
132
133
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@szc-ft/mcp-szcd-client",
3
- "version": "0.27.0",
3
+ "version": "0.27.2",
4
4
  "description": "MCP client for szcd component library - auto-configures AI coding tools with MCP server, skills, agents and commands",
5
5
  "keywords": [
6
6
  "mcp",
@@ -53,5 +53,5 @@ argument-hint: <目标页面URL> [可选:设计稿图片路径]
53
53
 
54
54
  **注意事项**:
55
55
  - 首次使用需确保 Chrome 以调试模式启动:`google-chrome --remote-debugging-port=9222`
56
- - 如执行器报错依赖缺失,引导用户安装:`npm install puppeteer-core pixelmatch pngjs sharp`
56
+ - 如执行器报错依赖缺失,优先按提示安装核心依赖;仅设计稿像素对比需要额外安装 `pixelmatch pngjs sharp`
57
57
  - connect 模式下天然继承用户浏览器的登录态和微前端环境
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "szcd-component-helper",
3
- "version": "0.27.0",
3
+ "version": "0.27.2",
4
4
  "description": "szcd 组件库 MCP 助手 — 查询组件信息、匹配需求、生成代码",
5
5
  "mcpServers": {
6
6
  "szcd-component-helper": {
@@ -12,11 +12,29 @@ compatibility:
12
12
  ## 触发条件
13
13
 
14
14
  当用户说出以下关键词时启动浏览器测试:
15
- - "测试一下"、"帮我验证"、"浏览器测试"
15
+ - "测试一下"、"帮我验证"、"浏览器测试"、"接管浏览器"
16
16
  - "对比设计稿"、"还原度"、"看看效果"
17
17
  - "功能测试"、"能不能正常用"
18
18
  - "检查页面"、"页面渲染"
19
19
 
20
+ ## 主链路定位
21
+
22
+ local-browser-test 的长期主链路是:
23
+
24
+ ```
25
+ Agent / SKILL.md
26
+ → szcd-mcp-client/local-browser-executor.js
27
+ → lib/browser-engine.js
28
+ → puppeteer-core + CDP
29
+ → 用户真实 Chrome / Edge
30
+ ```
31
+
32
+ 目标是在用户真实登录态/真实微前端环境中形成 browser-use + Playwright 结合体:
33
+ - browser-use 侧:`observe → act → observe`,通过结构化页面观察和交互元素 index 支持自主任务执行。
34
+ - Playwright 侧:locator、actionability、assert、plan 报告逐步收敛到 `BrowserEngine`。
35
+
36
+ `standard-skill/local-browser-test/local-browser-executor.cjs` 是过渡兼容执行器;新增稳定能力优先进入 `szcd-mcp-client/lib/browser-engine.js` 和根目录 `local-browser-executor.js`。
37
+
20
38
  ## 浏览器模式
21
39
 
22
40
  支持两种模式,执行器自动检测优先使用 connect:
@@ -60,14 +78,17 @@ AI 直接构造测试计划 JSON:
60
78
 
61
79
  | type | 功能 | 参数 | 返回 |
62
80
  |------|------|------|------|
81
+ | observe | 结构化观察 | `selector`, `depth`, `frameContentContains`, `maxInteractiveElements` | `{ frames, tree, interactiveElements[] }` |
82
+ | act | 按 index/selector 交互 | `index` 或 `selector/click/hover`, `typeText`, `clear`, `frameContentContains` | `{ acted, action, element }` |
83
+ | assert | 轻量断言 | `selector`, `expect`, `urlContains`, `textContains` | `{ passed, checks }` |
63
84
  | navigate | 导航到 URL | `url`, `waitUntil` | `{ url, title, loadTime }` |
64
85
  | screenshot | 页面截图 | `fullPage`, `clip`, `filename` | `{ filepath, width, height }` |
65
86
  | compare | 设计稿对比 | `designImagePath`, `threshold`, `regions[]` | `{ fidelity, diffPixels, diffImagePath, regions[] }` |
66
- | click | 点击元素 | `selector`, `waitForNavigation` | `{ clicked, tagName }` |
67
- | type | 输入文本 | `selector`, `text`, `clear` | `{ typed, value }` |
87
+ | click | 点击元素(兼容) | `selector`, `waitForNavigation` | `{ clicked, tagName }` |
88
+ | type | 输入文本(兼容) | `selector`, `text`, `clear` | `{ typed, value }` |
68
89
  | waitFor | 等待条件 | `selector` 或 `url`, `timeout` | `{ matched, waited }` |
69
90
  | evaluate | 执行 JS | `expression` | `{ result }` |
70
- | checkElement | 元素断言 | `selector`, `expect: {visible, minCount, maxCount, hasText}` | `{ passed, checks, elementCount }` |
91
+ | checkElement | 元素断言(兼容) | `selector`, `expect: {visible, minCount, maxCount, hasText}` | `{ passed, checks, elementCount }` |
71
92
  | findPage | 查找已打开的标签页 | `urlIncludes` 或 `urlRegex` 或 `titleIncludes` | `{ found, url, title, totalPages }` |
72
93
  | findFrame | 查找微前端 iframe | `urlIncludes` 或 `urlRegex` 或 `titleIncludes` 或 `contentIncludes` 或 `frameIndex` | `{ found, frameUrl, matchedBy, totalFrames }` |
73
94
  | loginWait | 等待 SSO 登录完成 | `loginSelector`, `timeout`, `interval` | `{ loggedIn, elapsed, currentUrl }` |
@@ -141,15 +162,15 @@ AI 直接构造测试计划 JSON:
141
162
  wujie 微前端子应用渲染在 blob URL iframe 中,**坐标点击无法到达 iframe 内容**。
142
163
 
143
164
  ```json
144
- { "type": "findFrame", "contentIncludes": "知识采编" }
145
- { "type": "click", "selector": "a.edit-btn" }
146
- { "type": "checkElement", "selector": "~.editKnowledge", "expect": { "minCount": 1 } }
165
+ { "type": "observe", "frameContentContains": "知识采编", "depth": 5, "maxInteractiveElements": 80 }
166
+ { "type": "act", "index": 3, "frameContentContains": "知识采编" }
167
+ { "type": "assert", "selector": "~.editKnowledge", "expect": { "minCount": 1 } }
147
168
  ```
148
169
 
149
- - `findFrame` 支持 `urlIncludes`、`titleIncludes`、`contentIncludes` 多种发现方式
150
- - 优先用 `contentIncludes`(按页面文字内容查找),不依赖 URL/端口
151
- - `findFrame` 后,后续所有步骤自动在 iframe 内执行
152
- - iframe 内的 click 使用 `evaluate()` 触发 DOM click,不依赖坐标
170
+ - 优先用 `observe` 发现 iframe 内的 `interactiveElements[index]`,再用 `act.index` 操作,不要重新猜 selector
171
+ - `observe/act` 支持 `frameUrlContains`、`frameContentContains`、`frameIndex` 多种发现方式
172
+ - 优先用 `frameContentContains`(按页面文字内容查找),不依赖 URL/端口
173
+ - iframe 内的 act 使用 DOM 事件触发,不依赖坐标
153
174
 
154
175
  ### CSS Modules 哈希类名
155
176
  项目使用 CSS Modules,类名会被哈希化(如 `editKnowledge___ynQgI`)。
@@ -159,32 +180,205 @@ wujie 微前端子应用渲染在 blob URL iframe 中,**坐标点击无法到
159
180
  - `~#myId` → 自动转为 `[id*="myId"]`
160
181
  - 普通选择器(如 `.my-class`)保持精确匹配
161
182
 
162
- ### puppeteer-core v22 注意事项
183
+ ## 实战经验补充
184
+
185
+ ### wujie 微前端诊断要点
186
+
187
+ 1. **子应用渲染在 blob URL iframe 中**,puppeteer 的 `page.frames()` 可以访问
188
+ 2. **iframe 内的 console 监听**:不要用 `frame.page().on()`(puppeteer-core 无此方法),改用 `page.on('console')` + `msg.frame().url()` 判断来源
189
+ 3. **生产环境 console 被屏蔽**:代码中 `console.log = () => {}` 导致 0 条消息。需提前注入 `localStorage.setItem('showConsoleLog', 'true')`
190
+ 4. **pageerror 事件是关键**:未捕获的 JS 异常不会出现在 console 中,必须监听 `page.on('pageerror')`
191
+ 5. **API 404/403 检查**:刷新页面后监听 `page.on('response')`,过滤 `resourceType === 'xhr'` 检查后端接口状态
192
+
193
+ ### 常见诊断流程
194
+
195
+ ```
196
+ 1. --action list-pages 确认目标页面存在
197
+ 2. --action diagnose 全面诊断(JS错误 + 网络 + 资源 + iframe)
198
+ 3. --action api-check 专门检查 API 请求(含 iframe 内的请求)
199
+ 4. 根据结果定位问题
200
+ ```
201
+
202
+ ### puppeteer-core 注意事项
203
+ - **连接时必须设 `defaultViewport: null`**,否则浏览器窗口会被强制缩放到指定尺寸:
204
+ ```js
205
+ // 正确:保持浏览器原始窗口大小
206
+ puppeteer.connect({ browserURL: 'http://localhost:9222', defaultViewport: null })
207
+ // 错误:会把浏览器视口改成 1440x900
208
+ puppeteer.connect({ browserURL: '...', defaultViewport: { width: 1440, height: 900 } })
209
+ ```
163
210
  - `page.$x()` 已移除,用 `evaluate` + `querySelectorAll` 替代
164
211
  - SVG 元素的 `className` 是 `SVGAnimatedString` 对象而非字符串,需先检查 `typeof`
165
212
  - 所有 `evaluate` 调用内部使用 `safeEval` 包装,自动处理 context destroyed 错误
166
213
 
167
214
  ## 执行命令
168
215
 
216
+ ### 结构化观察(主链路起点)
217
+ ```bash
218
+ node {client_path}/local-browser-executor.js \
219
+ --action observe \
220
+ --url-contains "platform.aicityos.com" \
221
+ --frame-content-contains "数据集目录" \
222
+ --depth 5 \
223
+ --output /tmp/browser-observe.json
224
+ ```
225
+
226
+ `observe` 输出 `frames`、`tree`、`interactiveElements[index]`、`selectorCandidates`、`bbox`、`state`。Agent 后续应优先使用 `index` 调用 `act`,不要从 DOM 树重新猜 selector。直接 `--action observe` 默认只连接用户已启动的真实浏览器 CDP;如确需无 CDP 时启动 headless 回退,追加 `--allow-launch`。
227
+
228
+ ### 观察后按 index 交互(主链路闭环)
229
+ ```bash
230
+ node {client_path}/local-browser-executor.js \
231
+ --action act \
232
+ --url-contains "platform.aicityos.com" \
233
+ --frame-content-contains "数据集目录" \
234
+ --index 3 \
235
+ --observe-after \
236
+ --output /tmp/browser-act-observe.json
237
+ ```
238
+
239
+ ### 轻量 DOM 断言
240
+ ```bash
241
+ node {client_path}/local-browser-executor.js \
242
+ --action assert \
243
+ --url-contains "platform.aicityos.com" \
244
+ --selector ".ant-table" \
245
+ --expect-visible \
246
+ --min-count 1 \
247
+ --output /tmp/browser-assert.json
248
+ ```
249
+
250
+ ### 快速诊断(过渡兼容)
251
+ ```bash
252
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
253
+ --action diagnose \
254
+ --url-contains "platform.aicityos.com" \
255
+ --wait 15000 \
256
+ --output-dir /tmp/browser-test-diagnose
257
+ ```
258
+
259
+ ### 列出所有标签页
169
260
  ```bash
170
- node {client_install_path}/local-browser-executor.js \
171
- --plan '<测试计划JSON>' \
172
- --output /tmp/browser-test-result.json \
173
- --base-url http://localhost:8088
261
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
262
+ --action list-pages
174
263
  ```
175
264
 
176
- 也支持从文件读取计划:
265
+ ### 检查 API 请求状态
177
266
  ```bash
178
- node {client_install_path}/local-browser-executor.js \
267
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
268
+ --action api-check \
269
+ --url-contains "platform.aicityos.com" \
270
+ --wait 15000
271
+ ```
272
+
273
+ ### 截图
274
+ ```bash
275
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
276
+ --action screenshot \
277
+ --url-contains "platform.aicityos.com" \
278
+ --filename current-page.png \
279
+ --output-dir /tmp/browser-test
280
+ ```
281
+
282
+ ### 执行测试计划 JSON
283
+ ```bash
284
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
285
+ --action plan \
179
286
  --plan-file /tmp/test-plan.json \
180
- --output /tmp/browser-test-result.json \
181
- --base-url http://localhost:8088
287
+ --output /tmp/browser-test-result.json
288
+ ```
289
+
290
+ ### DOM 快照(结构化页面树,类似 browser-use take_snapshot)
291
+ ```bash
292
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
293
+ --action snapshot \
294
+ --url-contains "platform.aicityos.com" \
295
+ --depth 4 \
296
+ --selector ".page-container"
297
+ ```
298
+ 输出示例:
299
+ ```
300
+ <div.page-container>
301
+ <section.page-layout>
302
+ <header.page-header>
303
+ <div.page-header-left> <div.logo>
304
+ <section.h-box>
305
+ <aside.ant-layout-sider> 🔗
306
+ <main.ant-layout-content>
307
+ <div.layout-wrap>
308
+ ```
309
+
310
+ ### 智能交互(支持 text=、role=、~ 选择器,类似 Playwright)
311
+ ```bash
312
+ # 点击包含“构建”文本的按钮
313
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
314
+ --action interact \
315
+ --url-contains "jenkins" \
316
+ --click "text=Build"
317
+
318
+ # 在输入框中输入文本
319
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
320
+ --action interact \
321
+ --click "#search-input" \
322
+ --type "hello world"
323
+
324
+ # 悬停 + 截图
325
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
326
+ --action interact \
327
+ --hover "~ant-menu-item" \
328
+ --screenshot-after
329
+
330
+ # 滚动页面
331
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
332
+ --action interact \
333
+ --scroll down --scroll-amount 500
334
+ ```
335
+ 选择器语法:
336
+ - `text=Build` → 按文本内容查找(类似 Playwright text selector)
337
+ - `role=button` → 按 ARIA role 查找
338
+ - `~ant-menu-item` → CSS class 模糊匹配(`[class*="ant-menu-item"]`)
339
+ - `.my-class` → 精确 CSS 选择器
340
+
341
+ ### 性能指标采集(FCP/TTFB/资源统计)
342
+ ```bash
343
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
344
+ --action perf \
345
+ --url-contains "platform.aicityos.com"
346
+ ```
347
+
348
+ ### 持续监控模式(定时截图 + 错误检测)
349
+ ```bash
350
+ NODE_PATH=~/.szcd-mcp/deps/node_modules node {skill_path}/local-browser-executor.cjs \
351
+ --action watch \
352
+ --url-contains "platform.aicityos.com" \
353
+ --interval 5000 \
354
+ --max-rounds 60 \
355
+ --output-dir /tmp/browser-watch
182
356
  ```
183
357
 
184
358
  ### 可选参数
185
359
 
186
- - `--cdp-url http://localhost:9223`:指定非默认的 CDP 端口
187
- - `--page-url http://xxx/page`:connect 模式下指定目标页面
360
+ - `--cdp-url http://localhost:9222`:CDP 地址(默认 9222)
361
+ - `--url <url>`:目标页面 URL(不存在则导航)
362
+ - `--url-contains <keyword>`:按关键词查找已打开的页面
363
+ - `--frame-url-contains <keyword>`:observe 时按 iframe URL 片段匹配目标 frame
364
+ - `--frame-content-contains <keyword>`:observe 时按 iframe 文本内容匹配目标 frame
365
+ - `--frame-index <n>`:observe 时按 frame 下标选择目标 frame
366
+ - `--wait <ms>`:额外等待时间(默认 5000ms,微前端建议 15000)
367
+ - `--output <path>`:JSON 结果输出路径
368
+ - `--output-dir <dir>`:截图/产物目录
369
+ - `--filename <name>`:截图文件名
370
+ - `--full-page`:全页截图
371
+ - `--selector <css>`:快照/observe 根元素(默认 body)
372
+ - `--depth <n>`:DOM 深度(默认 5)
373
+ - `--click <selector>`:点击元素(支持 text=/role=/~)
374
+ - `--type <text>`:输入文本
375
+ - `--hover <selector>`:悬停元素
376
+ - `--scroll <up|down|left|right>`:滚动方向
377
+ - `--scroll-amount <px>`:滚动距离(默认 300)
378
+ - `--screenshot-after`:交互后自动截图
379
+ - `--interval <ms>`:watch 模式间隔(默认 5000)
380
+ - `--max-rounds <n>`:watch 最大轮数(默认 60)
381
+ - `--allow-launch`:根执行器 action 模式允许无 CDP 时启动 headless Chrome;默认不启用,优先保障真实用户浏览器链路
188
382
 
189
383
  ## AI 语义断言(aiAssert)
190
384
 
@@ -211,12 +405,17 @@ node {client_install_path}/local-browser-executor.js \
211
405
 
212
406
  ## 依赖管理
213
407
 
214
- 浏览器测试依赖(puppeteer-core, pixelmatch, pngjs, sharp)采用**共享缓存**方案:
215
- - 首次使用时自动安装到 `~/.szcd-mcp/deps/`
408
+ 浏览器测试依赖采用**共享缓存 + 按需安装**方案:
409
+ - `observe/act/assert/diagnose/screenshot` 主链路只安装 `puppeteer-core` 到 `~/.szcd-mcp/deps/`
410
+ - 只有执行设计稿像素对比 `compare` 时才安装 `pixelmatch/pngjs/sharp`
216
411
  - 后续所有项目共享复用,无需重复安装
217
- - 如果自动安装失败,引导用户手动执行:
412
+ - 如果核心依赖自动安装失败,引导用户手动执行:
413
+ ```bash
414
+ cd ~/.szcd-mcp/deps && npm install --registry=https://registry.npmmirror.com puppeteer-core
415
+ ```
416
+ - 如果视觉对比依赖自动安装失败,引导用户手动执行:
218
417
  ```bash
219
- cd ~/.szcd-mcp/deps && npm install puppeteer-core pixelmatch pngjs sharp --registry=https://npmmirror.com
418
+ cd ~/.szcd-mcp/deps && npm install --registry=https://registry.npmmirror.com --@img:registry=https://registry.npmmirror.com --prefer-offline --no-audit --no-fund --omit=dev --package-lock=false --sharp_binary_host=https://npmmirror.com/mirrors/sharp --sharp_libvips_binary_host=https://npmmirror.com/mirrors/sharp-libvips pixelmatch pngjs sharp
220
419
  ```
221
420
 
222
421
  ## 结果解读