Skip to content

Commit 67241ff

Browse files
fix(mcp): report invalid tool arguments (#40979)
Signed-off-by: Pavel Feldman <pavel.feldman@gmail.com> Co-authored-by: Pavel Feldman <pavel.feldman@gmail.com>
1 parent 10d6473 commit 67241ff

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

packages/playwright-core/src/tools/backend/browserBackend.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
* limitations under the License.
1515
*/
1616

17+
import * as z from 'zod';
1718
import debug from 'debug';
1819
import { Context } from './context';
1920
import { Response } from './response';
@@ -63,8 +64,14 @@ export class BrowserBackend implements ServerBackend {
6364
const tool = this._tools.find(tool => tool.schema.name === name)!;
6465
if (!tool)
6566
return formatError(`Tool "${name}" not found`);
66-
// eslint-disable-next-line no-restricted-syntax
67-
const parsedArguments = tool.schema.inputSchema.parse(rawArguments) as any;
67+
let parsedArguments: any;
68+
try {
69+
parsedArguments = tool.schema.inputSchema.parse(rawArguments);
70+
} catch (error) {
71+
if (error instanceof z.ZodError)
72+
return formatError(`Invalid arguments for tool "${name}":\n${z.prettifyError(error)}`);
73+
throw error;
74+
}
6875
const cwd = rawArguments._meta?.cwd;
6976
const raw = !!rawArguments._meta?.raw;
7077
const context = this._context!;

tests/mcp/validation.spec.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Copyright (c) Microsoft Corporation.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { test, expect, parseResponse } from './fixtures';
18+
19+
test('reports missing required tool arguments', async ({ client }) => {
20+
const response = await client.callTool({
21+
name: 'browser_navigate',
22+
arguments: {},
23+
});
24+
25+
expect(response).toHaveResponse({
26+
isError: true,
27+
error: expect.stringContaining('Invalid arguments for tool "browser_navigate":'),
28+
});
29+
const parsed = parseResponse(response);
30+
expect(parsed.error).toContain('Invalid input: expected string');
31+
expect(parsed.error).toContain('at url');
32+
});
33+
34+
test('reports invalid tool argument types', async ({ client }) => {
35+
const response = await client.callTool({
36+
name: 'browser_navigate',
37+
arguments: { url: 123 },
38+
});
39+
40+
const parsed = parseResponse(response);
41+
expect(parsed.isError).toBe(true);
42+
expect(parsed.error).toContain('Invalid arguments for tool "browser_navigate":');
43+
expect(parsed.error).toContain('Invalid input: expected string, received number');
44+
expect(parsed.error).toContain('at url');
45+
});

0 commit comments

Comments
 (0)