Skip to content

Commit 5393d2d

Browse files
authored
fix(browser_eval): align tool args with Playwright MCP 0.0.75 schema (target fields + fill_form) (#141)
* fix(browser_eval): map element refs to Playwright MCP 'target' fields @playwright/mcp 0.0.75 (current @latest) renamed the locator field across several tools, so the wrapper's old names fail upstream validation (InputValidationError): - browser_click / browser_type / browser_evaluate: ref -> target - browser_drag: startRef/endRef -> startTarget/endTarget Verified against the auto-generated tool docs in @playwright/mcp@0.0.75. Adds target/startTarget/endTarget inputs and forwards the new names, while keeping ref/startRef/endRef accepted as back-compat aliases (target = args.target ?? args.ref). Note: browser_fill_form's field-object shape also changed upstream but its exact schema could not be verified from the package, so it is intentionally left unchanged here. Refs #136 * fix(browser_eval): update fill_form field shape for Playwright MCP 0.0.75 Verified against the live @playwright/mcp@0.0.75 browser_fill_form schema (via tools/list): each field is now { element?, target (req), name (req), type (req: textbox|checkbox|radio| combobox|slider), value (req) } replacing the old { selector, value }. Update the user-facing schema and forward the new field names; accept 'selector' as a back-compat alias routed to 'target' (target = f.target ?? f.selector). Completes the field-rename fix so fill_form no longer fails upstream with InputValidationError.
1 parent 3f9f406 commit 5393d2d

1 file changed

Lines changed: 59 additions & 12 deletions

File tree

src/tools/browser-eval.ts

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,16 @@ export const inputSchema = {
3636
url: z.string().optional().describe("URL to navigate to (required for 'navigate' action)"),
3737

3838
element: z.string().optional().describe("Element to interact with (CSS selector or text)"),
39-
ref: z.string().optional().describe("Reference to element from accessibility snapshot"),
39+
ref: z
40+
.string()
41+
.optional()
42+
.describe("Reference to element from accessibility snapshot (alias for 'target')"),
43+
target: z
44+
.string()
45+
.optional()
46+
.describe(
47+
"Exact target element reference from the page snapshot, or a unique element selector. Preferred over 'ref'."
48+
),
4049
doubleClick: z
4150
.union([z.boolean(), z.string().transform((val) => val === "true")])
4251
.optional()
@@ -52,8 +61,20 @@ export const inputSchema = {
5261
fields: z
5362
.array(
5463
z.object({
55-
selector: z.string(),
56-
value: z.string(),
64+
element: z.string().optional().describe("Human-readable element description"),
65+
target: z
66+
.string()
67+
.optional()
68+
.describe(
69+
"Exact target element reference from the snapshot, or a unique selector. Preferred over 'selector'."
70+
),
71+
selector: z.string().optional().describe("Alias for 'target' (back-compat)"),
72+
name: z.string().optional().describe("Human-readable field name"),
73+
type: z
74+
.enum(["textbox", "checkbox", "radio", "combobox", "slider"])
75+
.optional()
76+
.describe("Field type (required by Playwright MCP)"),
77+
value: z.string().describe("Value to fill into the field"),
5778
})
5879
)
5980
.optional()
@@ -72,9 +93,17 @@ export const inputSchema = {
7293
.describe("Only return error messages from console"),
7394

7495
startElement: z.string().optional().describe("Starting element for drag operation"),
75-
startRef: z.string().optional().describe("Starting element reference"),
96+
startRef: z.string().optional().describe("Starting element reference (alias for 'startTarget')"),
97+
startTarget: z
98+
.string()
99+
.optional()
100+
.describe("Exact source element reference for drag. Preferred over 'startRef'."),
76101
endElement: z.string().optional().describe("Ending element for drag operation"),
77-
endRef: z.string().optional().describe("Ending element reference"),
102+
endRef: z.string().optional().describe("Ending element reference (alias for 'endTarget')"),
103+
endTarget: z
104+
.string()
105+
.optional()
106+
.describe("Exact target element reference for drag. Preferred over 'endRef'."),
78107

79108
files: z.array(z.string()).optional().describe("File paths to upload"),
80109
}
@@ -134,18 +163,28 @@ type BrowserEvalArgs = {
134163
url?: string
135164
element?: string
136165
ref?: string
166+
target?: string
137167
doubleClick?: boolean | string
138168
button?: "left" | "right" | "middle"
139169
modifiers?: string[]
140170
text?: string
141-
fields?: Array<{ selector: string; value: string }>
171+
fields?: Array<{
172+
element?: string
173+
target?: string
174+
selector?: string
175+
name?: string
176+
type?: "textbox" | "checkbox" | "radio" | "combobox" | "slider"
177+
value: string
178+
}>
142179
script?: string
143180
fullPage?: boolean | string
144181
errorsOnly?: boolean | string
145182
startElement?: string
146183
startRef?: string
184+
startTarget?: string
147185
endElement?: string
148186
endRef?: string
187+
endTarget?: string
149188
files?: string[]
150189
}
151190

@@ -215,7 +254,7 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
215254
toolName = "browser_click"
216255
toolArgs = {
217256
element: args.element,
218-
ref: args.ref,
257+
target: args.target ?? args.ref,
219258
doubleClick: args.doubleClick,
220259
button: args.button,
221260
modifiers: args.modifiers,
@@ -229,7 +268,7 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
229268
toolName = "browser_type"
230269
toolArgs = {
231270
element: args.element,
232-
ref: args.ref,
271+
target: args.target ?? args.ref,
233272
text: args.text,
234273
}
235274
break
@@ -239,7 +278,15 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
239278
throw new Error("Fields are required for fill_form action")
240279
}
241280
toolName = "browser_fill_form"
242-
toolArgs = { fields: args.fields }
281+
toolArgs = {
282+
fields: args.fields.map((f) => ({
283+
element: f.element,
284+
target: f.target ?? f.selector,
285+
name: f.name,
286+
type: f.type,
287+
value: f.value,
288+
})),
289+
}
243290
break
244291

245292
case "evaluate":
@@ -250,7 +297,7 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
250297
toolArgs = {
251298
function: args.script,
252299
element: args.element,
253-
ref: args.ref,
300+
target: args.target ?? args.ref,
254301
}
255302
break
256303

@@ -271,9 +318,9 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
271318
toolName = "browser_drag"
272319
toolArgs = {
273320
startElement: args.startElement,
274-
startRef: args.startRef,
321+
startTarget: args.startTarget ?? args.startRef,
275322
endElement: args.endElement,
276-
endRef: args.endRef,
323+
endTarget: args.endTarget ?? args.endRef,
277324
}
278325
break
279326

0 commit comments

Comments
 (0)