@playwright/mcp 1.52.0-alpha-1742413599000 → 1.52.0-alpha-2025-03-20
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/lib/context.js +4 -1
- package/lib/resources/console.js +40 -0
- package/lib/resources/resource.js +5 -0
- package/lib/tools/common.js +162 -0
- package/lib/tools/screenshot.js +131 -0
- package/lib/tools/snapshot.js +105 -0
- package/lib/tools/tool.js +5 -0
- package/lib/tools/utils.js +96 -0
- package/package.json +3 -3
package/lib/context.js
CHANGED
|
@@ -60,7 +60,10 @@ class Context {
|
|
|
60
60
|
url.searchParams.set('launch-options', JSON.stringify(this._launchOptions));
|
|
61
61
|
return await playwright.chromium.connect(String(url));
|
|
62
62
|
}
|
|
63
|
-
return await playwright.chromium.launch(
|
|
63
|
+
return await playwright.chromium.launch({
|
|
64
|
+
channel: 'chrome',
|
|
65
|
+
...this._launchOptions
|
|
66
|
+
});
|
|
64
67
|
}
|
|
65
68
|
}
|
|
66
69
|
exports.Context = Context;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.console = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* Copyright (c) Microsoft Corporation.
|
|
9
|
+
*
|
|
10
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
11
|
+
* you may not use this file except in compliance with the License.
|
|
12
|
+
* You may obtain a copy of the License at
|
|
13
|
+
*
|
|
14
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
+
*
|
|
16
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
+
* See the License for the specific language governing permissions and
|
|
20
|
+
* limitations under the License.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
const console = exports.console = {
|
|
24
|
+
schema: {
|
|
25
|
+
uri: 'browser://console',
|
|
26
|
+
name: 'Page console',
|
|
27
|
+
mimeType: 'text/plain'
|
|
28
|
+
},
|
|
29
|
+
read: async (context, uri) => {
|
|
30
|
+
const result = [];
|
|
31
|
+
for (const message of await context.ensureConsole()) {
|
|
32
|
+
result.push({
|
|
33
|
+
uri,
|
|
34
|
+
mimeType: 'text/plain',
|
|
35
|
+
text: `[${message.type().toUpperCase()}] ${message.text()}`
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.wait = exports.pressKey = exports.pdf = exports.navigate = exports.goForward = exports.goBack = exports.close = void 0;
|
|
7
|
+
var _os = _interopRequireDefault(require("os"));
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _zod = require("zod");
|
|
10
|
+
var _zodToJsonSchema = require("zod-to-json-schema");
|
|
11
|
+
var _utils = require("./utils");
|
|
12
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
13
|
+
/**
|
|
14
|
+
* Copyright (c) Microsoft Corporation.
|
|
15
|
+
*
|
|
16
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
17
|
+
* you may not use this file except in compliance with the License.
|
|
18
|
+
* You may obtain a copy of the License at
|
|
19
|
+
*
|
|
20
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
21
|
+
*
|
|
22
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
23
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
24
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
25
|
+
* See the License for the specific language governing permissions and
|
|
26
|
+
* limitations under the License.
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
const navigateSchema = _zod.z.object({
|
|
30
|
+
url: _zod.z.string().describe('The URL to navigate to')
|
|
31
|
+
});
|
|
32
|
+
const navigate = snapshot => ({
|
|
33
|
+
schema: {
|
|
34
|
+
name: 'browser_navigate',
|
|
35
|
+
description: 'Navigate to a URL',
|
|
36
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(navigateSchema)
|
|
37
|
+
},
|
|
38
|
+
handle: async (context, params) => {
|
|
39
|
+
const validatedParams = navigateSchema.parse(params);
|
|
40
|
+
const page = await context.ensurePage();
|
|
41
|
+
await page.goto(validatedParams.url, {
|
|
42
|
+
waitUntil: 'domcontentloaded'
|
|
43
|
+
});
|
|
44
|
+
// Cap load event to 5 seconds, the page is operational at this point.
|
|
45
|
+
await page.waitForLoadState('load', {
|
|
46
|
+
timeout: 5000
|
|
47
|
+
}).catch(() => {});
|
|
48
|
+
if (snapshot) return (0, _utils.captureAriaSnapshot)(page);
|
|
49
|
+
return {
|
|
50
|
+
content: [{
|
|
51
|
+
type: 'text',
|
|
52
|
+
text: `Navigated to ${validatedParams.url}`
|
|
53
|
+
}]
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
exports.navigate = navigate;
|
|
58
|
+
const goBackSchema = _zod.z.object({});
|
|
59
|
+
const goBack = snapshot => ({
|
|
60
|
+
schema: {
|
|
61
|
+
name: 'browser_go_back',
|
|
62
|
+
description: 'Go back to the previous page',
|
|
63
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(goBackSchema)
|
|
64
|
+
},
|
|
65
|
+
handle: async context => {
|
|
66
|
+
return await (0, _utils.runAndWait)(context, 'Navigated back', async () => {
|
|
67
|
+
const page = await context.ensurePage();
|
|
68
|
+
await page.goBack();
|
|
69
|
+
}, snapshot);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
exports.goBack = goBack;
|
|
73
|
+
const goForwardSchema = _zod.z.object({});
|
|
74
|
+
const goForward = snapshot => ({
|
|
75
|
+
schema: {
|
|
76
|
+
name: 'browser_go_forward',
|
|
77
|
+
description: 'Go forward to the next page',
|
|
78
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(goForwardSchema)
|
|
79
|
+
},
|
|
80
|
+
handle: async context => {
|
|
81
|
+
return await (0, _utils.runAndWait)(context, 'Navigated forward', async () => {
|
|
82
|
+
const page = await context.ensurePage();
|
|
83
|
+
await page.goForward();
|
|
84
|
+
}, snapshot);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
exports.goForward = goForward;
|
|
88
|
+
const waitSchema = _zod.z.object({
|
|
89
|
+
time: _zod.z.number().describe('The time to wait in seconds')
|
|
90
|
+
});
|
|
91
|
+
const wait = exports.wait = {
|
|
92
|
+
schema: {
|
|
93
|
+
name: 'browser_wait',
|
|
94
|
+
description: 'Wait for a specified time in seconds',
|
|
95
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(waitSchema)
|
|
96
|
+
},
|
|
97
|
+
handle: async (context, params) => {
|
|
98
|
+
const validatedParams = waitSchema.parse(params);
|
|
99
|
+
const page = await context.ensurePage();
|
|
100
|
+
await page.waitForTimeout(Math.min(10000, validatedParams.time * 1000));
|
|
101
|
+
return {
|
|
102
|
+
content: [{
|
|
103
|
+
type: 'text',
|
|
104
|
+
text: `Waited for ${validatedParams.time} seconds`
|
|
105
|
+
}]
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const pressKeySchema = _zod.z.object({
|
|
110
|
+
key: _zod.z.string().describe('Name of the key to press or a character to generate, such as `ArrowLeft` or `a`')
|
|
111
|
+
});
|
|
112
|
+
const pressKey = exports.pressKey = {
|
|
113
|
+
schema: {
|
|
114
|
+
name: 'browser_press_key',
|
|
115
|
+
description: 'Press a key on the keyboard',
|
|
116
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(pressKeySchema)
|
|
117
|
+
},
|
|
118
|
+
handle: async (context, params) => {
|
|
119
|
+
const validatedParams = pressKeySchema.parse(params);
|
|
120
|
+
return await (0, _utils.runAndWait)(context, `Pressed key ${validatedParams.key}`, async page => {
|
|
121
|
+
await page.keyboard.press(validatedParams.key);
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
const pdfSchema = _zod.z.object({});
|
|
126
|
+
const pdf = exports.pdf = {
|
|
127
|
+
schema: {
|
|
128
|
+
name: 'browser_save_as_pdf',
|
|
129
|
+
description: 'Save page as PDF',
|
|
130
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(pdfSchema)
|
|
131
|
+
},
|
|
132
|
+
handle: async context => {
|
|
133
|
+
const page = await context.ensurePage();
|
|
134
|
+
const fileName = _path.default.join(_os.default.tmpdir(), `/page-${new Date().toISOString()}.pdf`);
|
|
135
|
+
await page.pdf({
|
|
136
|
+
path: fileName
|
|
137
|
+
});
|
|
138
|
+
return {
|
|
139
|
+
content: [{
|
|
140
|
+
type: 'text',
|
|
141
|
+
text: `Saved as ${fileName}`
|
|
142
|
+
}]
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const closeSchema = _zod.z.object({});
|
|
147
|
+
const close = exports.close = {
|
|
148
|
+
schema: {
|
|
149
|
+
name: 'browser_close',
|
|
150
|
+
description: 'Close the page',
|
|
151
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(closeSchema)
|
|
152
|
+
},
|
|
153
|
+
handle: async context => {
|
|
154
|
+
await context.close();
|
|
155
|
+
return {
|
|
156
|
+
content: [{
|
|
157
|
+
type: 'text',
|
|
158
|
+
text: `Page closed`
|
|
159
|
+
}]
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.type = exports.screenshot = exports.moveMouse = exports.drag = exports.click = void 0;
|
|
7
|
+
var _zod = require("zod");
|
|
8
|
+
var _zodToJsonSchema = require("zod-to-json-schema");
|
|
9
|
+
var _utils = require("./utils");
|
|
10
|
+
/**
|
|
11
|
+
* Copyright (c) Microsoft Corporation.
|
|
12
|
+
*
|
|
13
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
14
|
+
* you may not use this file except in compliance with the License.
|
|
15
|
+
* You may obtain a copy of the License at
|
|
16
|
+
*
|
|
17
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
18
|
+
*
|
|
19
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
* See the License for the specific language governing permissions and
|
|
23
|
+
* limitations under the License.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const screenshot = exports.screenshot = {
|
|
27
|
+
schema: {
|
|
28
|
+
name: 'browser_screenshot',
|
|
29
|
+
description: 'Take a screenshot of the current page',
|
|
30
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(_zod.z.object({}))
|
|
31
|
+
},
|
|
32
|
+
handle: async context => {
|
|
33
|
+
const page = await context.ensurePage();
|
|
34
|
+
const screenshot = await page.screenshot({
|
|
35
|
+
type: 'jpeg',
|
|
36
|
+
quality: 50,
|
|
37
|
+
scale: 'css'
|
|
38
|
+
});
|
|
39
|
+
return {
|
|
40
|
+
content: [{
|
|
41
|
+
type: 'image',
|
|
42
|
+
data: screenshot.toString('base64'),
|
|
43
|
+
mimeType: 'image/jpeg'
|
|
44
|
+
}]
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const elementSchema = _zod.z.object({
|
|
49
|
+
element: _zod.z.string().describe('Human-readable element description used to obtain permission to interact with the element')
|
|
50
|
+
});
|
|
51
|
+
const moveMouseSchema = elementSchema.extend({
|
|
52
|
+
x: _zod.z.number().describe('X coordinate'),
|
|
53
|
+
y: _zod.z.number().describe('Y coordinate')
|
|
54
|
+
});
|
|
55
|
+
const moveMouse = exports.moveMouse = {
|
|
56
|
+
schema: {
|
|
57
|
+
name: 'browser_move_mouse',
|
|
58
|
+
description: 'Move mouse to a given position',
|
|
59
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(moveMouseSchema)
|
|
60
|
+
},
|
|
61
|
+
handle: async (context, params) => {
|
|
62
|
+
const validatedParams = moveMouseSchema.parse(params);
|
|
63
|
+
const page = await context.ensurePage();
|
|
64
|
+
await page.mouse.move(validatedParams.x, validatedParams.y);
|
|
65
|
+
return {
|
|
66
|
+
content: [{
|
|
67
|
+
type: 'text',
|
|
68
|
+
text: `Moved mouse to (${validatedParams.x}, ${validatedParams.y})`
|
|
69
|
+
}]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const clickSchema = elementSchema.extend({
|
|
74
|
+
x: _zod.z.number().describe('X coordinate'),
|
|
75
|
+
y: _zod.z.number().describe('Y coordinate')
|
|
76
|
+
});
|
|
77
|
+
const click = exports.click = {
|
|
78
|
+
schema: {
|
|
79
|
+
name: 'browser_click',
|
|
80
|
+
description: 'Click left mouse button',
|
|
81
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(clickSchema)
|
|
82
|
+
},
|
|
83
|
+
handle: async (context, params) => {
|
|
84
|
+
return await (0, _utils.runAndWait)(context, 'Clicked mouse', async page => {
|
|
85
|
+
const validatedParams = clickSchema.parse(params);
|
|
86
|
+
await page.mouse.move(validatedParams.x, validatedParams.y);
|
|
87
|
+
await page.mouse.down();
|
|
88
|
+
await page.mouse.up();
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const dragSchema = elementSchema.extend({
|
|
93
|
+
startX: _zod.z.number().describe('Start X coordinate'),
|
|
94
|
+
startY: _zod.z.number().describe('Start Y coordinate'),
|
|
95
|
+
endX: _zod.z.number().describe('End X coordinate'),
|
|
96
|
+
endY: _zod.z.number().describe('End Y coordinate')
|
|
97
|
+
});
|
|
98
|
+
const drag = exports.drag = {
|
|
99
|
+
schema: {
|
|
100
|
+
name: 'browser_drag',
|
|
101
|
+
description: 'Drag left mouse button',
|
|
102
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(dragSchema)
|
|
103
|
+
},
|
|
104
|
+
handle: async (context, params) => {
|
|
105
|
+
const validatedParams = dragSchema.parse(params);
|
|
106
|
+
return await (0, _utils.runAndWait)(context, `Dragged mouse from (${validatedParams.startX}, ${validatedParams.startY}) to (${validatedParams.endX}, ${validatedParams.endY})`, async page => {
|
|
107
|
+
await page.mouse.move(validatedParams.startX, validatedParams.startY);
|
|
108
|
+
await page.mouse.down();
|
|
109
|
+
await page.mouse.move(validatedParams.endX, validatedParams.endY);
|
|
110
|
+
await page.mouse.up();
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const typeSchema = _zod.z.object({
|
|
115
|
+
text: _zod.z.string().describe('Text to type into the element'),
|
|
116
|
+
submit: _zod.z.boolean().describe('Whether to submit entered text (press Enter after)')
|
|
117
|
+
});
|
|
118
|
+
const type = exports.type = {
|
|
119
|
+
schema: {
|
|
120
|
+
name: 'browser_type',
|
|
121
|
+
description: 'Type text',
|
|
122
|
+
inputSchema: (0, _zodToJsonSchema.zodToJsonSchema)(typeSchema)
|
|
123
|
+
},
|
|
124
|
+
handle: async (context, params) => {
|
|
125
|
+
const validatedParams = typeSchema.parse(params);
|
|
126
|
+
return await (0, _utils.runAndWait)(context, `Typed text "${validatedParams.text}"`, async page => {
|
|
127
|
+
await page.keyboard.type(validatedParams.text);
|
|
128
|
+
if (validatedParams.submit) await page.keyboard.press('Enter');
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.type = exports.snapshot = exports.hover = exports.drag = exports.click = void 0;
|
|
7
|
+
var _zod = require("zod");
|
|
8
|
+
var _zodToJsonSchema = _interopRequireDefault(require("zod-to-json-schema"));
|
|
9
|
+
var _utils = require("./utils");
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
/**
|
|
12
|
+
* Copyright (c) Microsoft Corporation.
|
|
13
|
+
*
|
|
14
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
15
|
+
* you may not use this file except in compliance with the License.
|
|
16
|
+
* You may obtain a copy of the License at
|
|
17
|
+
*
|
|
18
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
19
|
+
*
|
|
20
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
21
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
22
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
23
|
+
* See the License for the specific language governing permissions and
|
|
24
|
+
* limitations under the License.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const snapshot = exports.snapshot = {
|
|
28
|
+
schema: {
|
|
29
|
+
name: 'browser_snapshot',
|
|
30
|
+
description: 'Capture accessibility snapshot of the current page, this is better than screenshot',
|
|
31
|
+
inputSchema: (0, _zodToJsonSchema.default)(_zod.z.object({}))
|
|
32
|
+
},
|
|
33
|
+
handle: async context => {
|
|
34
|
+
return await (0, _utils.captureAriaSnapshot)(await context.ensurePage());
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const elementSchema = _zod.z.object({
|
|
38
|
+
element: _zod.z.string().describe('Human-readable element description used to obtain permission to interact with the element'),
|
|
39
|
+
ref: _zod.z.string().describe('Exact target element reference from the page snapshot')
|
|
40
|
+
});
|
|
41
|
+
const click = exports.click = {
|
|
42
|
+
schema: {
|
|
43
|
+
name: 'browser_click',
|
|
44
|
+
description: 'Perform click on a web page',
|
|
45
|
+
inputSchema: (0, _zodToJsonSchema.default)(elementSchema)
|
|
46
|
+
},
|
|
47
|
+
handle: async (context, params) => {
|
|
48
|
+
const validatedParams = elementSchema.parse(params);
|
|
49
|
+
return (0, _utils.runAndWait)(context, `"${validatedParams.element}" clicked`, page => refLocator(page, validatedParams.ref).click(), true);
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
const dragSchema = _zod.z.object({
|
|
53
|
+
startElement: _zod.z.string().describe('Human-readable source element description used to obtain the permission to interact with the element'),
|
|
54
|
+
startRef: _zod.z.string().describe('Exact source element reference from the page snapshot'),
|
|
55
|
+
endElement: _zod.z.string().describe('Human-readable target element description used to obtain the permission to interact with the element'),
|
|
56
|
+
endRef: _zod.z.string().describe('Exact target element reference from the page snapshot')
|
|
57
|
+
});
|
|
58
|
+
const drag = exports.drag = {
|
|
59
|
+
schema: {
|
|
60
|
+
name: 'browser_drag',
|
|
61
|
+
description: 'Perform drag and drop between two elements',
|
|
62
|
+
inputSchema: (0, _zodToJsonSchema.default)(dragSchema)
|
|
63
|
+
},
|
|
64
|
+
handle: async (context, params) => {
|
|
65
|
+
const validatedParams = dragSchema.parse(params);
|
|
66
|
+
return (0, _utils.runAndWait)(context, `Dragged "${validatedParams.startElement}" to "${validatedParams.endElement}"`, async page => {
|
|
67
|
+
const startLocator = refLocator(page, validatedParams.startRef);
|
|
68
|
+
const endLocator = refLocator(page, validatedParams.endRef);
|
|
69
|
+
await startLocator.dragTo(endLocator);
|
|
70
|
+
}, true);
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
const hover = exports.hover = {
|
|
74
|
+
schema: {
|
|
75
|
+
name: 'browser_hover',
|
|
76
|
+
description: 'Hover over element on page',
|
|
77
|
+
inputSchema: (0, _zodToJsonSchema.default)(elementSchema)
|
|
78
|
+
},
|
|
79
|
+
handle: async (context, params) => {
|
|
80
|
+
const validatedParams = elementSchema.parse(params);
|
|
81
|
+
return (0, _utils.runAndWait)(context, `Hovered over "${validatedParams.element}"`, page => refLocator(page, validatedParams.ref).hover(), true);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
const typeSchema = elementSchema.extend({
|
|
85
|
+
text: _zod.z.string().describe('Text to type into the element'),
|
|
86
|
+
submit: _zod.z.boolean().describe('Whether to submit entered text (press Enter after)')
|
|
87
|
+
});
|
|
88
|
+
const type = exports.type = {
|
|
89
|
+
schema: {
|
|
90
|
+
name: 'browser_type',
|
|
91
|
+
description: 'Type text into editable element',
|
|
92
|
+
inputSchema: (0, _zodToJsonSchema.default)(typeSchema)
|
|
93
|
+
},
|
|
94
|
+
handle: async (context, params) => {
|
|
95
|
+
const validatedParams = typeSchema.parse(params);
|
|
96
|
+
return await (0, _utils.runAndWait)(context, `Typed "${validatedParams.text}" into "${validatedParams.element}"`, async page => {
|
|
97
|
+
const locator = refLocator(page, validatedParams.ref);
|
|
98
|
+
await locator.fill(validatedParams.text);
|
|
99
|
+
if (validatedParams.submit) await locator.press('Enter');
|
|
100
|
+
}, true);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
function refLocator(page, ref) {
|
|
104
|
+
return page.locator(`aria-ref=${ref}`);
|
|
105
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.captureAriaSnapshot = captureAriaSnapshot;
|
|
7
|
+
exports.runAndWait = runAndWait;
|
|
8
|
+
/**
|
|
9
|
+
* Copyright (c) Microsoft Corporation.
|
|
10
|
+
*
|
|
11
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
12
|
+
* you may not use this file except in compliance with the License.
|
|
13
|
+
* You may obtain a copy of the License at
|
|
14
|
+
*
|
|
15
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
16
|
+
*
|
|
17
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
18
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
19
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
20
|
+
* See the License for the specific language governing permissions and
|
|
21
|
+
* limitations under the License.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
async function waitForCompletion(page, callback) {
|
|
25
|
+
const requests = new Set();
|
|
26
|
+
let frameNavigated = false;
|
|
27
|
+
let waitCallback = () => {};
|
|
28
|
+
const waitBarrier = new Promise(f => {
|
|
29
|
+
waitCallback = f;
|
|
30
|
+
});
|
|
31
|
+
const requestListener = request => requests.add(request);
|
|
32
|
+
const requestFinishedListener = request => {
|
|
33
|
+
requests.delete(request);
|
|
34
|
+
if (!requests.size) waitCallback();
|
|
35
|
+
};
|
|
36
|
+
const frameNavigateListener = frame => {
|
|
37
|
+
if (frame.parentFrame()) return;
|
|
38
|
+
frameNavigated = true;
|
|
39
|
+
dispose();
|
|
40
|
+
clearTimeout(timeout);
|
|
41
|
+
void frame.waitForLoadState('load').then(() => {
|
|
42
|
+
waitCallback();
|
|
43
|
+
});
|
|
44
|
+
};
|
|
45
|
+
const onTimeout = () => {
|
|
46
|
+
dispose();
|
|
47
|
+
waitCallback();
|
|
48
|
+
};
|
|
49
|
+
page.on('request', requestListener);
|
|
50
|
+
page.on('requestfinished', requestFinishedListener);
|
|
51
|
+
page.on('framenavigated', frameNavigateListener);
|
|
52
|
+
const timeout = setTimeout(onTimeout, 10000);
|
|
53
|
+
const dispose = () => {
|
|
54
|
+
page.off('request', requestListener);
|
|
55
|
+
page.off('requestfinished', requestFinishedListener);
|
|
56
|
+
page.off('framenavigated', frameNavigateListener);
|
|
57
|
+
clearTimeout(timeout);
|
|
58
|
+
};
|
|
59
|
+
try {
|
|
60
|
+
const result = await callback();
|
|
61
|
+
if (!requests.size && !frameNavigated) waitCallback();
|
|
62
|
+
await waitBarrier;
|
|
63
|
+
await page.evaluate(() => new Promise(f => setTimeout(f, 1000)));
|
|
64
|
+
return result;
|
|
65
|
+
} finally {
|
|
66
|
+
dispose();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async function runAndWait(context, status, callback, snapshot = false) {
|
|
70
|
+
const page = await context.ensurePage();
|
|
71
|
+
await waitForCompletion(page, () => callback(page));
|
|
72
|
+
return snapshot ? captureAriaSnapshot(page, status) : {
|
|
73
|
+
content: [{
|
|
74
|
+
type: 'text',
|
|
75
|
+
text: status
|
|
76
|
+
}]
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
async function captureAriaSnapshot(page, status = '') {
|
|
80
|
+
const snapshot = await page.locator('html').ariaSnapshot({
|
|
81
|
+
ref: true
|
|
82
|
+
});
|
|
83
|
+
return {
|
|
84
|
+
content: [{
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: `${status ? `${status}\n` : ''}
|
|
87
|
+
- Page URL: ${page.url()}
|
|
88
|
+
- Page Title: ${await page.title()}
|
|
89
|
+
- Page Snapshot
|
|
90
|
+
\`\`\`yaml
|
|
91
|
+
${snapshot}
|
|
92
|
+
\`\`\`
|
|
93
|
+
`
|
|
94
|
+
}]
|
|
95
|
+
};
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@playwright/mcp",
|
|
3
|
-
"version": "1.52.0-alpha-
|
|
3
|
+
"version": "1.52.0-alpha-2025-03-20",
|
|
4
4
|
"description": "Playwright Tools for MCP",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"./package.json": "./package.json"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
27
28
|
"commander": "^13.1.0",
|
|
28
|
-
"playwright": "1.52.0-alpha-
|
|
29
|
+
"playwright": "1.52.0-alpha-2025-03-20",
|
|
29
30
|
"zod-to-json-schema": "^3.24.4"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@modelcontextprotocol/sdk": "^1.6.1",
|
|
33
33
|
"@types/node": "^22.13.10"
|
|
34
34
|
},
|
|
35
35
|
"bin": {
|