custom-ui-automator 1.0.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.
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # custom-ui-automator
2
+
3
+ A Playwright-based MCP (Model Context Protocol) server for browser UI automation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install custom-ui-automator
9
+ ```
10
+
11
+ After installation, you need to install Playwright browsers:
12
+
13
+ ```bash
14
+ npx playwright install chromium
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### With Claude Desktop
20
+
21
+ Add this to your Claude Desktop configuration (`claude_desktop_config.json`):
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "custom-ui-automator": {
27
+ "command": "npx",
28
+ "args": ["custom-ui-automator"]
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ ### With Claude Code
35
+
36
+ Add this to your `.mcp.json`:
37
+
38
+ ```json
39
+ {
40
+ "mcpServers": {
41
+ "custom-ui-automator": {
42
+ "command": "npx",
43
+ "args": ["custom-ui-automator"]
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Available Tools
50
+
51
+ | Tool | Description |
52
+ |------|-------------|
53
+ | `navigate_to` | Navigate the browser to a specified URL |
54
+ | `go_back` | Navigate back to the previous page |
55
+ | `click` | Click an element using CSS selector |
56
+ | `double_click` | Double click an element |
57
+ | `right_click` | Right click (context click) an element |
58
+ | `type_text` | Type text into an input field |
59
+ | `drag_and_drop` | Drag and drop elements |
60
+ | `wait_for_element` | Wait for an element to reach a specific state |
61
+ | `select_option` | Select option(s) from a dropdown |
62
+ | `execute_javascript` | Execute JavaScript in the browser context |
63
+ | `browser_handle_dialog` | Handle modal dialogs (alert, confirm, prompt) |
64
+ | `browser_upload_file` | Upload files via file chooser |
65
+ | `resize_window` | Resize the browser window |
66
+ | `press_key` | Press keyboard keys or combinations |
67
+ | `hover` | Hover over an element |
68
+ | `close_browser` | Close the browser instance |
69
+
70
+ ## CSS Selector Priority
71
+
72
+ When selecting elements, follow this priority order:
73
+
74
+ 1. `data-dgat` attribute: `[data-dgat="value"]`
75
+ 2. `data-testid` attribute: `[data-testid="value"]`
76
+ 3. `id` attribute: `#id`
77
+ 4. `class` or complex CSS selectors (last resort)
78
+
79
+ ## Example Usage
80
+
81
+ ```
82
+ Navigate to https://example.com
83
+ Click the login button using [data-testid="login-btn"]
84
+ Type "user@example.com" into the email field
85
+ ```
86
+
87
+ ## License
88
+
89
+ MIT
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":""}
package/dist/server.js ADDED
@@ -0,0 +1,794 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { chromium } from "playwright";
5
+ import z from "zod";
6
+ const server = new McpServer({
7
+ name: "custom-ui-automator",
8
+ version: "1.0.0",
9
+ });
10
+ // Output schemas
11
+ const NavigationResultSchema = z.object({
12
+ url: z.string(),
13
+ title: z.string(),
14
+ });
15
+ const ClickResultSchema = z.object({
16
+ description: z.string(),
17
+ locator: z.string(),
18
+ });
19
+ const TypeResultSchema = z.object({
20
+ description: z.string(),
21
+ locator: z.string(),
22
+ text: z.string(),
23
+ });
24
+ const ExecuteJavaScriptResultSchema = z.object({
25
+ result: z.any(),
26
+ });
27
+ // Browser management
28
+ let browser = null;
29
+ let page = null;
30
+ async function getBrowser() {
31
+ if (!browser) {
32
+ browser = await chromium.launch({ headless: false });
33
+ }
34
+ return browser;
35
+ }
36
+ async function getPage() {
37
+ if (!page) {
38
+ const browserInstance = await getBrowser();
39
+ page = await browserInstance.newPage();
40
+ }
41
+ return page;
42
+ }
43
+ // Navigate to URL tool
44
+ server.registerTool("navigate_to", {
45
+ title: "Navigate to URL",
46
+ description: "Navigate the browser to a specified URL",
47
+ inputSchema: {
48
+ url: z.string().url().describe("The URL to navigate to"),
49
+ },
50
+ outputSchema: NavigationResultSchema.shape,
51
+ }, async ({ url }) => {
52
+ try {
53
+ const currentPage = await getPage();
54
+ await currentPage.goto(url, { waitUntil: "domcontentloaded", timeout: 30000 });
55
+ const currentUrl = currentPage.url();
56
+ const title = await currentPage.title();
57
+ return {
58
+ content: [
59
+ {
60
+ type: "text",
61
+ text: `Successfully navigated to: ${currentUrl}\nPage title: ${title}`,
62
+ },
63
+ ],
64
+ structuredContent: { url: currentUrl, title },
65
+ };
66
+ }
67
+ catch (error) {
68
+ return {
69
+ content: [
70
+ {
71
+ type: "text",
72
+ text: `Error navigating to URL: ${error instanceof Error ? error.message : String(error)}`,
73
+ },
74
+ ],
75
+ isError: true,
76
+ };
77
+ }
78
+ });
79
+ // Go back tool
80
+ server.registerTool("go_back", {
81
+ title: "Go Back",
82
+ description: "Navigate back to the previous page in browser history",
83
+ inputSchema: {},
84
+ outputSchema: NavigationResultSchema.shape,
85
+ }, async () => {
86
+ try {
87
+ const currentPage = await getPage();
88
+ await currentPage.goBack({ waitUntil: "domcontentloaded", timeout: 30000 });
89
+ const currentUrl = currentPage.url();
90
+ const title = await currentPage.title();
91
+ return {
92
+ content: [
93
+ {
94
+ type: "text",
95
+ text: `Successfully navigated back to: ${currentUrl}\nPage title: ${title}`,
96
+ },
97
+ ],
98
+ structuredContent: { url: currentUrl, title },
99
+ };
100
+ }
101
+ catch (error) {
102
+ return {
103
+ content: [
104
+ {
105
+ type: "text",
106
+ text: `Error going back: ${error instanceof Error ? error.message : String(error)}`,
107
+ },
108
+ ],
109
+ isError: true,
110
+ };
111
+ }
112
+ });
113
+ // Click element tool
114
+ server.registerTool("click", {
115
+ title: "Click Element",
116
+ description: "Click an element on the page using a CSS selector. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
117
+ inputSchema: {
118
+ selector: z.string().describe("CSS selector for the element to click. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
119
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
120
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
121
+ },
122
+ outputSchema: ClickResultSchema.shape,
123
+ }, async ({ selector, frameSelector, timeout }) => {
124
+ try {
125
+ const currentPage = await getPage();
126
+ const locator = frameSelector
127
+ ? currentPage.frameLocator(frameSelector).locator(selector)
128
+ : currentPage.locator(selector);
129
+ await locator.click({ timeout: timeout ?? 5000 });
130
+ return {
131
+ content: [
132
+ {
133
+ type: "text",
134
+ text: `Successfully clicked element using selector: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
135
+ },
136
+ ],
137
+ structuredContent: { description: selector, locator: selector },
138
+ };
139
+ }
140
+ catch (error) {
141
+ return {
142
+ content: [
143
+ {
144
+ type: "text",
145
+ text: `Error clicking element: ${error instanceof Error ? error.message : String(error)}`,
146
+ },
147
+ ],
148
+ isError: true,
149
+ };
150
+ }
151
+ });
152
+ // Double click element tool
153
+ server.registerTool("double_click", {
154
+ title: "Double Click Element",
155
+ description: "Double click an element on the page using a CSS selector. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
156
+ inputSchema: {
157
+ selector: z.string().describe("CSS selector for the element to double click. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
158
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
159
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
160
+ },
161
+ outputSchema: ClickResultSchema.shape,
162
+ }, async ({ selector, frameSelector, timeout }) => {
163
+ try {
164
+ const currentPage = await getPage();
165
+ const locator = frameSelector
166
+ ? currentPage.frameLocator(frameSelector).locator(selector)
167
+ : currentPage.locator(selector);
168
+ await locator.dblclick({ timeout: timeout ?? 5000 });
169
+ return {
170
+ content: [
171
+ {
172
+ type: "text",
173
+ text: `Successfully double clicked element using selector: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
174
+ },
175
+ ],
176
+ structuredContent: { description: selector, locator: selector },
177
+ };
178
+ }
179
+ catch (error) {
180
+ return {
181
+ content: [
182
+ {
183
+ type: "text",
184
+ text: `Error double clicking element: ${error instanceof Error ? error.message : String(error)}`,
185
+ },
186
+ ],
187
+ isError: true,
188
+ };
189
+ }
190
+ });
191
+ // Right click element tool
192
+ server.registerTool("right_click", {
193
+ title: "Right Click Element",
194
+ description: "Right click (context click) an element on the page using a CSS selector. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
195
+ inputSchema: {
196
+ selector: z.string().describe("CSS selector for the element to right click. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
197
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
198
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
199
+ },
200
+ outputSchema: ClickResultSchema.shape,
201
+ }, async ({ selector, frameSelector, timeout }) => {
202
+ try {
203
+ const currentPage = await getPage();
204
+ const locator = frameSelector
205
+ ? currentPage.frameLocator(frameSelector).locator(selector)
206
+ : currentPage.locator(selector);
207
+ await locator.click({ button: 'right', timeout: timeout ?? 5000 });
208
+ return {
209
+ content: [
210
+ {
211
+ type: "text",
212
+ text: `Successfully right clicked element using selector: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
213
+ },
214
+ ],
215
+ structuredContent: { description: selector, locator: selector },
216
+ };
217
+ }
218
+ catch (error) {
219
+ return {
220
+ content: [
221
+ {
222
+ type: "text",
223
+ text: `Error right clicking element: ${error instanceof Error ? error.message : String(error)}`,
224
+ },
225
+ ],
226
+ isError: true,
227
+ };
228
+ }
229
+ });
230
+ // Type text tool
231
+ server.registerTool("type_text", {
232
+ title: "Type Text",
233
+ description: "Type text into an input field using a CSS selector. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
234
+ inputSchema: {
235
+ selector: z.string().describe("CSS selector for the input field. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
236
+ text: z.string().describe("Text to type into the field"),
237
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
238
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
239
+ clearFirst: z.boolean().optional().describe("Clear the field before typing (default: true)"),
240
+ },
241
+ outputSchema: TypeResultSchema.shape,
242
+ }, async ({ selector, text, frameSelector, timeout, clearFirst }) => {
243
+ try {
244
+ const currentPage = await getPage();
245
+ const locator = frameSelector
246
+ ? currentPage.frameLocator(frameSelector).locator(selector)
247
+ : currentPage.locator(selector);
248
+ // Use fill to type text (replaces deprecated type method)
249
+ if (clearFirst !== false) {
250
+ // Clear first then type
251
+ await locator.fill(text, { timeout: timeout ?? 5000 });
252
+ }
253
+ else {
254
+ // Append text without clearing
255
+ await locator.pressSequentially(text, { timeout: timeout ?? 5000 });
256
+ }
257
+ return {
258
+ content: [
259
+ {
260
+ type: "text",
261
+ text: `Successfully typed "${text}" into field using selector: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
262
+ },
263
+ ],
264
+ structuredContent: { description: selector, locator: selector, text },
265
+ };
266
+ }
267
+ catch (error) {
268
+ return {
269
+ content: [
270
+ {
271
+ type: "text",
272
+ text: `Error typing text: ${error instanceof Error ? error.message : String(error)}`,
273
+ },
274
+ ],
275
+ isError: true,
276
+ };
277
+ }
278
+ });
279
+ // Drag and drop tool
280
+ server.registerTool("drag_and_drop", {
281
+ title: "Drag and Drop",
282
+ description: "Drag an element and drop it onto another element. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
283
+ inputSchema: {
284
+ sourceSelector: z.string().describe("CSS selector for the element to drag. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
285
+ targetSelector: z.string().describe("CSS selector for the element to drop onto. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
286
+ sourceFrameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the source element"),
287
+ targetFrameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the target element (defaults to sourceFrameSelector if not provided)"),
288
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
289
+ },
290
+ outputSchema: z.object({
291
+ success: z.boolean(),
292
+ sourceSelector: z.string(),
293
+ targetSelector: z.string(),
294
+ }).shape,
295
+ }, async ({ sourceSelector, targetSelector, sourceFrameSelector, targetFrameSelector, timeout }) => {
296
+ try {
297
+ const currentPage = await getPage();
298
+ const sourceLocator = sourceFrameSelector
299
+ ? currentPage.frameLocator(sourceFrameSelector).locator(sourceSelector)
300
+ : currentPage.locator(sourceSelector);
301
+ const targetFrame = targetFrameSelector ?? sourceFrameSelector;
302
+ const targetLocator = targetFrame
303
+ ? currentPage.frameLocator(targetFrame).locator(targetSelector)
304
+ : currentPage.locator(targetSelector);
305
+ await sourceLocator.dragTo(targetLocator, { timeout: timeout ?? 5000 });
306
+ return {
307
+ content: [
308
+ {
309
+ type: "text",
310
+ text: `Successfully dragged "${sourceSelector}"${sourceFrameSelector ? ` from iframe: ${sourceFrameSelector}` : ''} to "${targetSelector}"${targetFrame ? ` in iframe: ${targetFrame}` : ''}`,
311
+ },
312
+ ],
313
+ structuredContent: {
314
+ success: true,
315
+ sourceSelector,
316
+ targetSelector,
317
+ },
318
+ };
319
+ }
320
+ catch (error) {
321
+ return {
322
+ content: [
323
+ {
324
+ type: "text",
325
+ text: `Error during drag and drop: ${error instanceof Error ? error.message : String(error)}`,
326
+ },
327
+ ],
328
+ isError: true,
329
+ };
330
+ }
331
+ });
332
+ // Wait for element tool
333
+ server.registerTool("wait_for_element", {
334
+ title: "Wait For Element",
335
+ description: "Wait for an element to reach a specific state. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
336
+ inputSchema: {
337
+ selector: z.string().describe("CSS selector for the element to wait for. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
338
+ state: z.enum(['visible', 'hidden', 'attached', 'detached']).optional().describe("The state to wait for: 'visible' (default) - element is visible, 'hidden' - element is not visible, 'attached' - element is in DOM, 'detached' - element is removed from DOM"),
339
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
340
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 30000)"),
341
+ },
342
+ outputSchema: z.object({
343
+ success: z.boolean(),
344
+ selector: z.string(),
345
+ state: z.string(),
346
+ }).shape,
347
+ }, async ({ selector, state, frameSelector, timeout }) => {
348
+ try {
349
+ const currentPage = await getPage();
350
+ const locator = frameSelector
351
+ ? currentPage.frameLocator(frameSelector).locator(selector)
352
+ : currentPage.locator(selector);
353
+ const waitState = state ?? 'visible';
354
+ await locator.waitFor({ state: waitState, timeout: timeout ?? 30000 });
355
+ return {
356
+ content: [
357
+ {
358
+ type: "text",
359
+ text: `Element "${selector}" is now ${waitState}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
360
+ },
361
+ ],
362
+ structuredContent: {
363
+ success: true,
364
+ selector,
365
+ state: waitState,
366
+ },
367
+ };
368
+ }
369
+ catch (error) {
370
+ return {
371
+ content: [
372
+ {
373
+ type: "text",
374
+ text: `Error waiting for element: ${error instanceof Error ? error.message : String(error)}`,
375
+ },
376
+ ],
377
+ isError: true,
378
+ };
379
+ }
380
+ });
381
+ // Select dropdown option tool
382
+ server.registerTool("select_option", {
383
+ title: "Select Option",
384
+ description: "Select option(s) from a dropdown/select element. Supports both single and multi-select dropdowns. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
385
+ inputSchema: {
386
+ selector: z.string().describe("CSS selector for the select element. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
387
+ values: z.array(z.string()).optional().describe("Array of option values to select (uses the 'value' attribute of <option>)"),
388
+ labels: z.array(z.string()).optional().describe("Array of option labels to select (uses the visible text of <option>)"),
389
+ indices: z.array(z.number()).optional().describe("Array of option indices to select (0-based)"),
390
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
391
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
392
+ },
393
+ outputSchema: z.object({
394
+ success: z.boolean(),
395
+ selectedOptions: z.array(z.string()),
396
+ }).shape,
397
+ }, async ({ selector, values, labels, indices, frameSelector, timeout }) => {
398
+ try {
399
+ const currentPage = await getPage();
400
+ const locator = frameSelector
401
+ ? currentPage.frameLocator(frameSelector).locator(selector)
402
+ : currentPage.locator(selector);
403
+ // Build the selection criteria
404
+ let selectOptions = [];
405
+ if (values && values.length > 0) {
406
+ selectOptions = values.map(value => ({ value }));
407
+ }
408
+ else if (labels && labels.length > 0) {
409
+ selectOptions = labels.map(label => ({ label }));
410
+ }
411
+ else if (indices && indices.length > 0) {
412
+ selectOptions = indices.map(index => ({ index }));
413
+ }
414
+ else {
415
+ throw new Error("Must provide at least one of: values, labels, or indices");
416
+ }
417
+ const selectedValues = await locator.selectOption(selectOptions, { timeout: timeout ?? 5000 });
418
+ return {
419
+ content: [
420
+ {
421
+ type: "text",
422
+ text: `Successfully selected option(s): ${selectedValues.join(', ')} from dropdown: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
423
+ },
424
+ ],
425
+ structuredContent: {
426
+ success: true,
427
+ selectedOptions: selectedValues,
428
+ },
429
+ };
430
+ }
431
+ catch (error) {
432
+ return {
433
+ content: [
434
+ {
435
+ type: "text",
436
+ text: `Error selecting option: ${error instanceof Error ? error.message : String(error)}`,
437
+ },
438
+ ],
439
+ isError: true,
440
+ };
441
+ }
442
+ });
443
+ // Execute JavaScript tool
444
+ server.registerTool("execute_javascript", {
445
+ title: "Execute JavaScript",
446
+ description: "Execute arbitrary JavaScript code in the browser context and return the result. This tool should primarily be used for fetching CSS from DOM, accessing DOM elements, or reading page state. For performing clicks, use the 'click', 'double_click', or 'right_click' tools. For filling text, use the 'type_text' tool. For other interactions, use the corresponding dedicated tools.",
447
+ inputSchema: {
448
+ code: z.string().describe("JavaScript code to execute in the browser context"),
449
+ },
450
+ outputSchema: ExecuteJavaScriptResultSchema.shape,
451
+ }, async ({ code }) => {
452
+ try {
453
+ const currentPage = await getPage();
454
+ const result = await currentPage.evaluate((codeToRun) => {
455
+ return eval(codeToRun);
456
+ }, code);
457
+ return {
458
+ content: [
459
+ {
460
+ type: "text",
461
+ text: `JavaScript executed successfully.\nResult: ${JSON.stringify(result, null, 2)}`,
462
+ },
463
+ ],
464
+ structuredContent: { result },
465
+ };
466
+ }
467
+ catch (error) {
468
+ return {
469
+ content: [
470
+ {
471
+ type: "text",
472
+ text: `Error executing JavaScript: ${error instanceof Error ? error.message : String(error)}`,
473
+ },
474
+ ],
475
+ isError: true,
476
+ };
477
+ }
478
+ });
479
+ // Handle dialog tool - for handling modal dialogs
480
+ server.registerTool("browser_handle_dialog", {
481
+ title: "Handle Dialog",
482
+ description: "Handle a modal dialog (alert, confirm, prompt) by accepting or dismissing it",
483
+ inputSchema: {
484
+ action: z.enum(['accept', 'dismiss']).describe("Whether to accept or dismiss the dialog"),
485
+ promptText: z.string().optional().describe("Text to enter in a prompt dialog (only used if dialog is a prompt)"),
486
+ },
487
+ outputSchema: z.object({
488
+ success: z.boolean(),
489
+ dialogType: z.string(),
490
+ message: z.string(),
491
+ }).shape,
492
+ }, async ({ action, promptText }) => {
493
+ try {
494
+ const currentPage = await getPage();
495
+ // Set up a one-time dialog handler
496
+ const dialogPromise = new Promise((resolve, reject) => {
497
+ const timeout = setTimeout(() => reject(new Error("No dialog appeared within timeout")), 5000);
498
+ currentPage.once('dialog', async (dialog) => {
499
+ clearTimeout(timeout);
500
+ const dialogType = dialog.type();
501
+ const dialogMessage = dialog.message();
502
+ if (action === 'accept') {
503
+ if (dialogType === 'prompt' && promptText !== undefined) {
504
+ await dialog.accept(promptText);
505
+ }
506
+ else {
507
+ await dialog.accept();
508
+ }
509
+ }
510
+ else {
511
+ await dialog.dismiss();
512
+ }
513
+ resolve({ type: dialogType, message: dialogMessage });
514
+ });
515
+ });
516
+ const result = await dialogPromise;
517
+ return {
518
+ content: [
519
+ {
520
+ type: "text",
521
+ text: `Dialog ${action}ed successfully.\nDialog type: ${result.type}\nDialog message: ${result.message}`,
522
+ },
523
+ ],
524
+ structuredContent: {
525
+ success: true,
526
+ dialogType: result.type,
527
+ message: result.message,
528
+ },
529
+ };
530
+ }
531
+ catch (error) {
532
+ return {
533
+ content: [
534
+ {
535
+ type: "text",
536
+ text: `Error handling dialog: ${error instanceof Error ? error.message : String(error)}`,
537
+ },
538
+ ],
539
+ isError: true,
540
+ };
541
+ }
542
+ });
543
+ // File upload tool - for handling file chooser dialogs
544
+ server.registerTool("browser_upload_file", {
545
+ title: "Upload File",
546
+ description: "Upload a file when a file chooser dialog is present",
547
+ inputSchema: {
548
+ filePaths: z.array(z.string()).describe("Array of file paths to upload"),
549
+ },
550
+ outputSchema: z.object({
551
+ success: z.boolean(),
552
+ uploadedFiles: z.array(z.string()),
553
+ }).shape,
554
+ }, async ({ filePaths }) => {
555
+ try {
556
+ const currentPage = await getPage();
557
+ // Wait for file chooser and set files
558
+ const [fileChooser] = await Promise.all([
559
+ currentPage.waitForEvent('filechooser', { timeout: 5000 }),
560
+ ]);
561
+ await fileChooser.setFiles(filePaths);
562
+ return {
563
+ content: [
564
+ {
565
+ type: "text",
566
+ text: `Files uploaded successfully: ${filePaths.join(', ')}`,
567
+ },
568
+ ],
569
+ structuredContent: {
570
+ success: true,
571
+ uploadedFiles: filePaths,
572
+ },
573
+ };
574
+ }
575
+ catch (error) {
576
+ return {
577
+ content: [
578
+ {
579
+ type: "text",
580
+ text: `Error uploading file: ${error instanceof Error ? error.message : String(error)}`,
581
+ },
582
+ ],
583
+ isError: true,
584
+ };
585
+ }
586
+ });
587
+ // Resize browser window tool
588
+ server.registerTool("resize_window", {
589
+ title: "Resize Window",
590
+ description: "Resize the browser window to specified dimensions",
591
+ inputSchema: {
592
+ width: z.number().describe("The width of the browser window in pixels"),
593
+ height: z.number().describe("The height of the browser window in pixels"),
594
+ },
595
+ outputSchema: z.object({
596
+ success: z.boolean(),
597
+ width: z.number(),
598
+ height: z.number(),
599
+ }).shape,
600
+ }, async ({ width, height }) => {
601
+ try {
602
+ const currentPage = await getPage();
603
+ await currentPage.setViewportSize({ width, height });
604
+ return {
605
+ content: [
606
+ {
607
+ type: "text",
608
+ text: `Browser window resized to ${width}x${height} pixels.`,
609
+ },
610
+ ],
611
+ structuredContent: {
612
+ success: true,
613
+ width,
614
+ height,
615
+ },
616
+ };
617
+ }
618
+ catch (error) {
619
+ return {
620
+ content: [
621
+ {
622
+ type: "text",
623
+ text: `Error resizing window: ${error instanceof Error ? error.message : String(error)}`,
624
+ },
625
+ ],
626
+ isError: true,
627
+ };
628
+ }
629
+ });
630
+ // Press keyboard key tool
631
+ server.registerTool("press_key", {
632
+ title: "Press Key",
633
+ description: "Press a keyboard key or key combination (e.g., 'Enter', 'Escape', 'Control+C', 'Shift+Tab')",
634
+ inputSchema: {
635
+ key: z.string().describe("The key to press (e.g., 'Enter', 'Escape', 'Tab', 'ArrowDown', 'Control+A', 'Shift+Tab')"),
636
+ selector: z.string().optional().describe("Optional CSS selector for the element to focus before pressing the key"),
637
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
638
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
639
+ },
640
+ outputSchema: z.object({
641
+ success: z.boolean(),
642
+ key: z.string(),
643
+ }).shape,
644
+ }, async ({ key, selector, frameSelector, timeout }) => {
645
+ try {
646
+ const currentPage = await getPage();
647
+ if (selector) {
648
+ const locator = frameSelector
649
+ ? currentPage.frameLocator(frameSelector).locator(selector)
650
+ : currentPage.locator(selector);
651
+ await locator.press(key, { timeout: timeout ?? 5000 });
652
+ }
653
+ else {
654
+ await currentPage.keyboard.press(key);
655
+ }
656
+ return {
657
+ content: [
658
+ {
659
+ type: "text",
660
+ text: `Successfully pressed key: ${key}${selector ? ` on element: ${selector}` : ''}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
661
+ },
662
+ ],
663
+ structuredContent: {
664
+ success: true,
665
+ key,
666
+ },
667
+ };
668
+ }
669
+ catch (error) {
670
+ return {
671
+ content: [
672
+ {
673
+ type: "text",
674
+ text: `Error pressing key: ${error instanceof Error ? error.message : String(error)}`,
675
+ },
676
+ ],
677
+ isError: true,
678
+ };
679
+ }
680
+ });
681
+ // Hover mouse tool
682
+ server.registerTool("hover", {
683
+ title: "Hover Element",
684
+ description: "Hover the mouse over an element using a CSS selector. Priority order: 1. data-dgat [data-dgat=\"value\"], 2. data-testid [data-testid=\"value\"], 3. id #id, 4. class or complex CSS (last resort)",
685
+ inputSchema: {
686
+ selector: z.string().describe("CSS selector for the element to hover. Follow priority: 1. [data-dgat=\"value\"] (FIRST), 2. [data-testid=\"value\"] (if no data-dgat), 3. #id (if no data attributes), 4. .class or complex CSS (last resort)"),
687
+ frameSelector: z.string().optional().describe("Optional CSS selector for the iframe containing the element (e.g., 'iframe#my-frame', 'iframe[name=\"content\"]')"),
688
+ timeout: z.number().optional().describe("Timeout in milliseconds (default: 5000)"),
689
+ },
690
+ outputSchema: z.object({
691
+ success: z.boolean(),
692
+ selector: z.string(),
693
+ }).shape,
694
+ }, async ({ selector, frameSelector, timeout }) => {
695
+ try {
696
+ const currentPage = await getPage();
697
+ const locator = frameSelector
698
+ ? currentPage.frameLocator(frameSelector).locator(selector)
699
+ : currentPage.locator(selector);
700
+ await locator.hover({ timeout: timeout ?? 5000 });
701
+ return {
702
+ content: [
703
+ {
704
+ type: "text",
705
+ text: `Successfully hovered over element: ${selector}${frameSelector ? ` in iframe: ${frameSelector}` : ''}`,
706
+ },
707
+ ],
708
+ structuredContent: {
709
+ success: true,
710
+ selector,
711
+ },
712
+ };
713
+ }
714
+ catch (error) {
715
+ return {
716
+ content: [
717
+ {
718
+ type: "text",
719
+ text: `Error hovering element: ${error instanceof Error ? error.message : String(error)}`,
720
+ },
721
+ ],
722
+ isError: true,
723
+ };
724
+ }
725
+ });
726
+ // Close browser tool
727
+ server.registerTool("close_browser", {
728
+ title: "Close Browser",
729
+ description: "Close the browser instance and clean up resources",
730
+ inputSchema: {},
731
+ outputSchema: z.object({
732
+ success: z.boolean(),
733
+ message: z.string(),
734
+ }).shape,
735
+ }, async () => {
736
+ try {
737
+ if (browser) {
738
+ await browser.close();
739
+ browser = null;
740
+ page = null;
741
+ return {
742
+ content: [
743
+ {
744
+ type: "text",
745
+ text: "Browser closed successfully.",
746
+ },
747
+ ],
748
+ structuredContent: {
749
+ success: true,
750
+ message: "Browser closed successfully",
751
+ },
752
+ };
753
+ }
754
+ else {
755
+ return {
756
+ content: [
757
+ {
758
+ type: "text",
759
+ text: "No browser instance was open.",
760
+ },
761
+ ],
762
+ structuredContent: {
763
+ success: true,
764
+ message: "No browser instance was open",
765
+ },
766
+ };
767
+ }
768
+ }
769
+ catch (error) {
770
+ return {
771
+ content: [
772
+ {
773
+ type: "text",
774
+ text: `Error closing browser: ${error instanceof Error ? error.message : String(error)}`,
775
+ },
776
+ ],
777
+ isError: true,
778
+ };
779
+ }
780
+ });
781
+ // Cleanup on exit
782
+ process.on("SIGINT", async () => {
783
+ if (browser) {
784
+ await browser.close();
785
+ }
786
+ process.exit(0);
787
+ });
788
+ // Start the server
789
+ (async () => {
790
+ const transport = new StdioServerTransport();
791
+ await server.connect(transport);
792
+ console.error("Playwright Browser MCP Server running on stdio");
793
+ })();
794
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "custom-ui-automator",
3
+ "version": "1.0.0",
4
+ "description": "A Playwright browser MCP server for UI automation",
5
+ "type": "module",
6
+ "main": "dist/server.js",
7
+ "bin": {
8
+ "custom-ui-automator": "dist/server.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md",
13
+ "package.json"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "prepublishOnly": "npm run build"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "model-context-protocol",
22
+ "playwright",
23
+ "browser-automation",
24
+ "ui-automation",
25
+ "testing",
26
+ "web-automation"
27
+ ],
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.20.2",
30
+ "playwright": "^1.57.0",
31
+ "zod": "^3.23.8"
32
+ },
33
+ "devDependencies": {
34
+ "@playwright/test": "^1.57.0",
35
+ "@types/node": "^24.9.1",
36
+ "tsx": "^4.19.1",
37
+ "typescript": "^5.6.3"
38
+ },
39
+ "engines": {
40
+ "node": ">=18.0.0"
41
+ },
42
+ "author": "Atul Bharadwaj",
43
+ "license": "MIT"
44
+ }