@playwright/mcp 0.0.10 → 0.0.14
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 +133 -32
- package/index.d.ts +37 -24
- package/lib/context.js +162 -76
- package/lib/index.js +63 -11
- package/lib/javascript.js +54 -0
- package/lib/manualPromise.js +116 -0
- package/lib/program.js +9 -55
- package/lib/server.js +15 -4
- package/lib/tools/common.js +40 -12
- package/lib/{resources → tools}/console.js +23 -12
- package/lib/tools/dialogs.js +54 -0
- package/lib/tools/files.js +16 -7
- package/lib/tools/install.js +3 -4
- package/lib/tools/keyboard.js +11 -5
- package/lib/tools/navigate.js +34 -20
- package/lib/tools/pdf.js +43 -6
- package/lib/tools/screen.js +108 -19
- package/lib/tools/snapshot.js +154 -42
- package/lib/tools/tabs.js +36 -18
- package/lib/tools/utils.js +2 -2
- package/package.json +5 -1
package/lib/tools/screen.js
CHANGED
|
@@ -14,9 +14,43 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
17
50
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
51
|
const zod_1 = require("zod");
|
|
19
52
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
53
|
+
const javascript = __importStar(require("../javascript"));
|
|
20
54
|
const screenshot = {
|
|
21
55
|
capability: 'core',
|
|
22
56
|
schema: {
|
|
@@ -25,10 +59,22 @@ const screenshot = {
|
|
|
25
59
|
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({})),
|
|
26
60
|
},
|
|
27
61
|
handle: async (context) => {
|
|
28
|
-
const tab = context.
|
|
29
|
-
const
|
|
62
|
+
const tab = await context.ensureTab();
|
|
63
|
+
const options = { type: 'jpeg', quality: 50, scale: 'css' };
|
|
64
|
+
const code = [
|
|
65
|
+
`// Take a screenshot of the current page`,
|
|
66
|
+
`await page.screenshot(${javascript.formatObject(options)});`,
|
|
67
|
+
];
|
|
68
|
+
const action = () => tab.page.screenshot(options).then(buffer => {
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: 'image', data: buffer.toString('base64'), mimeType: 'image/jpeg' }],
|
|
71
|
+
};
|
|
72
|
+
});
|
|
30
73
|
return {
|
|
31
|
-
|
|
74
|
+
code,
|
|
75
|
+
action,
|
|
76
|
+
captureSnapshot: false,
|
|
77
|
+
waitForNetwork: false
|
|
32
78
|
};
|
|
33
79
|
},
|
|
34
80
|
};
|
|
@@ -48,10 +94,17 @@ const moveMouse = {
|
|
|
48
94
|
},
|
|
49
95
|
handle: async (context, params) => {
|
|
50
96
|
const validatedParams = moveMouseSchema.parse(params);
|
|
51
|
-
const tab = context.
|
|
52
|
-
|
|
97
|
+
const tab = context.currentTabOrDie();
|
|
98
|
+
const code = [
|
|
99
|
+
`// Move mouse to (${validatedParams.x}, ${validatedParams.y})`,
|
|
100
|
+
`await page.mouse.move(${validatedParams.x}, ${validatedParams.y});`,
|
|
101
|
+
];
|
|
102
|
+
const action = () => tab.page.mouse.move(validatedParams.x, validatedParams.y);
|
|
53
103
|
return {
|
|
54
|
-
|
|
104
|
+
code,
|
|
105
|
+
action,
|
|
106
|
+
captureSnapshot: false,
|
|
107
|
+
waitForNetwork: false
|
|
55
108
|
};
|
|
56
109
|
},
|
|
57
110
|
};
|
|
@@ -67,14 +120,25 @@ const click = {
|
|
|
67
120
|
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(clickSchema),
|
|
68
121
|
},
|
|
69
122
|
handle: async (context, params) => {
|
|
70
|
-
|
|
71
|
-
|
|
123
|
+
const validatedParams = clickSchema.parse(params);
|
|
124
|
+
const tab = context.currentTabOrDie();
|
|
125
|
+
const code = [
|
|
126
|
+
`// Click mouse at coordinates (${validatedParams.x}, ${validatedParams.y})`,
|
|
127
|
+
`await page.mouse.move(${validatedParams.x}, ${validatedParams.y});`,
|
|
128
|
+
`await page.mouse.down();`,
|
|
129
|
+
`await page.mouse.up();`,
|
|
130
|
+
];
|
|
131
|
+
const action = async () => {
|
|
72
132
|
await tab.page.mouse.move(validatedParams.x, validatedParams.y);
|
|
73
133
|
await tab.page.mouse.down();
|
|
74
134
|
await tab.page.mouse.up();
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
135
|
+
};
|
|
136
|
+
return {
|
|
137
|
+
code,
|
|
138
|
+
action,
|
|
139
|
+
captureSnapshot: false,
|
|
140
|
+
waitForNetwork: true,
|
|
141
|
+
};
|
|
78
142
|
},
|
|
79
143
|
};
|
|
80
144
|
const dragSchema = elementSchema.extend({
|
|
@@ -92,14 +156,26 @@ const drag = {
|
|
|
92
156
|
},
|
|
93
157
|
handle: async (context, params) => {
|
|
94
158
|
const validatedParams = dragSchema.parse(params);
|
|
95
|
-
|
|
159
|
+
const tab = context.currentTabOrDie();
|
|
160
|
+
const code = [
|
|
161
|
+
`// Drag mouse from (${validatedParams.startX}, ${validatedParams.startY}) to (${validatedParams.endX}, ${validatedParams.endY})`,
|
|
162
|
+
`await page.mouse.move(${validatedParams.startX}, ${validatedParams.startY});`,
|
|
163
|
+
`await page.mouse.down();`,
|
|
164
|
+
`await page.mouse.move(${validatedParams.endX}, ${validatedParams.endY});`,
|
|
165
|
+
`await page.mouse.up();`,
|
|
166
|
+
];
|
|
167
|
+
const action = async () => {
|
|
96
168
|
await tab.page.mouse.move(validatedParams.startX, validatedParams.startY);
|
|
97
169
|
await tab.page.mouse.down();
|
|
98
170
|
await tab.page.mouse.move(validatedParams.endX, validatedParams.endY);
|
|
99
171
|
await tab.page.mouse.up();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
|
|
172
|
+
};
|
|
173
|
+
return {
|
|
174
|
+
code,
|
|
175
|
+
action,
|
|
176
|
+
captureSnapshot: false,
|
|
177
|
+
waitForNetwork: true,
|
|
178
|
+
};
|
|
103
179
|
},
|
|
104
180
|
};
|
|
105
181
|
const typeSchema = zod_1.z.object({
|
|
@@ -115,13 +191,26 @@ const type = {
|
|
|
115
191
|
},
|
|
116
192
|
handle: async (context, params) => {
|
|
117
193
|
const validatedParams = typeSchema.parse(params);
|
|
118
|
-
|
|
194
|
+
const tab = context.currentTabOrDie();
|
|
195
|
+
const code = [
|
|
196
|
+
`// Type ${validatedParams.text}`,
|
|
197
|
+
`await page.keyboard.type('${validatedParams.text}');`,
|
|
198
|
+
];
|
|
199
|
+
const action = async () => {
|
|
119
200
|
await tab.page.keyboard.type(validatedParams.text);
|
|
120
201
|
if (validatedParams.submit)
|
|
121
202
|
await tab.page.keyboard.press('Enter');
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
203
|
+
};
|
|
204
|
+
if (validatedParams.submit) {
|
|
205
|
+
code.push(`// Submit text`);
|
|
206
|
+
code.push(`await page.keyboard.press('Enter');`);
|
|
207
|
+
}
|
|
208
|
+
return {
|
|
209
|
+
code,
|
|
210
|
+
action,
|
|
211
|
+
captureSnapshot: false,
|
|
212
|
+
waitForNetwork: true,
|
|
213
|
+
};
|
|
125
214
|
},
|
|
126
215
|
};
|
|
127
216
|
exports.default = [
|
package/lib/tools/snapshot.js
CHANGED
|
@@ -14,12 +14,50 @@
|
|
|
14
14
|
* See the License for the specific language governing permissions and
|
|
15
15
|
* limitations under the License.
|
|
16
16
|
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
17
50
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
18
51
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
19
52
|
};
|
|
20
53
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
const path_1 = __importDefault(require("path"));
|
|
55
|
+
const os_1 = __importDefault(require("os"));
|
|
21
56
|
const zod_1 = require("zod");
|
|
22
57
|
const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
|
|
58
|
+
const utils_1 = require("./utils");
|
|
59
|
+
const context_1 = require("../context");
|
|
60
|
+
const javascript = __importStar(require("../javascript"));
|
|
23
61
|
const snapshot = {
|
|
24
62
|
capability: 'core',
|
|
25
63
|
schema: {
|
|
@@ -28,7 +66,12 @@ const snapshot = {
|
|
|
28
66
|
inputSchema: (0, zod_to_json_schema_1.default)(zod_1.z.object({})),
|
|
29
67
|
},
|
|
30
68
|
handle: async (context) => {
|
|
31
|
-
|
|
69
|
+
await context.ensureTab();
|
|
70
|
+
return {
|
|
71
|
+
code: [`// <internal code to capture accessibility snapshot>`],
|
|
72
|
+
captureSnapshot: true,
|
|
73
|
+
waitForNetwork: false,
|
|
74
|
+
};
|
|
32
75
|
},
|
|
33
76
|
};
|
|
34
77
|
const elementSchema = zod_1.z.object({
|
|
@@ -44,12 +87,18 @@ const click = {
|
|
|
44
87
|
},
|
|
45
88
|
handle: async (context, params) => {
|
|
46
89
|
const validatedParams = elementSchema.parse(params);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
90
|
+
const tab = context.currentTabOrDie();
|
|
91
|
+
const locator = tab.snapshotOrDie().refLocator(validatedParams.ref);
|
|
92
|
+
const code = [
|
|
93
|
+
`// Click ${validatedParams.element}`,
|
|
94
|
+
`await page.${await (0, context_1.generateLocator)(locator)}.click();`
|
|
95
|
+
];
|
|
96
|
+
return {
|
|
97
|
+
code,
|
|
98
|
+
action: () => locator.click(),
|
|
99
|
+
captureSnapshot: true,
|
|
100
|
+
waitForNetwork: true,
|
|
101
|
+
};
|
|
53
102
|
},
|
|
54
103
|
};
|
|
55
104
|
const dragSchema = zod_1.z.object({
|
|
@@ -67,13 +116,19 @@ const drag = {
|
|
|
67
116
|
},
|
|
68
117
|
handle: async (context, params) => {
|
|
69
118
|
const validatedParams = dragSchema.parse(params);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
119
|
+
const snapshot = context.currentTabOrDie().snapshotOrDie();
|
|
120
|
+
const startLocator = snapshot.refLocator(validatedParams.startRef);
|
|
121
|
+
const endLocator = snapshot.refLocator(validatedParams.endRef);
|
|
122
|
+
const code = [
|
|
123
|
+
`// Drag ${validatedParams.startElement} to ${validatedParams.endElement}`,
|
|
124
|
+
`await page.${await (0, context_1.generateLocator)(startLocator)}.dragTo(page.${await (0, context_1.generateLocator)(endLocator)});`
|
|
125
|
+
];
|
|
126
|
+
return {
|
|
127
|
+
code,
|
|
128
|
+
action: () => startLocator.dragTo(endLocator),
|
|
129
|
+
captureSnapshot: true,
|
|
130
|
+
waitForNetwork: true,
|
|
131
|
+
};
|
|
77
132
|
},
|
|
78
133
|
};
|
|
79
134
|
const hover = {
|
|
@@ -85,12 +140,18 @@ const hover = {
|
|
|
85
140
|
},
|
|
86
141
|
handle: async (context, params) => {
|
|
87
142
|
const validatedParams = elementSchema.parse(params);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
143
|
+
const snapshot = context.currentTabOrDie().snapshotOrDie();
|
|
144
|
+
const locator = snapshot.refLocator(validatedParams.ref);
|
|
145
|
+
const code = [
|
|
146
|
+
`// Hover over ${validatedParams.element}`,
|
|
147
|
+
`await page.${await (0, context_1.generateLocator)(locator)}.hover();`
|
|
148
|
+
];
|
|
149
|
+
return {
|
|
150
|
+
code,
|
|
151
|
+
action: () => locator.hover(),
|
|
152
|
+
captureSnapshot: true,
|
|
153
|
+
waitForNetwork: true,
|
|
154
|
+
};
|
|
94
155
|
},
|
|
95
156
|
};
|
|
96
157
|
const typeSchema = elementSchema.extend({
|
|
@@ -107,17 +168,31 @@ const type = {
|
|
|
107
168
|
},
|
|
108
169
|
handle: async (context, params) => {
|
|
109
170
|
const validatedParams = typeSchema.parse(params);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
|
|
171
|
+
const snapshot = context.currentTabOrDie().snapshotOrDie();
|
|
172
|
+
const locator = snapshot.refLocator(validatedParams.ref);
|
|
173
|
+
const code = [];
|
|
174
|
+
const steps = [];
|
|
175
|
+
if (validatedParams.slowly) {
|
|
176
|
+
code.push(`// Press "${validatedParams.text}" sequentially into "${validatedParams.element}"`);
|
|
177
|
+
code.push(`await page.${await (0, context_1.generateLocator)(locator)}.pressSequentially(${javascript.quote(validatedParams.text)});`);
|
|
178
|
+
steps.push(() => locator.pressSequentially(validatedParams.text));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
code.push(`// Fill "${validatedParams.text}" into "${validatedParams.element}"`);
|
|
182
|
+
code.push(`await page.${await (0, context_1.generateLocator)(locator)}.fill(${javascript.quote(validatedParams.text)});`);
|
|
183
|
+
steps.push(() => locator.fill(validatedParams.text));
|
|
184
|
+
}
|
|
185
|
+
if (validatedParams.submit) {
|
|
186
|
+
code.push(`// Submit text`);
|
|
187
|
+
code.push(`await page.${await (0, context_1.generateLocator)(locator)}.press('Enter');`);
|
|
188
|
+
steps.push(() => locator.press('Enter'));
|
|
189
|
+
}
|
|
190
|
+
return {
|
|
191
|
+
code,
|
|
192
|
+
action: () => steps.reduce((acc, step) => acc.then(step), Promise.resolve()),
|
|
193
|
+
captureSnapshot: true,
|
|
194
|
+
waitForNetwork: true,
|
|
195
|
+
};
|
|
121
196
|
},
|
|
122
197
|
};
|
|
123
198
|
const selectOptionSchema = elementSchema.extend({
|
|
@@ -132,16 +207,29 @@ const selectOption = {
|
|
|
132
207
|
},
|
|
133
208
|
handle: async (context, params) => {
|
|
134
209
|
const validatedParams = selectOptionSchema.parse(params);
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
210
|
+
const snapshot = context.currentTabOrDie().snapshotOrDie();
|
|
211
|
+
const locator = snapshot.refLocator(validatedParams.ref);
|
|
212
|
+
const code = [
|
|
213
|
+
`// Select options [${validatedParams.values.join(', ')}] in ${validatedParams.element}`,
|
|
214
|
+
`await page.${await (0, context_1.generateLocator)(locator)}.selectOption(${javascript.formatObject(validatedParams.values)});`
|
|
215
|
+
];
|
|
216
|
+
return {
|
|
217
|
+
code,
|
|
218
|
+
action: () => locator.selectOption(validatedParams.values).then(() => { }),
|
|
219
|
+
captureSnapshot: true,
|
|
220
|
+
waitForNetwork: true,
|
|
221
|
+
};
|
|
141
222
|
},
|
|
142
223
|
};
|
|
143
224
|
const screenshotSchema = zod_1.z.object({
|
|
144
225
|
raw: zod_1.z.boolean().optional().describe('Whether to return without compression (in PNG format). Default is false, which returns a JPEG image.'),
|
|
226
|
+
element: zod_1.z.string().optional().describe('Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too.'),
|
|
227
|
+
ref: zod_1.z.string().optional().describe('Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too.'),
|
|
228
|
+
}).refine(data => {
|
|
229
|
+
return !!data.element === !!data.ref;
|
|
230
|
+
}, {
|
|
231
|
+
message: 'Both element and ref must be provided or neither.',
|
|
232
|
+
path: ['ref', 'element']
|
|
145
233
|
});
|
|
146
234
|
const screenshot = {
|
|
147
235
|
capability: 'core',
|
|
@@ -152,13 +240,37 @@ const screenshot = {
|
|
|
152
240
|
},
|
|
153
241
|
handle: async (context, params) => {
|
|
154
242
|
const validatedParams = screenshotSchema.parse(params);
|
|
155
|
-
const tab = context.
|
|
156
|
-
const
|
|
157
|
-
const
|
|
243
|
+
const tab = context.currentTabOrDie();
|
|
244
|
+
const snapshot = tab.snapshotOrDie();
|
|
245
|
+
const fileType = validatedParams.raw ? 'png' : 'jpeg';
|
|
246
|
+
const fileName = path_1.default.join(os_1.default.tmpdir(), (0, utils_1.sanitizeForFilePath)(`page-${new Date().toISOString()}`)) + `.${fileType}`;
|
|
247
|
+
const options = { type: fileType, quality: fileType === 'png' ? undefined : 50, scale: 'css', path: fileName };
|
|
248
|
+
const isElementScreenshot = validatedParams.element && validatedParams.ref;
|
|
249
|
+
const code = [
|
|
250
|
+
`// Screenshot ${isElementScreenshot ? validatedParams.element : 'viewport'} and save it as ${fileName}`,
|
|
251
|
+
];
|
|
252
|
+
const locator = validatedParams.ref ? snapshot.refLocator(validatedParams.ref) : null;
|
|
253
|
+
if (locator)
|
|
254
|
+
code.push(`await page.${await (0, context_1.generateLocator)(locator)}.screenshot(${javascript.formatObject(options)});`);
|
|
255
|
+
else
|
|
256
|
+
code.push(`await page.screenshot(${javascript.formatObject(options)});`);
|
|
257
|
+
const action = async () => {
|
|
258
|
+
const screenshot = locator ? await locator.screenshot(options) : await tab.page.screenshot(options);
|
|
259
|
+
return {
|
|
260
|
+
content: [{
|
|
261
|
+
type: 'image',
|
|
262
|
+
data: screenshot.toString('base64'),
|
|
263
|
+
mimeType: fileType === 'png' ? 'image/png' : 'image/jpeg',
|
|
264
|
+
}]
|
|
265
|
+
};
|
|
266
|
+
};
|
|
158
267
|
return {
|
|
159
|
-
|
|
268
|
+
code,
|
|
269
|
+
action,
|
|
270
|
+
captureSnapshot: true,
|
|
271
|
+
waitForNetwork: false,
|
|
160
272
|
};
|
|
161
|
-
}
|
|
273
|
+
}
|
|
162
274
|
};
|
|
163
275
|
exports.default = [
|
|
164
276
|
snapshot,
|
package/lib/tools/tabs.js
CHANGED
|
@@ -25,11 +25,17 @@ const listTabs = {
|
|
|
25
25
|
inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({})),
|
|
26
26
|
},
|
|
27
27
|
handle: async (context) => {
|
|
28
|
+
await context.ensureTab();
|
|
28
29
|
return {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
code: [`// <internal code to list tabs>`],
|
|
31
|
+
captureSnapshot: false,
|
|
32
|
+
waitForNetwork: false,
|
|
33
|
+
resultOverride: {
|
|
34
|
+
content: [{
|
|
35
|
+
type: 'text',
|
|
36
|
+
text: await context.listTabsMarkdown(),
|
|
37
|
+
}],
|
|
38
|
+
},
|
|
33
39
|
};
|
|
34
40
|
},
|
|
35
41
|
};
|
|
@@ -46,14 +52,20 @@ const selectTab = captureSnapshot => ({
|
|
|
46
52
|
handle: async (context, params) => {
|
|
47
53
|
const validatedParams = selectTabSchema.parse(params);
|
|
48
54
|
await context.selectTab(validatedParams.index);
|
|
49
|
-
const
|
|
50
|
-
|
|
55
|
+
const code = [
|
|
56
|
+
`// <internal code to select tab ${validatedParams.index}>`,
|
|
57
|
+
];
|
|
58
|
+
return {
|
|
59
|
+
code,
|
|
60
|
+
captureSnapshot,
|
|
61
|
+
waitForNetwork: false
|
|
62
|
+
};
|
|
51
63
|
},
|
|
52
64
|
});
|
|
53
65
|
const newTabSchema = zod_1.z.object({
|
|
54
66
|
url: zod_1.z.string().optional().describe('The URL to navigate to in the new tab. If not provided, the new tab will be blank.'),
|
|
55
67
|
});
|
|
56
|
-
const newTab = {
|
|
68
|
+
const newTab = captureSnapshot => ({
|
|
57
69
|
capability: 'tabs',
|
|
58
70
|
schema: {
|
|
59
71
|
name: 'browser_tab_new',
|
|
@@ -64,10 +76,17 @@ const newTab = {
|
|
|
64
76
|
const validatedParams = newTabSchema.parse(params);
|
|
65
77
|
await context.newTab();
|
|
66
78
|
if (validatedParams.url)
|
|
67
|
-
await context.
|
|
68
|
-
|
|
79
|
+
await context.currentTabOrDie().navigate(validatedParams.url);
|
|
80
|
+
const code = [
|
|
81
|
+
`// <internal code to open a new tab>`,
|
|
82
|
+
];
|
|
83
|
+
return {
|
|
84
|
+
code,
|
|
85
|
+
captureSnapshot,
|
|
86
|
+
waitForNetwork: false
|
|
87
|
+
};
|
|
69
88
|
},
|
|
70
|
-
};
|
|
89
|
+
});
|
|
71
90
|
const closeTabSchema = zod_1.z.object({
|
|
72
91
|
index: zod_1.z.number().optional().describe('The index of the tab to close. Closes current tab if not provided.'),
|
|
73
92
|
});
|
|
@@ -81,20 +100,19 @@ const closeTab = captureSnapshot => ({
|
|
|
81
100
|
handle: async (context, params) => {
|
|
82
101
|
const validatedParams = closeTabSchema.parse(params);
|
|
83
102
|
await context.closeTab(validatedParams.index);
|
|
84
|
-
const
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
const code = [
|
|
104
|
+
`// <internal code to close tab ${validatedParams.index}>`,
|
|
105
|
+
];
|
|
87
106
|
return {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}],
|
|
107
|
+
code,
|
|
108
|
+
captureSnapshot,
|
|
109
|
+
waitForNetwork: false
|
|
92
110
|
};
|
|
93
111
|
},
|
|
94
112
|
});
|
|
95
113
|
exports.default = (captureSnapshot) => [
|
|
96
114
|
listTabs,
|
|
97
|
-
newTab,
|
|
115
|
+
newTab(captureSnapshot),
|
|
98
116
|
selectTab(captureSnapshot),
|
|
99
117
|
closeTab(captureSnapshot),
|
|
100
118
|
];
|
package/lib/tools/utils.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
18
|
exports.waitForCompletion = waitForCompletion;
|
|
19
19
|
exports.sanitizeForFilePath = sanitizeForFilePath;
|
|
20
|
-
async function waitForCompletion(page, callback) {
|
|
20
|
+
async function waitForCompletion(context, page, callback) {
|
|
21
21
|
const requests = new Set();
|
|
22
22
|
let frameNavigated = false;
|
|
23
23
|
let waitCallback = () => { };
|
|
@@ -57,7 +57,7 @@ async function waitForCompletion(page, callback) {
|
|
|
57
57
|
if (!requests.size && !frameNavigated)
|
|
58
58
|
waitCallback();
|
|
59
59
|
await waitBarrier;
|
|
60
|
-
await
|
|
60
|
+
await context.waitForTimeout(1000);
|
|
61
61
|
return result;
|
|
62
62
|
}
|
|
63
63
|
finally {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwright/mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.14",
|
|
4
4
|
"description": "Playwright Tools for MCP",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,8 +17,12 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"build": "tsc",
|
|
19
19
|
"lint": "eslint .",
|
|
20
|
+
"update-readme": "node utils/update-readme.js",
|
|
20
21
|
"watch": "tsc --watch",
|
|
21
22
|
"test": "playwright test",
|
|
23
|
+
"ctest": "playwright test --project=chrome",
|
|
24
|
+
"ftest": "playwright test --project=firefox",
|
|
25
|
+
"wtest": "playwright test --project=webkit",
|
|
22
26
|
"clean": "rm -rf lib",
|
|
23
27
|
"npm-publish": "npm run clean && npm run build && npm run test && npm publish"
|
|
24
28
|
},
|