Skip to content

Commit e3e5af3

Browse files
committed
data in error response
1 parent d3e796a commit e3e5af3

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/examples/server/honoWebStandardStreamableHttp.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ app.use(
5656
// Health check endpoint
5757
app.get('/health', c => c.json({ status: 'ok' }));
5858

59-
// MCP endpoint - pass requests directly to the transport
59+
// MCP endpoint
6060
app.all('/mcp', c => transport.handleRequest(c.req.raw));
6161

6262
// Start the server

src/server/webStandardStreamableHttp.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,18 +255,27 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
255255
/**
256256
* Helper to create a JSON error response
257257
*/
258-
private createJsonErrorResponse(status: number, code: number, message: string, headers?: Record<string, string>): Response {
258+
private createJsonErrorResponse(
259+
status: number,
260+
code: number,
261+
message: string,
262+
options?: { headers?: Record<string, string>; data?: string }
263+
): Response {
264+
const error: { code: number; message: string; data?: string } = { code, message };
265+
if (options?.data !== undefined) {
266+
error.data = options.data;
267+
}
259268
return new Response(
260269
JSON.stringify({
261270
jsonrpc: '2.0',
262-
error: { code, message },
271+
error,
263272
id: null
264273
}),
265274
{
266275
status,
267276
headers: {
268277
'Content-Type': 'application/json',
269-
...headers
278+
...options?.headers
270279
}
271280
}
272281
);
@@ -767,7 +776,7 @@ export class WebStandardStreamableHTTPServerTransport implements Transport {
767776
} catch (error) {
768777
// return JSON-RPC formatted error
769778
this.onerror?.(error as Error);
770-
return this.createJsonErrorResponse(400, -32700, 'Parse error');
779+
return this.createJsonErrorResponse(400, -32700, 'Parse error', { data: String(error) });
771780
}
772781
}
773782

test/server/streamableHttp.test.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,22 @@ async function sendPostRequest(
119119
});
120120
}
121121

122-
function expectErrorResponse(data: unknown, expectedCode: number, expectedMessagePattern: RegExp): void {
122+
function expectErrorResponse(
123+
data: unknown,
124+
expectedCode: number,
125+
expectedMessagePattern: RegExp,
126+
options?: { expectData?: boolean }
127+
): void {
123128
expect(data).toMatchObject({
124129
jsonrpc: '2.0',
125130
error: expect.objectContaining({
126131
code: expectedCode,
127132
message: expect.stringMatching(expectedMessagePattern)
128133
})
129134
});
135+
if (options?.expectData) {
136+
expect((data as { error: { data?: string } }).error.data).toBeDefined();
137+
}
130138
}
131139
describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
132140
/**
@@ -679,6 +687,28 @@ describe.each(zodTestMatrix)('$zodVersionLabel', (entry: ZodMatrixEntry) => {
679687
expectErrorResponse(errorData, -32700, /Parse error/);
680688
});
681689

690+
it('should include error data in parse error response for unexpected errors', async () => {
691+
sessionId = await initializeServer();
692+
693+
// We can't easily trigger the catch-all error handler, but we can verify
694+
// that the JSON parse error includes useful information
695+
const response = await fetch(baseUrl, {
696+
method: 'POST',
697+
headers: {
698+
'Content-Type': 'application/json',
699+
Accept: 'application/json, text/event-stream',
700+
'mcp-session-id': sessionId
701+
},
702+
body: '{ invalid json }'
703+
});
704+
705+
expect(response.status).toBe(400);
706+
const errorData = await response.json();
707+
expectErrorResponse(errorData, -32700, /Parse error/);
708+
// The error message should contain details about what went wrong
709+
expect(errorData.error.message).toContain('Invalid JSON');
710+
});
711+
682712
it('should return 400 error for invalid JSON-RPC messages', async () => {
683713
sessionId = await initializeServer();
684714

0 commit comments

Comments
 (0)