@pyrokine/mcp-chrome 2.1.0 → 2.3.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.
Files changed (39) hide show
  1. package/README.md +38 -20
  2. package/README_zh.md +578 -0
  3. package/dist/cdp/launcher.d.ts.map +1 -1
  4. package/dist/cdp/launcher.js +41 -19
  5. package/dist/cdp/launcher.js.map +1 -1
  6. package/dist/core/browser-driver.d.ts +3 -0
  7. package/dist/core/browser-driver.d.ts.map +1 -1
  8. package/dist/core/browser-driver.js.map +1 -1
  9. package/dist/core/session.d.ts.map +1 -1
  10. package/dist/core/session.js +41 -12
  11. package/dist/core/session.js.map +1 -1
  12. package/dist/core/types.d.ts +12 -0
  13. package/dist/core/types.d.ts.map +1 -1
  14. package/dist/core/types.js +41 -0
  15. package/dist/core/types.js.map +1 -1
  16. package/dist/core/unified-session.d.ts +9 -0
  17. package/dist/core/unified-session.d.ts.map +1 -1
  18. package/dist/core/unified-session.js +105 -34
  19. package/dist/core/unified-session.js.map +1 -1
  20. package/dist/core/utils.d.ts.map +1 -1
  21. package/dist/core/utils.js +21 -8
  22. package/dist/core/utils.js.map +1 -1
  23. package/dist/extension/http-server.d.ts +6 -0
  24. package/dist/extension/http-server.d.ts.map +1 -1
  25. package/dist/extension/http-server.js +86 -4
  26. package/dist/extension/http-server.js.map +1 -1
  27. package/dist/tools/evaluate.d.ts.map +1 -1
  28. package/dist/tools/evaluate.js +10 -0
  29. package/dist/tools/evaluate.js.map +1 -1
  30. package/dist/tools/input.d.ts.map +1 -1
  31. package/dist/tools/input.js +7 -0
  32. package/dist/tools/input.js.map +1 -1
  33. package/dist/tools/manage.js +1 -1
  34. package/dist/tools/manage.js.map +1 -1
  35. package/dist/tools/post-condition.d.ts +14 -0
  36. package/dist/tools/post-condition.d.ts.map +1 -0
  37. package/dist/tools/post-condition.js +154 -0
  38. package/dist/tools/post-condition.js.map +1 -0
  39. package/package.json +9 -6
