z-mcp-codesign 0.1.2 → 0.1.4
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/README.md +14 -20
- package/dist/index.js +133 -240
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,46 +21,40 @@
|
|
|
21
21
|
}
|
|
22
22
|
```
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
24
|
# 提供的工具
|
|
27
25
|
|
|
28
|
-
| 工具名
|
|
29
|
-
|
|
|
30
|
-
| `codesign_open_login`
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `codesign_screen_list`
|
|
26
|
+
| 工具名 | 说明 |
|
|
27
|
+
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
28
|
+
| `codesign_open_login` | 有界面打开 CoDesign 登录页,用于在本机 Edge 用户数据目录中完成登录 |
|
|
29
|
+
| `codesign_screen_inspect_save` | 打开指定 CoDesign 页面,截取最大的可见 `.screen-inspect` 区域,保存为本地 PNG 文件并返回保存路径(默认保存到项目根目录 `_z-mcp-imgs/`) |
|
|
30
|
+
| `codesign_screen_viewer_download_save` | 打开 CoDesign 页面,点击 `.screen-viewer__action` 选择“下载图片”,捕获下载并保存到项目根目录 `_z-mcp-imgs/` |
|
|
31
|
+
| `codesign_screen_list` | 获取 CoDesign 设计页面左侧菜单中的所有页面名称和访问地址 |
|
|
34
32
|
|
|
35
33
|
# 使用示例
|
|
36
34
|
|
|
37
35
|
**打开登录页(用于后续抓图)**
|
|
38
36
|
|
|
39
37
|
```bash
|
|
40
|
-
|
|
38
|
+
调用MCP 打开CoDesign登录页
|
|
41
39
|
```
|
|
42
40
|
|
|
43
41
|
**列出当前项目的页面列表**
|
|
44
42
|
|
|
45
43
|
```bash
|
|
46
|
-
|
|
44
|
+
调用MCP 获取CoDesign所有页面列表使用表格展示。
|
|
45
|
+
URL为:https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect
|
|
47
46
|
```
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
**通过页面“下载图片”保存到本地**
|
|
50
49
|
|
|
51
50
|
```bash
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
**抓图并保存到本地**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
请打开这个 CoDesign inspect 链接,获取图片,把截图保存到本地,并告诉我保存路径:https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect
|
|
51
|
+
调用MCP 打开CoDesign页面,下载图片保存到本地,并告诉我保存路径。
|
|
52
|
+
传入参数url为:https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect
|
|
59
53
|
```
|
|
60
54
|
|
|
61
55
|
**生成项目**
|
|
62
56
|
|
|
63
57
|
```bash
|
|
64
|
-
|
|
58
|
+
调用MCP 打开CoDesign页面,下载图片保存到本地,并识别图片内容生成Vue3+Vite项目。
|
|
59
|
+
传入参数url为:https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect
|
|
65
60
|
```
|
|
66
|
-
|
package/dist/index.js
CHANGED
|
@@ -2980,7 +2980,7 @@ var require_compile = __commonJS({
|
|
|
2980
2980
|
const schOrFunc = root.refs[ref];
|
|
2981
2981
|
if (schOrFunc)
|
|
2982
2982
|
return schOrFunc;
|
|
2983
|
-
let _sch =
|
|
2983
|
+
let _sch = resolve5.call(this, root, ref);
|
|
2984
2984
|
if (_sch === void 0) {
|
|
2985
2985
|
const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
2986
2986
|
const { schemaId } = this.opts;
|
|
@@ -3007,7 +3007,7 @@ var require_compile = __commonJS({
|
|
|
3007
3007
|
function sameSchemaEnv(s1, s2) {
|
|
3008
3008
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
3009
3009
|
}
|
|
3010
|
-
function
|
|
3010
|
+
function resolve5(root, ref) {
|
|
3011
3011
|
let sch;
|
|
3012
3012
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
3013
3013
|
ref = sch;
|
|
@@ -3582,7 +3582,7 @@ var require_fast_uri = __commonJS({
|
|
|
3582
3582
|
}
|
|
3583
3583
|
return uri;
|
|
3584
3584
|
}
|
|
3585
|
-
function
|
|
3585
|
+
function resolve5(baseURI, relativeURI, options) {
|
|
3586
3586
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
3587
3587
|
const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
3588
3588
|
schemelessOptions.skipEscape = true;
|
|
@@ -3809,7 +3809,7 @@ var require_fast_uri = __commonJS({
|
|
|
3809
3809
|
var fastUri = {
|
|
3810
3810
|
SCHEMES,
|
|
3811
3811
|
normalize,
|
|
3812
|
-
resolve:
|
|
3812
|
+
resolve: resolve5,
|
|
3813
3813
|
resolveComponent,
|
|
3814
3814
|
equal,
|
|
3815
3815
|
serialize,
|
|
@@ -6800,7 +6800,7 @@ var require_dist = __commonJS({
|
|
|
6800
6800
|
|
|
6801
6801
|
// src/index.ts
|
|
6802
6802
|
import { createRequire } from "node:module";
|
|
6803
|
-
import { dirname
|
|
6803
|
+
import { dirname, join as join4 } from "node:path";
|
|
6804
6804
|
import { fileURLToPath } from "node:url";
|
|
6805
6805
|
|
|
6806
6806
|
// node_modules/zod/v3/external.js
|
|
@@ -18875,7 +18875,7 @@ var Protocol = class {
|
|
|
18875
18875
|
return;
|
|
18876
18876
|
}
|
|
18877
18877
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
18878
|
-
await new Promise((
|
|
18878
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
18879
18879
|
options?.signal?.throwIfAborted();
|
|
18880
18880
|
}
|
|
18881
18881
|
} catch (error2) {
|
|
@@ -18892,7 +18892,7 @@ var Protocol = class {
|
|
|
18892
18892
|
*/
|
|
18893
18893
|
request(request, resultSchema, options) {
|
|
18894
18894
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
18895
|
-
return new Promise((
|
|
18895
|
+
return new Promise((resolve5, reject) => {
|
|
18896
18896
|
const earlyReject = (error2) => {
|
|
18897
18897
|
reject(error2);
|
|
18898
18898
|
};
|
|
@@ -18970,7 +18970,7 @@ var Protocol = class {
|
|
|
18970
18970
|
if (!parseResult.success) {
|
|
18971
18971
|
reject(parseResult.error);
|
|
18972
18972
|
} else {
|
|
18973
|
-
|
|
18973
|
+
resolve5(parseResult.data);
|
|
18974
18974
|
}
|
|
18975
18975
|
} catch (error2) {
|
|
18976
18976
|
reject(error2);
|
|
@@ -19231,12 +19231,12 @@ var Protocol = class {
|
|
|
19231
19231
|
}
|
|
19232
19232
|
} catch {
|
|
19233
19233
|
}
|
|
19234
|
-
return new Promise((
|
|
19234
|
+
return new Promise((resolve5, reject) => {
|
|
19235
19235
|
if (signal.aborted) {
|
|
19236
19236
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
19237
19237
|
return;
|
|
19238
19238
|
}
|
|
19239
|
-
const timeoutId = setTimeout(
|
|
19239
|
+
const timeoutId = setTimeout(resolve5, interval);
|
|
19240
19240
|
signal.addEventListener("abort", () => {
|
|
19241
19241
|
clearTimeout(timeoutId);
|
|
19242
19242
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -20336,7 +20336,7 @@ var McpServer = class {
|
|
|
20336
20336
|
let task = createTaskResult.task;
|
|
20337
20337
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
20338
20338
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
20339
|
-
await new Promise((
|
|
20339
|
+
await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
|
|
20340
20340
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
20341
20341
|
if (!updatedTask) {
|
|
20342
20342
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -20979,12 +20979,12 @@ var StdioServerTransport = class {
|
|
|
20979
20979
|
this.onclose?.();
|
|
20980
20980
|
}
|
|
20981
20981
|
send(message) {
|
|
20982
|
-
return new Promise((
|
|
20982
|
+
return new Promise((resolve5) => {
|
|
20983
20983
|
const json = serializeMessage(message);
|
|
20984
20984
|
if (this._stdout.write(json)) {
|
|
20985
|
-
|
|
20985
|
+
resolve5();
|
|
20986
20986
|
} else {
|
|
20987
|
-
this._stdout.once("drain",
|
|
20987
|
+
this._stdout.once("drain", resolve5);
|
|
20988
20988
|
}
|
|
20989
20989
|
});
|
|
20990
20990
|
}
|
|
@@ -21008,8 +21008,7 @@ import { resolve as resolve4 } from "node:path";
|
|
|
21008
21008
|
import { join } from "node:path";
|
|
21009
21009
|
var ENV_EDGE_USER_DATA = "Z_MCP_CODESIGN_EDGE_USER_DATA";
|
|
21010
21010
|
var DEFAULT_CODESIGN_LOGIN_URL = "https://codesign.qq.com/app/login";
|
|
21011
|
-
var
|
|
21012
|
-
var DEFAULT_MCP_EDGE_PROFILE = join(process.cwd(), ".z-mcp-codesign-edge");
|
|
21011
|
+
var DEFAULT_MCP_EDGE_PROFILE = join(process.cwd(), "_z-mcp-edge");
|
|
21013
21012
|
|
|
21014
21013
|
// src/lib/login-window.ts
|
|
21015
21014
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -21205,9 +21204,8 @@ var toolError = (text) => ({
|
|
|
21205
21204
|
// src/tools/open-login.ts
|
|
21206
21205
|
var codesignLoginInput = external_exports.object({
|
|
21207
21206
|
loginUrl: external_exports.string().url().optional().describe(`\u53EF\u9009\uFF1B\u9ED8\u8BA4 ${DEFAULT_CODESIGN_LOGIN_URL}`),
|
|
21208
|
-
userDataDir: external_exports.string().optional().describe("\u6D4F\u89C8\u5668\u7528\u6237\u6570\u636E\u6839\u76EE\u5F55\uFF1B\u672A\u4F20\u65F6\u540C\u6293\u56FE\u5DE5\u5177\uFF08\u73AF\u5883\u53D8\u91CF\u6216\u4E34\u65F6\u76EE\u5F55\uFF09\u3002"),
|
|
21209
21207
|
profileDirectory: external_exports.string().optional().describe(
|
|
21210
|
-
"User Data \u4E0B Edge profile \u76EE\u5F55\u540D\uFF08\u5982 Default\uFF09\uFF1B\u4E0E\u6293\u56FE\u5DE5\u5177
|
|
21208
|
+
"User Data \u4E0B Edge profile \u76EE\u5F55\u540D\uFF08\u5982 Default\uFF09\uFF1B\u4E0E\u6293\u56FE\u5DE5\u5177\u4F7F\u7528\u540C\u4E00\u76EE\u5F55\u65F6\u987B\u4F20\u76F8\u540C\u503C\u3002"
|
|
21211
21209
|
)
|
|
21212
21210
|
});
|
|
21213
21211
|
function registerOpenLoginTool(mcpServer2, deps2) {
|
|
@@ -21226,7 +21224,7 @@ function registerOpenLoginTool(mcpServer2, deps2) {
|
|
|
21226
21224
|
return toolError("loginUrl \u4E0D\u662F\u5408\u6CD5 URL\u3002");
|
|
21227
21225
|
}
|
|
21228
21226
|
}
|
|
21229
|
-
const persistentDir = resolveEdgeUserDataDir(
|
|
21227
|
+
const persistentDir = resolveEdgeUserDataDir(void 0);
|
|
21230
21228
|
const ok = await openOrNavigateCodesignLogin(
|
|
21231
21229
|
deps2,
|
|
21232
21230
|
loginUrl,
|
|
@@ -21243,77 +21241,7 @@ function registerOpenLoginTool(mcpServer2, deps2) {
|
|
|
21243
21241
|
{
|
|
21244
21242
|
loginUrl,
|
|
21245
21243
|
userDataDir: resolve4(persistentDir),
|
|
21246
|
-
hint: "\u5728\u5F39\u51FA\u7684\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u767B\u5F55\u540E\u5173\u95ED\u7A97\u53E3\uFF0C\u518D\u8C03\u7528
|
|
21247
|
-
},
|
|
21248
|
-
null,
|
|
21249
|
-
2
|
|
21250
|
-
)
|
|
21251
|
-
);
|
|
21252
|
-
}
|
|
21253
|
-
);
|
|
21254
|
-
}
|
|
21255
|
-
|
|
21256
|
-
// src/tools/save-image.ts
|
|
21257
|
-
import { resolve as resolve5, dirname, extname } from "node:path";
|
|
21258
|
-
import { mkdir as mkdir2, writeFile } from "node:fs/promises";
|
|
21259
|
-
var saveImageInput = external_exports.object({
|
|
21260
|
-
imageBase64: external_exports.string().min(1).describe(
|
|
21261
|
-
"\u56FE\u7247 base64\uFF1B\u652F\u6301\u7EAF base64\uFF0C\u6216 data URL\uFF08\u5982 data:image/png;base64,AAAA...\uFF09\u3002"
|
|
21262
|
-
),
|
|
21263
|
-
filePath: external_exports.string().min(1).describe("\u4FDD\u5B58\u8DEF\u5F84\uFF08\u76F8\u5BF9\u6216\u7EDD\u5BF9\uFF09\uFF0C\u5982 ./out/shot.png \u6216 D:/tmp/shot.png"),
|
|
21264
|
-
mimeType: external_exports.string().optional().describe("\u53EF\u9009\uFF1B\u7528\u4E8E\u63A8\u65AD\u6269\u5C55\u540D\uFF08\u5F53 filePath \u65E0\u6269\u5C55\u540D\u65F6\uFF09\u3002\u5982 image/png")
|
|
21265
|
-
});
|
|
21266
|
-
function extFromMime(mimeType) {
|
|
21267
|
-
const m = (mimeType || "").trim().toLowerCase();
|
|
21268
|
-
if (!m) return null;
|
|
21269
|
-
if (m === "image/png") return ".png";
|
|
21270
|
-
if (m === "image/jpeg" || m === "image/jpg") return ".jpg";
|
|
21271
|
-
if (m === "image/webp") return ".webp";
|
|
21272
|
-
if (m === "image/gif") return ".gif";
|
|
21273
|
-
return null;
|
|
21274
|
-
}
|
|
21275
|
-
function parseBase64(input) {
|
|
21276
|
-
const s = input.trim();
|
|
21277
|
-
const m = s.match(/^data:([^;]+);base64,(.*)$/i);
|
|
21278
|
-
if (m) {
|
|
21279
|
-
const mimeType = m[1]?.trim();
|
|
21280
|
-
const base642 = (m[2] || "").trim();
|
|
21281
|
-
if (!base642) return null;
|
|
21282
|
-
return { mimeType, base64: base642 };
|
|
21283
|
-
}
|
|
21284
|
-
return { base64: s };
|
|
21285
|
-
}
|
|
21286
|
-
function registerSaveImageTool(mcpServer2) {
|
|
21287
|
-
mcpServer2.registerTool(
|
|
21288
|
-
"codesign_save_image",
|
|
21289
|
-
{
|
|
21290
|
-
description: "\u5C06 base64 \u56FE\u7247\u4FDD\u5B58\u4E3A\u672C\u5730\u6587\u4EF6\u8DEF\u5F84\u3002",
|
|
21291
|
-
inputSchema: saveImageInput
|
|
21292
|
-
},
|
|
21293
|
-
async (input) => {
|
|
21294
|
-
const parsed = parseBase64(input.imageBase64);
|
|
21295
|
-
if (!parsed) return toolError("imageBase64 \u4E3A\u7A7A\u6216\u4E0D\u662F\u5408\u6CD5\u7684 base64/dataURL\u3002");
|
|
21296
|
-
let filePath = input.filePath.trim();
|
|
21297
|
-
if (!filePath) return toolError("filePath \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
21298
|
-
const inferredExt = extFromMime(parsed.mimeType) || extFromMime(input.mimeType);
|
|
21299
|
-
if (!extname(filePath) && inferredExt) {
|
|
21300
|
-
filePath += inferredExt;
|
|
21301
|
-
}
|
|
21302
|
-
const absPath = resolve5(filePath);
|
|
21303
|
-
await mkdir2(dirname(absPath), { recursive: true });
|
|
21304
|
-
let buf;
|
|
21305
|
-
try {
|
|
21306
|
-
buf = Buffer.from(parsed.base64, "base64");
|
|
21307
|
-
} catch {
|
|
21308
|
-
return toolError("base64 \u89E3\u7801\u5931\u8D25\uFF08\u8BF7\u786E\u8BA4\u4E0D\u662F\u88AB\u622A\u65AD/\u4E0D\u662F base64\uFF09\u3002");
|
|
21309
|
-
}
|
|
21310
|
-
if (buf.length === 0) return toolError("base64 \u89E3\u7801\u540E\u4E3A\u7A7A\uFF08\u8BF7\u786E\u8BA4\u8F93\u5165\u6B63\u786E\uFF09\u3002");
|
|
21311
|
-
await writeFile(absPath, buf);
|
|
21312
|
-
return toolResult(
|
|
21313
|
-
JSON.stringify(
|
|
21314
|
-
{
|
|
21315
|
-
savedPath: absPath,
|
|
21316
|
-
bytes: buf.length
|
|
21244
|
+
hint: "\u5728\u5F39\u51FA\u7684\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u767B\u5F55\u540E\u5173\u95ED\u7A97\u53E3\uFF0C\u518D\u8C03\u7528\u6293\u56FE/\u5217\u8868/\u4E0B\u8F7D\u7B49\u5DE5\u5177\u3002"
|
|
21317
21245
|
},
|
|
21318
21246
|
null,
|
|
21319
21247
|
2
|
|
@@ -21337,9 +21265,9 @@ async function withCodesignPage(deps2, input, fn, opts = {}) {
|
|
|
21337
21265
|
...opts.defaults ?? {}
|
|
21338
21266
|
};
|
|
21339
21267
|
const url = input.url;
|
|
21340
|
-
const headless =
|
|
21268
|
+
const headless = opts.allowHeaded ? merged.headless : true;
|
|
21341
21269
|
const timeoutMs = input.timeoutMs ?? merged.timeoutMs;
|
|
21342
|
-
const persistentDir = resolveEdgeUserDataDir(
|
|
21270
|
+
const persistentDir = resolveEdgeUserDataDir(void 0);
|
|
21343
21271
|
const context = await chromium2.launchPersistentContext(
|
|
21344
21272
|
persistentDir,
|
|
21345
21273
|
persistentBrowserContextOptions({
|
|
@@ -21378,49 +21306,62 @@ async function withCodesignPage(deps2, input, fn, opts = {}) {
|
|
|
21378
21306
|
}
|
|
21379
21307
|
}
|
|
21380
21308
|
|
|
21381
|
-
// src/
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21385
|
-
for (const h of handles) {
|
|
21386
|
-
const box = await h.boundingBox();
|
|
21387
|
-
if (!box || box.width < 1 || box.height < 1) continue;
|
|
21388
|
-
const area = box.width * box.height;
|
|
21389
|
-
const bestArea = best ? best.box.width * best.box.height : 0;
|
|
21390
|
-
if (!best || area > bestArea) best = { handle: h, box };
|
|
21391
|
-
}
|
|
21392
|
-
if (!best) return null;
|
|
21393
|
-
const buffer = Buffer.from(await best.handle.screenshot({ type: "png" }));
|
|
21394
|
-
return { buffer, boundingBox: best.box };
|
|
21395
|
-
}
|
|
21396
|
-
|
|
21397
|
-
// src/tools/screen-inspect.ts
|
|
21398
|
-
var screenInspectInput = external_exports.object({
|
|
21399
|
-
url: external_exports.string().url().describe("CoDesign \u9875\u9762\u5730\u5740"),
|
|
21400
|
-
headless: external_exports.boolean().optional().describe("\u65E0\u5934\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 true"),
|
|
21401
|
-
timeoutMs: external_exports.number().int().positive().optional().describe("\u6574\u4F53\u8D85\u65F6\u6BEB\u79D2\u6570\uFF0C\u9ED8\u8BA4 60000"),
|
|
21402
|
-
userDataDir: external_exports.string().optional().describe(
|
|
21403
|
-
"\u6D4F\u89C8\u5668\u7528\u6237\u6570\u636E\u6839\u76EE\u5F55\uFF08\u987B\u5148\u9000\u51FA\u5360\u7528\u8BE5\u76EE\u5F55\u7684\u6D4F\u89C8\u5668\uFF09\u3002\u672A\u4F20\u65F6\u4F7F\u7528\u73AF\u5883\u53D8\u91CF Z_MCP_CODESIGN_EDGE_USER_DATA \u6216\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55\u4E0B\u9ED8\u8BA4\u914D\u7F6E\u3002"
|
|
21309
|
+
// src/tools/screen-list.ts
|
|
21310
|
+
var screenListInput = external_exports.object({
|
|
21311
|
+
url: external_exports.string().url().describe(
|
|
21312
|
+
"CoDesign \u8BBE\u8BA1\u9875\u9762\u5730\u5740\uFF0C\u5982 https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect"
|
|
21404
21313
|
),
|
|
21314
|
+
timeoutMs: external_exports.number().int().positive().optional().describe("\u6574\u4F53\u8D85\u65F6\u6BEB\u79D2\u6570\uFF0C\u9ED8\u8BA4 60000"),
|
|
21405
21315
|
profileDirectory: external_exports.string().optional().describe("User Data \u4E0B\u914D\u7F6E\u540D\uFF0C\u5982 Default\u3002")
|
|
21406
21316
|
});
|
|
21407
|
-
async function
|
|
21317
|
+
async function runScreenList(deps2, input) {
|
|
21408
21318
|
return withCodesignPage(
|
|
21409
21319
|
deps2,
|
|
21410
21320
|
input,
|
|
21411
21321
|
async (page) => {
|
|
21412
|
-
const
|
|
21413
|
-
|
|
21414
|
-
|
|
21322
|
+
const pages = await page.evaluate(() => {
|
|
21323
|
+
const items = document.querySelectorAll(".screen-list__item");
|
|
21324
|
+
const result = [];
|
|
21325
|
+
for (const item of items) {
|
|
21326
|
+
const id = item.getAttribute("id") || "";
|
|
21327
|
+
const match = id.match(/^screen-(\d+)$/);
|
|
21328
|
+
if (!match) continue;
|
|
21329
|
+
const pageId = match[1];
|
|
21330
|
+
let name = "";
|
|
21331
|
+
const nameEl = item.querySelector(
|
|
21332
|
+
"[class*='name'], [class*='title'], [class*='label']"
|
|
21333
|
+
);
|
|
21334
|
+
if (nameEl) {
|
|
21335
|
+
name = nameEl.textContent?.trim() || "";
|
|
21336
|
+
}
|
|
21337
|
+
if (!name) {
|
|
21338
|
+
name = item.textContent?.trim().replace(/\s+/g, " ") || "";
|
|
21339
|
+
}
|
|
21340
|
+
result.push({
|
|
21341
|
+
name,
|
|
21342
|
+
pageId
|
|
21343
|
+
});
|
|
21344
|
+
}
|
|
21345
|
+
return result;
|
|
21346
|
+
});
|
|
21347
|
+
if (pages.length === 0) {
|
|
21348
|
+
return toolError("\u672A\u627E\u5230\u5DE6\u4FA7\u83DC\u5355\u4E2D\u7684\u9875\u9762\u5217\u8868\u3002");
|
|
21415
21349
|
}
|
|
21350
|
+
const currentUrl = new URL(input.url);
|
|
21351
|
+
const pathParts = currentUrl.pathname.split("/");
|
|
21352
|
+
const projectId = pathParts.find((p) => /^\d{10,}$/.test(p)) || "";
|
|
21353
|
+
const currentPageId = pathParts.find((p) => /^\d+$/.test(p)) || "";
|
|
21354
|
+
const resultData = pages.map((p) => ({
|
|
21355
|
+
name: p.name,
|
|
21356
|
+
pageId: p.pageId,
|
|
21357
|
+
url: projectId ? `https://codesign.qq.com/app/design/${projectId}/${p.pageId}/inspect` : currentPageId ? input.url.replace(`/${currentPageId}/`, `/${p.pageId}/`) : input.url
|
|
21358
|
+
}));
|
|
21416
21359
|
return toolResult(
|
|
21417
21360
|
JSON.stringify(
|
|
21418
21361
|
{
|
|
21419
|
-
|
|
21420
|
-
|
|
21421
|
-
|
|
21422
|
-
imageBase64: shot.buffer.toString("base64"),
|
|
21423
|
-
boundingBox: shot.boundingBox
|
|
21362
|
+
projectId,
|
|
21363
|
+
totalCount: resultData.length,
|
|
21364
|
+
pages: resultData
|
|
21424
21365
|
},
|
|
21425
21366
|
null,
|
|
21426
21367
|
2
|
|
@@ -21428,24 +21369,24 @@ async function runScreenInspect(deps2, input) {
|
|
|
21428
21369
|
);
|
|
21429
21370
|
},
|
|
21430
21371
|
{
|
|
21431
|
-
waitForSelector: { selector: ".screen-
|
|
21372
|
+
waitForSelector: { selector: ".screen-list__item", state: "attached" },
|
|
21432
21373
|
defaults: { afterLoadWaitMs: 250 }
|
|
21433
21374
|
}
|
|
21434
21375
|
);
|
|
21435
21376
|
}
|
|
21436
|
-
function
|
|
21377
|
+
function registerScreenListTool(mcpServer2, deps2) {
|
|
21437
21378
|
mcpServer2.registerTool(
|
|
21438
|
-
"
|
|
21379
|
+
"codesign_screen_list",
|
|
21439
21380
|
{
|
|
21440
|
-
description: "\
|
|
21441
|
-
inputSchema:
|
|
21381
|
+
description: "\u6839\u636ECoDesign\u9875\u9762\u5730\u5740\u83B7\u53D6\u9879\u76EE\u6240\u6709\u9875\u9762\u5217\u8868\uFF0C\u8FD4\u56DE\u9879\u76EEID\u3001\u603B\u9875\u9762\u6570\u3001\u9875\u9762\u5217\u8868\u3002",
|
|
21382
|
+
inputSchema: screenListInput
|
|
21442
21383
|
},
|
|
21443
|
-
(input) =>
|
|
21384
|
+
(input) => runScreenList(deps2, input)
|
|
21444
21385
|
);
|
|
21445
21386
|
}
|
|
21446
21387
|
|
|
21447
|
-
// src/tools/screen-
|
|
21448
|
-
import { mkdir as
|
|
21388
|
+
// src/tools/screen-viewer-download-save.ts
|
|
21389
|
+
import { mkdir as mkdir2 } from "node:fs/promises";
|
|
21449
21390
|
import path from "node:path";
|
|
21450
21391
|
function safeSegment(s) {
|
|
21451
21392
|
return s.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
@@ -21465,124 +21406,78 @@ function deriveCodesignIds(url) {
|
|
|
21465
21406
|
return {};
|
|
21466
21407
|
}
|
|
21467
21408
|
}
|
|
21468
|
-
var
|
|
21409
|
+
var screenViewerDownloadSaveInput = external_exports.object({
|
|
21469
21410
|
url: external_exports.string().url().describe("CoDesign \u9875\u9762\u5730\u5740"),
|
|
21470
|
-
headless: external_exports.boolean().optional().describe("\u65E0\u5934\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 true"),
|
|
21471
21411
|
timeoutMs: external_exports.number().int().positive().optional().describe("\u6574\u4F53\u8D85\u65F6\u6BEB\u79D2\u6570\uFF0C\u9ED8\u8BA4 60000"),
|
|
21472
|
-
userDataDir: external_exports.string().optional().describe(
|
|
21473
|
-
"\u6D4F\u89C8\u5668\u7528\u6237\u6570\u636E\u6839\u76EE\u5F55\uFF08\u987B\u5148\u9000\u51FA\u5360\u7528\u8BE5\u76EE\u5F55\u7684\u6D4F\u89C8\u5668\uFF09\u3002\u672A\u4F20\u65F6\u4F7F\u7528\u73AF\u5883\u53D8\u91CF Z_MCP_CODESIGN_EDGE_USER_DATA \u6216\u7CFB\u7EDF\u4E34\u65F6\u76EE\u5F55\u4E0B\u9ED8\u8BA4\u914D\u7F6E\u3002"
|
|
21474
|
-
),
|
|
21475
21412
|
profileDirectory: external_exports.string().optional().describe("User Data \u4E0B\u914D\u7F6E\u540D\uFF0C\u5982 Default\u3002")
|
|
21476
21413
|
});
|
|
21477
|
-
async function
|
|
21414
|
+
async function clickFirstVisibleText(page, candidates) {
|
|
21415
|
+
for (const text of candidates) {
|
|
21416
|
+
const loc = page.getByText(text, { exact: true }).first();
|
|
21417
|
+
try {
|
|
21418
|
+
if (await loc.isVisible()) {
|
|
21419
|
+
await loc.click();
|
|
21420
|
+
return true;
|
|
21421
|
+
}
|
|
21422
|
+
} catch {
|
|
21423
|
+
}
|
|
21424
|
+
}
|
|
21425
|
+
return false;
|
|
21426
|
+
}
|
|
21427
|
+
async function runScreenViewerDownloadSave(deps2, input) {
|
|
21478
21428
|
return withCodesignPage(
|
|
21479
21429
|
deps2,
|
|
21480
21430
|
input,
|
|
21481
21431
|
async (page) => {
|
|
21482
|
-
const
|
|
21483
|
-
|
|
21484
|
-
|
|
21432
|
+
const action = page.locator(".screen-viewer__action").first();
|
|
21433
|
+
try {
|
|
21434
|
+
await action.waitFor({ state: "visible", timeout: 5e3 });
|
|
21435
|
+
} catch {
|
|
21436
|
+
return toolError(
|
|
21437
|
+
"\u672A\u627E\u5230\u53EF\u89C1\u7684 .screen-viewer__action\uFF08\u53EF\u80FD\u672A\u8FDB\u5165\u53EF\u4E0B\u8F7D\u7684\u753B\u677F\u89C6\u56FE\uFF09\u3002"
|
|
21438
|
+
);
|
|
21439
|
+
}
|
|
21440
|
+
const downloadPromise = page.waitForEvent("download", {
|
|
21441
|
+
timeout: Math.max(1e4, Math.min(45e3, input.timeoutMs ?? 6e4))
|
|
21442
|
+
});
|
|
21443
|
+
await action.click();
|
|
21444
|
+
const clicked = await clickFirstVisibleText(page, [
|
|
21445
|
+
"\u4E0B\u8F7D\u56FE\u7247",
|
|
21446
|
+
"\u4E0B\u8F7D\u539F\u56FE",
|
|
21447
|
+
"\u4E0B\u8F7D"
|
|
21448
|
+
]);
|
|
21449
|
+
if (!clicked) {
|
|
21450
|
+
return toolError(
|
|
21451
|
+
"\u672A\u627E\u5230\u201C\u4E0B\u8F7D\u56FE\u7247\u201D\u6309\u94AE/\u83DC\u5355\u9879\uFF08\u53EF\u80FD\u9875\u9762\u7ED3\u6784\u53D8\u66F4\u6216\u672A\u767B\u5F55\uFF09\u3002"
|
|
21452
|
+
);
|
|
21485
21453
|
}
|
|
21486
|
-
|
|
21454
|
+
let download;
|
|
21455
|
+
try {
|
|
21456
|
+
download = await downloadPromise;
|
|
21457
|
+
} catch {
|
|
21458
|
+
return toolError("\u672A\u6355\u83B7\u5230\u4E0B\u8F7D\u4E8B\u4EF6\uFF08\u70B9\u51FB\u540E\u672A\u89E6\u53D1\u4E0B\u8F7D\uFF09\u3002");
|
|
21459
|
+
}
|
|
21460
|
+
const suggested = download.suggestedFilename() || "codesign_download.png";
|
|
21461
|
+
const ext = path.extname(suggested) || ".png";
|
|
21462
|
+
const outDir = path.resolve(process.cwd(), "_z-mcp-imgs");
|
|
21487
21463
|
const { projectId, pageId } = deriveCodesignIds(input.url);
|
|
21488
21464
|
const filenameParts = [
|
|
21489
21465
|
"codesign",
|
|
21466
|
+
"viewer_download",
|
|
21490
21467
|
projectId ? `p${safeSegment(projectId)}` : void 0,
|
|
21491
21468
|
pageId ? `s${safeSegment(pageId)}` : void 0,
|
|
21492
21469
|
timestampCompact(/* @__PURE__ */ new Date())
|
|
21493
21470
|
].filter(Boolean);
|
|
21494
|
-
const finalPath = path.join(outDir, `${filenameParts.join("_")}
|
|
21495
|
-
await
|
|
21496
|
-
await
|
|
21471
|
+
const finalPath = path.join(outDir, `${filenameParts.join("_")}${ext}`);
|
|
21472
|
+
await mkdir2(path.dirname(finalPath), { recursive: true });
|
|
21473
|
+
await download.saveAs(finalPath);
|
|
21497
21474
|
return toolResult(
|
|
21498
21475
|
JSON.stringify(
|
|
21499
21476
|
{
|
|
21500
21477
|
url: input.url,
|
|
21501
21478
|
title: await page.title(),
|
|
21502
|
-
|
|
21503
|
-
savedPath: finalPath
|
|
21504
|
-
boundingBox: shot.boundingBox
|
|
21505
|
-
},
|
|
21506
|
-
null,
|
|
21507
|
-
2
|
|
21508
|
-
)
|
|
21509
|
-
);
|
|
21510
|
-
},
|
|
21511
|
-
{
|
|
21512
|
-
waitForSelector: { selector: ".screen-inspect", state: "visible" },
|
|
21513
|
-
defaults: { afterLoadWaitMs: 250 }
|
|
21514
|
-
}
|
|
21515
|
-
);
|
|
21516
|
-
}
|
|
21517
|
-
function registerScreenInspectSaveTool(mcpServer2, deps2) {
|
|
21518
|
-
mcpServer2.registerTool(
|
|
21519
|
-
"codesign_screen_inspect_save",
|
|
21520
|
-
{
|
|
21521
|
-
description: "\u6253\u5F00 CoDesign \u9875\u9762\uFF0C\u4EC5\u622A\u53D6\u9762\u79EF\u6700\u5927\u7684\u53EF\u89C1 .screen-inspect \u533A\u57DF\uFF0C\u4FDD\u5B58\u4E3A\u672C\u5730 PNG \u6587\u4EF6\u5E76\u8FD4\u56DE\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u4FDD\u5B58\u5230\u9879\u76EE\u6839\u76EE\u5F55 .codesign_screen_imgs\uFF09\u3002",
|
|
21522
|
-
inputSchema: screenInspectSaveInput
|
|
21523
|
-
},
|
|
21524
|
-
(input) => runScreenInspectSave(deps2, input)
|
|
21525
|
-
);
|
|
21526
|
-
}
|
|
21527
|
-
|
|
21528
|
-
// src/tools/screen-list.ts
|
|
21529
|
-
var screenListInput = external_exports.object({
|
|
21530
|
-
url: external_exports.string().url().describe(
|
|
21531
|
-
"CoDesign \u8BBE\u8BA1\u9875\u9762\u5730\u5740\uFF0C\u5982 https://codesign.qq.com/app/design/<projectId>/<pageId>/inspect"
|
|
21532
|
-
),
|
|
21533
|
-
headless: external_exports.boolean().optional().describe("\u65E0\u5934\u6A21\u5F0F\uFF0C\u9ED8\u8BA4 true"),
|
|
21534
|
-
timeoutMs: external_exports.number().int().positive().optional().describe("\u6574\u4F53\u8D85\u65F6\u6BEB\u79D2\u6570\uFF0C\u9ED8\u8BA4 60000"),
|
|
21535
|
-
userDataDir: external_exports.string().optional().describe("\u6D4F\u89C8\u5668\u7528\u6237\u6570\u636E\u6839\u76EE\u5F55\uFF1B\u672A\u4F20\u65F6\u540C\u6293\u56FE\u5DE5\u5177\uFF08\u73AF\u5883\u53D8\u91CF\u6216\u4E34\u65F6\u76EE\u5F55\uFF09\u3002"),
|
|
21536
|
-
profileDirectory: external_exports.string().optional().describe("User Data \u4E0B\u914D\u7F6E\u540D\uFF0C\u5982 Default\u3002")
|
|
21537
|
-
});
|
|
21538
|
-
async function runScreenList(deps2, input) {
|
|
21539
|
-
return withCodesignPage(
|
|
21540
|
-
deps2,
|
|
21541
|
-
input,
|
|
21542
|
-
async (page) => {
|
|
21543
|
-
const pages = await page.evaluate(() => {
|
|
21544
|
-
const items = document.querySelectorAll(".screen-list__item");
|
|
21545
|
-
const result = [];
|
|
21546
|
-
for (const item of items) {
|
|
21547
|
-
const id = item.getAttribute("id") || "";
|
|
21548
|
-
const match = id.match(/^screen-(\d+)$/);
|
|
21549
|
-
if (!match) continue;
|
|
21550
|
-
const pageId = match[1];
|
|
21551
|
-
let name = "";
|
|
21552
|
-
const nameEl = item.querySelector(
|
|
21553
|
-
"[class*='name'], [class*='title'], [class*='label']"
|
|
21554
|
-
);
|
|
21555
|
-
if (nameEl) {
|
|
21556
|
-
name = nameEl.textContent?.trim() || "";
|
|
21557
|
-
}
|
|
21558
|
-
if (!name) {
|
|
21559
|
-
name = item.textContent?.trim().replace(/\s+/g, " ") || "";
|
|
21560
|
-
}
|
|
21561
|
-
result.push({
|
|
21562
|
-
name,
|
|
21563
|
-
pageId
|
|
21564
|
-
});
|
|
21565
|
-
}
|
|
21566
|
-
return result;
|
|
21567
|
-
});
|
|
21568
|
-
if (pages.length === 0) {
|
|
21569
|
-
return toolError("\u672A\u627E\u5230\u5DE6\u4FA7\u83DC\u5355\u4E2D\u7684\u9875\u9762\u5217\u8868\u3002");
|
|
21570
|
-
}
|
|
21571
|
-
const currentUrl = new URL(input.url);
|
|
21572
|
-
const pathParts = currentUrl.pathname.split("/");
|
|
21573
|
-
const projectId = pathParts.find((p) => /^\d{10,}$/.test(p)) || "";
|
|
21574
|
-
const currentPageId = pathParts.find((p) => /^\d+$/.test(p)) || "";
|
|
21575
|
-
const resultData = pages.map((p) => ({
|
|
21576
|
-
name: p.name,
|
|
21577
|
-
pageId: p.pageId,
|
|
21578
|
-
url: projectId ? `https://codesign.qq.com/app/design/${projectId}/${p.pageId}/inspect` : currentPageId ? input.url.replace(`/${currentPageId}/`, `/${p.pageId}/`) : input.url
|
|
21579
|
-
}));
|
|
21580
|
-
return toolResult(
|
|
21581
|
-
JSON.stringify(
|
|
21582
|
-
{
|
|
21583
|
-
projectId,
|
|
21584
|
-
totalCount: resultData.length,
|
|
21585
|
-
pages: resultData
|
|
21479
|
+
suggestedFilename: suggested,
|
|
21480
|
+
savedPath: finalPath
|
|
21586
21481
|
},
|
|
21587
21482
|
null,
|
|
21588
21483
|
2
|
|
@@ -21590,35 +21485,33 @@ async function runScreenList(deps2, input) {
|
|
|
21590
21485
|
);
|
|
21591
21486
|
},
|
|
21592
21487
|
{
|
|
21593
|
-
waitForSelector: { selector: ".screen-
|
|
21594
|
-
defaults: { afterLoadWaitMs:
|
|
21488
|
+
waitForSelector: { selector: ".screen-viewer__action", state: "visible" },
|
|
21489
|
+
defaults: { afterLoadWaitMs: 600, networkIdleMaxWaitMs: 2e3 }
|
|
21595
21490
|
}
|
|
21596
21491
|
);
|
|
21597
21492
|
}
|
|
21598
|
-
function
|
|
21493
|
+
function registerScreenViewerDownloadSaveTool(mcpServer2, deps2) {
|
|
21599
21494
|
mcpServer2.registerTool(
|
|
21600
|
-
"
|
|
21495
|
+
"codesign_screen_viewer_download_save",
|
|
21601
21496
|
{
|
|
21602
|
-
description: "\
|
|
21603
|
-
inputSchema:
|
|
21497
|
+
description: "\u6253\u5F00 CoDesign \u9875\u9762\uFF0C\u70B9\u51FB\u201C\u4E0B\u8F7D\u56FE\u7247\u201D\uFF0C\u6355\u83B7\u6D4F\u89C8\u5668\u4E0B\u8F7D\u5E76\u4FDD\u5B58\u5230\u9879\u76EE\u6839\u76EE\u5F55 _z-mcp-imgs/\u3002\u4E0B\u8F7DCoDesign\u9875\u9762\u56FE\u7247\u5230\u672C\u5730",
|
|
21498
|
+
inputSchema: screenViewerDownloadSaveInput
|
|
21604
21499
|
},
|
|
21605
|
-
(input) =>
|
|
21500
|
+
(input) => runScreenViewerDownloadSave(deps2, input)
|
|
21606
21501
|
);
|
|
21607
21502
|
}
|
|
21608
21503
|
|
|
21609
21504
|
// src/tools/register-all.ts
|
|
21610
21505
|
function registerAllCodesignTools(mcpServer2, deps2) {
|
|
21611
|
-
|
|
21612
|
-
registerScreenInspectSaveTool(mcpServer2, deps2);
|
|
21506
|
+
registerScreenViewerDownloadSaveTool(mcpServer2, deps2);
|
|
21613
21507
|
registerScreenListTool(mcpServer2, deps2);
|
|
21614
21508
|
registerOpenLoginTool(mcpServer2, deps2);
|
|
21615
|
-
registerSaveImageTool(mcpServer2);
|
|
21616
21509
|
}
|
|
21617
21510
|
|
|
21618
21511
|
// src/index.ts
|
|
21619
21512
|
var SERVER_NAME = "z-mcp-codesign";
|
|
21620
21513
|
var _require = createRequire(import.meta.url);
|
|
21621
|
-
var _dirname =
|
|
21514
|
+
var _dirname = dirname(fileURLToPath(import.meta.url));
|
|
21622
21515
|
var SERVER_VERSION = _require(join4(_dirname, "..", "package.json")).version ?? "1.0.0";
|
|
21623
21516
|
var USAGE = "npx -y z-mcp-codesign --stdio";
|
|
21624
21517
|
var args = process.argv.slice(2);
|