Skip to content

Commit 02634bf

Browse files
committed
fix: report POST parse errors via transport onerror
1 parent ccb78f2 commit 02634bf

2 files changed

Lines changed: 42 additions & 2 deletions

File tree

packages/server/src/server/streamableHttp.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,8 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
635635
if (options?.parsedBody === undefined) {
636636
try {
637637
rawMessage = await req.json();
638-
} catch {
638+
} catch (error) {
639+
this.onerror?.(error instanceof Error ? error : new Error(String(error)));
639640
return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON');
640641
}
641642
} else {
@@ -649,7 +650,8 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
649650
messages = Array.isArray(rawMessage)
650651
? rawMessage.map(msg => JSONRPCMessageSchema.parse(msg))
651652
: [JSONRPCMessageSchema.parse(rawMessage)];
652-
} catch {
653+
} catch (error) {
654+
this.onerror?.(error instanceof Error ? error : new Error(String(error)));
653655
return this.createJsonErrorResponse(400, -32_700, 'Parse error: Invalid JSON-RPC message');
654656
}
655657

packages/server/test/server/streamableHttp.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,44 @@ describe('Zod v4', () => {
333333
expectErrorResponse(errorData, -32_700, /Parse error.*Invalid JSON/);
334334
});
335335

336+
it('should call onerror for invalid JSON', async () => {
337+
const errorSpy = vi.fn();
338+
transport.onerror = errorSpy;
339+
340+
const request = new Request('http://localhost/mcp', {
341+
method: 'POST',
342+
headers: {
343+
Accept: 'application/json, text/event-stream',
344+
'Content-Type': 'application/json'
345+
},
346+
body: 'not valid json'
347+
});
348+
349+
const response = await transport.handleRequest(request);
350+
351+
expect(response.status).toBe(400);
352+
expect(errorSpy).toHaveBeenCalledTimes(1);
353+
});
354+
355+
it('should call onerror for invalid JSON-RPC message', async () => {
356+
const errorSpy = vi.fn();
357+
transport.onerror = errorSpy;
358+
359+
const request = new Request('http://localhost/mcp', {
360+
method: 'POST',
361+
headers: {
362+
Accept: 'application/json, text/event-stream',
363+
'Content-Type': 'application/json'
364+
},
365+
body: JSON.stringify({ bad: 'shape' })
366+
});
367+
368+
const response = await transport.handleRequest(request);
369+
370+
expect(response.status).toBe(400);
371+
expect(errorSpy).toHaveBeenCalledTimes(1);
372+
});
373+
336374
it('should accept notifications without session and return 202', async () => {
337375
sessionId = await initializeServer();
338376

0 commit comments

Comments
 (0)