Skip to content

Commit 5e538a6

Browse files
fix(core): guard spec-schema parse for non-spec methods in handler registration
The normalize-then-fall-through change routes custom methods through _setRequestHandlerByMethod, which previously assumed a spec method (unconditional getRequestSchema(method).parse). Guard with schema?. so custom methods registered via Server/Client overrides do not crash.
1 parent be7b9eb commit 5e538a6

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

packages/core/src/shared/protocol.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,7 +1064,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
10641064
this.assertRequestHandlerCapability(method);
10651065
const schema = getRequestSchema(method as RequestMethod);
10661066
this._requestHandlers.set(method, (request, ctx) => {
1067-
const parsed = schema.parse(request) as Request;
1067+
const parsed = schema ? (schema.parse(request) as Request) : request;
10681068
return Promise.resolve(handler(parsed, ctx));
10691069
});
10701070
}
@@ -1112,7 +1112,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
11121112
}
11131113
const schema = getNotificationSchema(method as NotificationMethod);
11141114
this._notificationHandlers.set(method, notification => {
1115-
const parsed = schema.parse(notification);
1115+
const parsed = schema ? schema.parse(notification) : notification;
11161116
return Promise.resolve(handler(parsed));
11171117
});
11181118
}

packages/server/test/server/setRequestHandlerSchemaParity.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { describe, expect, it } from 'vitest';
2+
import { z } from 'zod';
23

34
import { CallToolRequestSchema, InMemoryTransport } from '@modelcontextprotocol/core';
45

@@ -46,4 +47,17 @@ describe('Server.setRequestHandler — Zod-schema form parity', () => {
4647
expect(stringRes.error).toBeDefined();
4748
expect(schemaRes.error).toEqual(stringRes.error);
4849
});
50+
51+
it('schema form handles non-spec methods through Server (no spec-schema crash)', async () => {
52+
const Echo = z.object({ method: z.literal('acme/echo'), params: z.object({ msg: z.string() }) });
53+
const { ct } = await setup(s => s.setRequestHandler(Echo, req => ({ reply: req.params.msg })));
54+
const res = await new Promise<{ result?: unknown; error?: unknown }>(resolve => {
55+
ct.onmessage = m => {
56+
const msg = m as { result?: unknown; error?: unknown };
57+
if ('result' in msg || 'error' in msg) resolve(msg);
58+
};
59+
ct.send({ jsonrpc: '2.0', id: 1, method: 'acme/echo', params: { msg: 'hi' } });
60+
});
61+
expect(res.result).toEqual({ reply: 'hi' });
62+
});
4963
});

0 commit comments

Comments
 (0)