Skip to content

Commit 1baf4b6

Browse files
committed
test: expect invalid tool args protocol errors
1 parent be61bca commit 1baf4b6

3 files changed

Lines changed: 67 additions & 91 deletions

File tree

test/e2e/requirements.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,12 +2109,7 @@ export const REQUIREMENTS: Record<string, Requirement> = {
21092109
'standardschema:tool:invalid-args-rejected': {
21102110
source: 'sdk',
21112111
behavior:
2112-
'tools/call arguments that fail the registered Standard Schema validation are rejected with JSON-RPC -32602 (Input validation error) and the tool handler is not invoked.',
2113-
knownFailures: [
2114-
{
2115-
note: "McpServer's tools/call handler catches the input-validation ProtocolError (-32602) and returns it as an isError result, so callTool() resolves instead of rejecting; the handler is still not invoked."
2116-
}
2117-
]
2112+
'tools/call arguments that fail the registered Standard Schema validation are rejected with JSON-RPC -32602 (Input validation error) and the tool handler is not invoked.'
21182113
},
21192114
'validators:from-json-schema:tool-roundtrip': {
21202115
source: 'sdk',
@@ -2124,12 +2119,7 @@ export const REQUIREMENTS: Record<string, Requirement> = {
21242119
'validators:from-json-schema:invalid-args-rejected': {
21252120
source: 'sdk',
21262121
behavior:
2127-
'tools/call arguments violating the JSON Schema wrapped by fromJsonSchema() are rejected with JSON-RPC -32602 and the handler is not invoked.',
2128-
knownFailures: [
2129-
{
2130-
note: "McpServer's tools/call handler catches the input-validation ProtocolError (-32602) and returns it as an isError result, so callTool() resolves instead of rejecting; the handler is still not invoked."
2131-
}
2132-
]
2122+
'tools/call arguments violating the JSON Schema wrapped by fromJsonSchema() are rejected with JSON-RPC -32602 and the handler is not invoked.'
21332123
},
21342124
'validators:custom-validator:override': {
21352125
source: 'sdk',

test/e2e/scenarios/tools.test.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,14 +1064,16 @@ verifies('mcpserver:tool:input-validation', async ({ transport }: TestArgs) => {
10641064
expect(ok.isError).toBeFalsy();
10651065
expect(handlerCalls.n).toBe(1);
10661066

1067-
const wrongType = await client.callTool({ name: 'typed', arguments: { prompt: 123 } });
1068-
expect(wrongType.isError).toBe(true);
1069-
expect(wrongType.content).toEqual([{ type: 'text', text: expect.stringMatching(/invalid|validation/i) }]);
1067+
await expect(client.callTool({ name: 'typed', arguments: { prompt: 123 } })).rejects.toMatchObject({
1068+
code: ProtocolErrorCode.InvalidParams,
1069+
message: expect.stringMatching(/invalid|validation/i)
1070+
});
10701071
expect(handlerCalls.n).toBe(1);
10711072

1072-
const missing = await client.callTool({ name: 'typed', arguments: {} });
1073-
expect(missing.isError).toBe(true);
1074-
expect(missing.content).toEqual([{ type: 'text', text: expect.stringMatching(/invalid|validation|required/i) }]);
1073+
await expect(client.callTool({ name: 'typed', arguments: {} })).rejects.toMatchObject({
1074+
code: ProtocolErrorCode.InvalidParams,
1075+
message: expect.stringMatching(/invalid|validation|required/i)
1076+
});
10751077
expect(handlerCalls.n).toBe(1);
10761078
});
10771079

@@ -1200,14 +1202,18 @@ verifies('typescript:mcpserver:tool:schema-variants', async ({ transport }: Test
12001202
expect(coerced.content).toEqual([{ type: 'text', text: 'coerced:7' }]);
12011203

12021204
// Rejections — proves parse() actually runs for each shape.
1203-
const unionRejected = await client.callTool({ name: 'zod-union', arguments: { kind: 'a', a: 123 } });
1204-
expect(unionRejected.isError).toBe(true);
1205-
const intersectionRejected = await client.callTool({ name: 'zod-intersection', arguments: { left: 'L' } });
1206-
expect(intersectionRejected.isError).toBe(true);
1207-
const nestedRejected = await client.callTool({ name: 'zod-nested', arguments: { outer: { inner: { value: 'x' } } } });
1208-
expect(nestedRejected.isError).toBe(true);
1209-
const coerceRejected = await client.callTool({ name: 'zod-coerce', arguments: { n: '-3' } });
1210-
expect(coerceRejected.isError).toBe(true);
1205+
await expect(client.callTool({ name: 'zod-union', arguments: { kind: 'a', a: 123 } })).rejects.toMatchObject({
1206+
code: ProtocolErrorCode.InvalidParams
1207+
});
1208+
await expect(client.callTool({ name: 'zod-intersection', arguments: { left: 'L' } })).rejects.toMatchObject({
1209+
code: ProtocolErrorCode.InvalidParams
1210+
});
1211+
await expect(client.callTool({ name: 'zod-nested', arguments: { outer: { inner: { value: 'x' } } } })).rejects.toMatchObject({
1212+
code: ProtocolErrorCode.InvalidParams
1213+
});
1214+
await expect(client.callTool({ name: 'zod-coerce', arguments: { n: '-3' } })).rejects.toMatchObject({
1215+
code: ProtocolErrorCode.InvalidParams
1216+
});
12111217
});
12121218

12131219
verifies('typescript:mcpserver:tool:extra', async ({ transport }: TestArgs) => {

test/integration/test/server/mcp.test.ts

Lines changed: 45 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,26 +1189,21 @@ describe('Zod v4', () => {
11891189

11901190
await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]);
11911191

1192-
const result = await client.request({
1193-
method: 'tools/call',
1194-
params: {
1195-
name: 'test',
1196-
arguments: {
1192+
await expect(
1193+
client.request({
1194+
method: 'tools/call',
1195+
params: {
11971196
name: 'test',
1198-
value: 'not a number'
1197+
arguments: {
1198+
name: 'test',
1199+
value: 'not a number'
1200+
}
11991201
}
1200-
}
1202+
})
1203+
).rejects.toMatchObject({
1204+
code: ProtocolErrorCode.InvalidParams,
1205+
message: expect.stringContaining('Input validation error: Invalid arguments for tool test')
12011206
});
1202-
1203-
expect(result.isError).toBe(true);
1204-
expect(result.content).toEqual(
1205-
expect.arrayContaining([
1206-
{
1207-
type: 'text',
1208-
text: expect.stringContaining('Input validation error: Invalid arguments for tool test')
1209-
}
1210-
])
1211-
);
12121207
});
12131208

12141209
/***
@@ -4986,23 +4981,18 @@ describe('Zod v4', () => {
49864981
await server.connect(serverTransport);
49874982
await client.connect(clientTransport);
49884983

4989-
const invalidTypeResult = await client.callTool({
4990-
name: 'union-test',
4991-
arguments: {
4992-
type: 'a',
4993-
value: 123
4994-
}
4984+
await expect(
4985+
client.callTool({
4986+
name: 'union-test',
4987+
arguments: {
4988+
type: 'a',
4989+
value: 123
4990+
}
4991+
})
4992+
).rejects.toMatchObject({
4993+
code: ProtocolErrorCode.InvalidParams,
4994+
message: expect.stringContaining('Input validation error')
49954995
});
4996-
4997-
expect(invalidTypeResult.isError).toBe(true);
4998-
expect(invalidTypeResult.content).toEqual(
4999-
expect.arrayContaining([
5000-
expect.objectContaining({
5001-
type: 'text',
5002-
text: expect.stringContaining('Input validation error')
5003-
})
5004-
])
5005-
);
50064996
});
50074997
});
50084998

@@ -6244,41 +6234,31 @@ describe('Zod v4', () => {
62446234
await server.connect(serverTransport);
62456235
await client.connect(clientTransport);
62466236

6247-
const invalidTypeResult = await client.callTool({
6248-
name: 'union-test',
6249-
arguments: {
6250-
type: 'a',
6251-
value: 123
6252-
}
6237+
await expect(
6238+
client.callTool({
6239+
name: 'union-test',
6240+
arguments: {
6241+
type: 'a',
6242+
value: 123
6243+
}
6244+
})
6245+
).rejects.toMatchObject({
6246+
code: ProtocolErrorCode.InvalidParams,
6247+
message: expect.stringContaining('Input validation error')
62536248
});
62546249

6255-
expect(invalidTypeResult.isError).toBe(true);
6256-
expect(invalidTypeResult.content).toEqual(
6257-
expect.arrayContaining([
6258-
expect.objectContaining({
6259-
type: 'text',
6260-
text: expect.stringContaining('Input validation error')
6261-
})
6262-
])
6263-
);
6264-
6265-
const invalidDiscriminatorResult = await client.callTool({
6266-
name: 'union-test',
6267-
arguments: {
6268-
type: 'c',
6269-
value: 'test'
6270-
}
6250+
await expect(
6251+
client.callTool({
6252+
name: 'union-test',
6253+
arguments: {
6254+
type: 'c',
6255+
value: 'test'
6256+
}
6257+
})
6258+
).rejects.toMatchObject({
6259+
code: ProtocolErrorCode.InvalidParams,
6260+
message: expect.stringContaining('Input validation error')
62716261
});
6272-
6273-
expect(invalidDiscriminatorResult.isError).toBe(true);
6274-
expect(invalidDiscriminatorResult.content).toEqual(
6275-
expect.arrayContaining([
6276-
expect.objectContaining({
6277-
type: 'text',
6278-
text: expect.stringContaining('Input validation error')
6279-
})
6280-
])
6281-
);
62826262
});
62836263
});
62846264

0 commit comments

Comments
 (0)