Skip to content

Commit 5a279e5

Browse files
authored
Merge pull request #72 from executeautomation/main
Added Hover and Select Capability in Puppeteer MCP Server
2 parents def7549 + 2385870 commit 5a279e5

File tree

2 files changed

+89
-5
lines changed

2 files changed

+89
-5
lines changed

src/puppeteer/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,22 @@ A Model Context Protocol server that provides browser automation capabilities us
2222
- Click elements on the page
2323
- Input: `selector` (string): CSS selector for element to click
2424

25+
- **puppeteer_hover**
26+
- Hover elements on the page
27+
- Input: `selector` (string): CSS selector for element to hover
28+
2529
- **puppeteer_fill**
2630
- Fill out input fields
2731
- Inputs:
2832
- `selector` (string): CSS selector for input field
2933
- `value` (string): Value to fill
3034

35+
- **puppeteer_select**
36+
- Select an element with SELECT tag
37+
- Inputs:
38+
- `selector` (string): CSS selector for element to select
39+
- `value` (string): Value to select
40+
3141
- **puppeteer_evaluate**
3242
- Execute JavaScript in the browser console
3343
- Input: `script` (string): JavaScript code to execute
@@ -64,6 +74,7 @@ Here's the Claude Desktop configuration to use the Puppeter server:
6474
}
6575
}
6676
}
77+
```
6778

6879
## License
6980

src/puppeteer/index.ts

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,29 @@ const TOOLS: Tool[] = [
6464
required: ["selector", "value"],
6565
},
6666
},
67+
{
68+
name: "puppeteer_select",
69+
description: "Select an element on the page with Select tag",
70+
inputSchema: {
71+
type: "object",
72+
properties: {
73+
selector: { type: "string", description: "CSS selector for element to select" },
74+
value: { type: "string", description: "Value to select" },
75+
},
76+
required: ["selector", "value"],
77+
},
78+
},
79+
{
80+
name: "puppeteer_hover",
81+
description: "Hover an element on the page",
82+
inputSchema: {
83+
type: "object",
84+
properties: {
85+
selector: { type: "string", description: "CSS selector for element to hover" },
86+
},
87+
required: ["selector"],
88+
},
89+
},
6790
{
6891
name: "puppeteer_evaluate",
6992
description: "Execute JavaScript in the browser console",
@@ -88,7 +111,7 @@ async function ensureBrowser() {
88111
browser = await puppeteer.launch({ headless: false });
89112
const pages = await browser.pages();
90113
page = pages[0];
91-
114+
92115
page.on("console", (msg) => {
93116
const logEntry = `[${msg.type()}] ${msg.text()}`;
94117
consoleLogs.push(logEntry);
@@ -122,7 +145,7 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
122145
const height = args.height ?? 600;
123146
await page.setViewport({ width, height });
124147

125-
const screenshot = await (args.selector ?
148+
const screenshot = await (args.selector ?
126149
(await page.$(args.selector))?.screenshot({ encoding: "base64" }) :
127150
page.screenshot({ encoding: "base64", fullPage: false }));
128151

@@ -210,12 +233,62 @@ async function handleToolCall(name: string, args: any): Promise<{ toolResult: Ca
210233
};
211234
}
212235

236+
case "puppeteer_select":
237+
try {
238+
await page.waitForSelector(args.selector);
239+
await page.select(args.selector, args.value);
240+
return {
241+
toolResult: {
242+
content: [{
243+
type: "text",
244+
text: `Selected ${args.selector} with: ${args.value}`,
245+
}],
246+
isError: false,
247+
},
248+
};
249+
} catch (error) {
250+
return {
251+
toolResult: {
252+
content: [{
253+
type: "text",
254+
text: `Failed to select ${args.selector}: ${(error as Error).message}`,
255+
}],
256+
isError: true,
257+
},
258+
};
259+
}
260+
261+
case "puppeteer_hover":
262+
try {
263+
await page.waitForSelector(args.selector);
264+
await page.hover(args.selector);
265+
return {
266+
toolResult: {
267+
content: [{
268+
type: "text",
269+
text: `Hovered ${args.selector}`,
270+
}],
271+
isError: false,
272+
},
273+
};
274+
} catch (error) {
275+
return {
276+
toolResult: {
277+
content: [{
278+
type: "text",
279+
text: `Failed to hover ${args.selector}: ${(error as Error).message}`,
280+
}],
281+
isError: true,
282+
},
283+
};
284+
}
285+
213286
case "puppeteer_evaluate":
214287
try {
215288
const result = await page.evaluate((script) => {
216289
const logs: string[] = [];
217290
const originalConsole = { ...console };
218-
291+
219292
['log', 'info', 'warn', 'error'].forEach(method => {
220293
(console as any)[method] = (...args: any[]) => {
221294
logs.push(`[${method}] ${args.join(' ')}`);
@@ -301,7 +374,7 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
301374

302375
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
303376
const uri = request.params.uri.toString();
304-
377+
305378
if (uri === "console://logs") {
306379
return {
307380
contents: [{
@@ -333,7 +406,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
333406
tools: TOOLS,
334407
}));
335408

336-
server.setRequestHandler(CallToolRequestSchema, async (request) =>
409+
server.setRequestHandler(CallToolRequestSchema, async (request) =>
337410
handleToolCall(request.params.name, request.params.arguments ?? {})
338411
);
339412

0 commit comments

Comments
 (0)