@@ -0,0 +1,154 @@
1
+ import { z } from 'zod';
2
+ const POST_CONDITION_DEFAULT_TIMEOUT_MS = 3000;
3
+ const POST_CONDITION_MAX_TIMEOUT_MS = 60_000;
4
+ const POST_CONDITION_DEFAULT_INTERVAL_MS = 100;
5
+ const POST_CONDITION_MIN_INTERVAL_MS = 50;
6
+ const POST_CONDITION_MAX_INTERVAL_MS = 5000;
7
+ export const postConditionSchema = z
8
+ .object({
9
+ text: z.string().optional().describe('等待页面文本包含该内容'),
10
+ selector: z.string().optional().describe('等待 CSS selector 至少匹配一个元素'),
11
+ urlIncludes: z.string().optional().describe('等待当前 URL 包含该字符串'),
12
+ script: z.string().optional().describe('等待 JavaScript 表达式或函数返回 truthy'),
13
+ exact: z.boolean().optional().describe('text 使用精确匹配,默认 false'),
14
+ timeout: z
15
+ .number()
16
+ .int()
17
+ .positive()
18
+ .max(POST_CONDITION_MAX_TIMEOUT_MS)
19
+ .optional()
20
+ .describe('等待超时毫秒,默认 3000,最大 60000'),
21
+ interval: z
22
+ .number()
23
+ .int()
24
+ .min(POST_CONDITION_MIN_INTERVAL_MS)
25
+ .max(POST_CONDITION_MAX_INTERVAL_MS)
26
+ .optional()
27
+ .describe('轮询间隔毫秒,默认 100,范围 50-5000'),
28
+ })
29
+ .refine((value) => value.text || value.selector || value.urlIncludes || value.script, {
30
+ message: 'postCondition 至少需要 text、selector、urlIncludes、script 之一',
31
+ });
32
+ class PostConditionError extends Error {
33
+ context;
34
+ code = 'POST_CONDITION_FAILED';
35
+ suggestion = '工具动作已执行,但 postCondition 未满足。请检查页面状态、异步业务流程或放宽 postCondition 条件';
36
+ constructor(context) {
37
+ super('postCondition 未满足,工具动作不能证明业务目标已经达成');
38
+ this.context = context;
39
+ this.name = 'PostConditionError';
40
+ }
41
+ toJSON() {
42
+ return {
43
+ error: {
44
+ code: this.code,
45
+ message: this.message,
46
+ suggestion: this.suggestion,
47
+ context: this.context,
48
+ },
49
+ };
50
+ }
51
+ }
52
+ function sleep(ms) {
53
+ return new Promise((resolve) => setTimeout(resolve, ms));
54
+ }
55
+ function remainingMs(timeout, startedAt) {
56
+ return Math.max(0, timeout - (Date.now() - startedAt));
57
+ }
58
+ async function checkPostCondition(unifiedSession, condition, remainingTimeout) {
59
+ const checks = [];
60
+ if (condition.text !== undefined) {
61
+ const result = await unifiedSession.evaluate(`(expected, exact) => {
62
+ const body = document.body
63
+ const sampleLimit = 500
64
+ const appendSample = (sample, value) =>
65
+ sample.length >= sampleLimit ? sample : sample + value.slice(0, sampleLimit - sample.length)
66
+ const formatSample = (sample, truncated) => ({
67
+ actual: truncated ? sample.slice(0, sampleLimit) + '...' : sample,
68
+ truncated,
69
+ })
70
+ if (!body) {
71
+ return { matched: false, actual: '', truncated: false }
72
+ }
73
+ if (exact) {
74
+ const text = body.textContent || ''
75
+ const sample = text.slice(0, sampleLimit)
76
+ return { matched: text === expected, ...formatSample(sample, text.length > sampleLimit) }
77
+ }
78
+
79
+ const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT)
80
+ let node = walker.nextNode()
81
+ let carry = ''
82
+ let sample = ''
83
+ let total = 0
84
+ const carryLength = Math.max(0, expected.length - 1)
85
+ while (node) {
86
+ const value = node.nodeValue || ''
87
+ sample = appendSample(sample, value)
88
+ total += value.length
89
+ const searchable = carry + value
90
+ if (searchable.includes(expected)) {
91
+ return { matched: true, ...formatSample(sample, total > sampleLimit) }
92
+ }
93
+ carry = carryLength > 0 ? searchable.slice(-carryLength) : ''
94
+ node = walker.nextNode()
95
+ }
96
+ return { matched: false, ...formatSample(sample, total > sampleLimit) }
97
+ }`, undefined, Math.max(1, remainingTimeout), [condition.text, condition.exact === true]);
98
+ checks.push({
99
+ name: 'text',
100
+ matched: result.matched,
101
+ actual: result.actual,
102
+ });
103
+ }
104
+ if (condition.selector !== undefined) {
105
+ const count = await unifiedSession.evaluate('(selector) => document.querySelectorAll(selector).length', undefined, Math.max(1, remainingTimeout), [condition.selector]);
106
+ checks.push({ name: 'selector', matched: count > 0, actual: { count } });
107
+ }
108
+ if (condition.urlIncludes !== undefined) {
109
+ const url = await unifiedSession.evaluate('location.href', undefined, Math.max(1, remainingTimeout));
110
+ checks.push({ name: 'urlIncludes', matched: url.includes(condition.urlIncludes), actual: url });
111
+ }
112
+ if (condition.script !== undefined) {
113
+ const value = await unifiedSession.evaluate(condition.script, undefined, Math.max(1, remainingTimeout));
114
+ checks.push({ name: 'script', matched: Boolean(value), actual: value });
115
+ }
116
+ return checks;
117
+ }
118
+ export async function waitForPostCondition(unifiedSession, condition, operation) {
119
+ const timeout = condition.timeout ?? POST_CONDITION_DEFAULT_TIMEOUT_MS;
120
+ const interval = condition.interval ?? POST_CONDITION_DEFAULT_INTERVAL_MS;
121
+ const startedAt = Date.now();
122
+ let lastChecks = [];
123
+ let lastError;
124
+ while (remainingMs(timeout, startedAt) > 0) {
125
+ try {
126
+ const checkTimeout = Math.max(1, Math.min(interval, remainingMs(timeout, startedAt)));
127
+ lastChecks = await checkPostCondition(unifiedSession, condition, checkTimeout);
128
+ lastError = undefined;
129
+ if (lastChecks.every((check) => check.matched)) {
130
+ return {
131
+ matched: true,
132
+ operation,
133
+ elapsedMs: Date.now() - startedAt,
134
+ checks: lastChecks,
135
+ };
136
+ }
137
+ }
138
+ catch (error) {
139
+ lastError = error instanceof Error ? error.message : String(error);
140
+ }
141
+ const waitMs = Math.min(interval, remainingMs(timeout, startedAt));
142
+ if (waitMs <= 0) {
143
+ break;
144
+ }
145
+ await sleep(waitMs);
146
+ }
147
+ throw new PostConditionError({
148
+ operation,
149
+ timeout,
150
+ checks: lastChecks,
151
+ lastError,
152
+ });
153
+ }
154
+ //# sourceMappingURL=post-condition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"post-condition.js","sourceRoot":"","sources":["../../src/tools/post-condition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAGvB,MAAM,iCAAiC,GAAG,IAAI,CAAA;AAC9C,MAAM,6BAA6B,GAAG,MAAM,CAAA;AAC5C,MAAM,kCAAkC,GAAG,GAAG,CAAA;AAC9C,MAAM,8BAA8B,GAAG,EAAE,CAAA;AACzC,MAAM,8BAA8B,GAAG,IAAI,CAAA;AAE3C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC;KAC/B,MAAM,CAAC;IACJ,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;IACnD,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACpE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAC9D,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IACvE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAC9D,OAAO,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,EAAE;SACL,QAAQ,EAAE;SACV,GAAG,CAAC,6BAA6B,CAAC;SAClC,QAAQ,EAAE;SACV,QAAQ,CAAC,yBAAyB,CAAC;IACxC,QAAQ,EAAE,CAAC;SACN,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,8BAA8B,CAAC;SACnC,GAAG,CAAC,8BAA8B,CAAC;SACnC,QAAQ,EAAE;SACV,QAAQ,CAAC,0BAA0B,CAAC;CAC5C,CAAC;KACD,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,MAAM,EAAE;IAClF,OAAO,EAAE,wDAAwD;CACpE,CAAC,CAAA;AAgBN,MAAM,kBAAmB,SAAQ,KAAK;IAKb;IAJZ,IAAI,GAAG,uBAAuB,CAAA;IAC9B,UAAU,GACf,gEAAgE,CAAA;IAEpE,YAAqB,OAAgC;QACjD,KAAK,CAAC,oCAAoC,CAAC,CAAA;QAD1B,YAAO,GAAP,OAAO,CAAyB;QAEjD,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAA;IACpC,CAAC;IAED,MAAM;QACF,OAAO;YACH,KAAK,EAAE;gBACH,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;aACxB;SACJ,CAAA;IACL,CAAC;CACJ;AAED,SAAS,KAAK,CAAC,EAAU;IACrB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,WAAW,CAAC,OAAe,EAAE,SAAiB;IACnD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC7B,cAAoD,EACpD,SAAwB,EACxB,gBAAwB;IAExB,MAAM,MAAM,GAAkB,EAAE,CAAA;IAEhC,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,QAAQ,CACxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoCE,EACF,SAAS,EACT,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAC7B,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,KAAK,KAAK,IAAI,CAAC,CAC7C,CAAA;QACD,MAAM,CAAC,IAAI,CAAC;YACR,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,MAAM,EAAE,MAAM,CAAC,MAAM;SACxB,CAAC,CAAA;IACN,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,QAAQ,CACvC,0DAA0D,EAC1D,SAAS,EACT,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAC7B,CAAC,SAAS,CAAC,QAAQ,CAAC,CACvB,CAAA;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,IAAI,SAAS,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAS,eAAe,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAA;QAC5G,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;IACnG,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,QAAQ,CAAU,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAA;QAChH,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IAC3E,CAAC;IAED,OAAO,MAAM,CAAA;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACtC,cAAoD,EACpD,SAAwB,EACxB,SAAiB;IAEjB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,IAAI,iCAAiC,CAAA;IACtE,MAAM,QAAQ,GAAG,SAAS,CAAC,QAAQ,IAAI,kCAAkC,CAAA;IACzE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IAC5B,IAAI,UAAU,GAAkB,EAAE,CAAA;IAClC,IAAI,SAA6B,CAAA;IAEjC,OAAO,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC;YACD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;YACrF,UAAU,GAAG,MAAM,kBAAkB,CAAC,cAAc,EAAE,SAAS,EAAE,YAAY,CAAC,CAAA;YAC9E,SAAS,GAAG,SAAS,CAAA;YACrB,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC7C,OAAO;oBACH,OAAO,EAAE,IAAI;oBACb,SAAS;oBACT,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;oBACjC,MAAM,EAAE,UAAU;iBACrB,CAAA;YACL,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,SAAS,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACtE,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;QAClE,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YACd,MAAK;QACT,CAAC;QACD,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;IACvB,CAAC;IAED,MAAM,IAAI,kBAAkB,CAAC;QACzB,SAAS;QACT,OAAO;QACP,MAAM,EAAE,UAAU;QAClB,SAAS;KACZ,CAAC,CAAA;AACN,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pyrokine/mcp-chrome",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
4
4
  "description": "Chrome browser automation MCP Server using Chrome DevTools Protocol",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -31,12 +31,12 @@
31
31
  },
32
32
  "devDependencies": {
33
33
  "@eslint/js": "^10.0.1",
34
- "@types/node": "^25.9.1",
34
+ "@types/node": "^25.9.3",
35
35
  "@types/ws": "^8.18.1",
36
- "eslint": "^10.4.0",
37
- "prettier": "^3.8.3",
36
+ "eslint": "^10.5.0",
37
+ "prettier": "^3.8.4",
38
38
  "typescript": "^6.0.3",
39
- "typescript-eslint": "^8.60.0"
39
+ "typescript-eslint": "^8.61.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=18"
@@ -45,6 +45,9 @@
45
45
  "mcp-chrome": "dist/index.js"
46
46
  },
47
47
  "files": [
48
- "dist"
48
+ "dist",
49
+ "README.md",
50
+ "README_zh.md",
51
+ "LICENSE"
49
52
  ]
50
53
  }