Skip to content

Commit f4b5f42

Browse files
fix: revert out-of-scope SdkError, add ctx.mcpReq.send to changeset + tests
1 parent 296e179 commit f4b5f42

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

.changeset/custom-method-overloads.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
'@modelcontextprotocol/server': minor
44
---
55

6-
`setRequestHandler`/`setNotificationHandler` accept the v1 `(ZodSchema, handler)` form as a first-class alternative to `(methodString, handler)`. `request()` accepts an explicit result schema (`request(req, resultSchema, options?)`) and has a method-keyed return type for spec methods. `callTool(params, resultSchema?)` accepts the v1 schema arg (ignored). `removeRequestHandler`/`removeNotificationHandler`/`assertCanSetRequestHandler` accept any method string.
6+
`setRequestHandler`/`setNotificationHandler` accept the v1 `(ZodSchema, handler)` form as a first-class alternative to `(methodString, handler)`. `request()` and `ctx.mcpReq.send()` accept an explicit result schema (`request(req, resultSchema, options?)`) and have method-keyed return types for spec methods. `callTool(params, resultSchema?)` accepts the v1 schema arg (ignored). `removeRequestHandler`/`removeNotificationHandler`/`assertCanSetRequestHandler` accept any method string.

packages/core/src/shared/protocol.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,7 @@ export abstract class Protocol<ContextT extends BaseContext> {
837837
};
838838

839839
if (!this._transport) {
840-
earlyReject(new SdkError(SdkErrorCode.NotConnected, 'Not connected'));
840+
earlyReject(new Error('Not connected'));
841841
return;
842842
}
843843

packages/core/test/shared/customMethods.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,32 @@ describe('request() — explicit result schema overload', () => {
108108
});
109109
});
110110

111+
describe('ctx.mcpReq.send() — explicit result schema overload', () => {
112+
it('forwards to a related request and validates result via the supplied schema', async () => {
113+
const { a, b } = await makePair();
114+
a.setRequestHandler(EchoRequest, req => ({ reply: req.params.msg }));
115+
let captured: unknown;
116+
b.setRequestHandler(z.object({ method: z.literal('acme/outer') }), async (_req, ctx) => {
117+
captured = await ctx.mcpReq.send({ method: 'acme/echo', params: { msg: 'via-send' } }, z.object({ reply: z.string() }));
118+
return {};
119+
});
120+
await a.request({ method: 'acme/outer' }, z.object({}));
121+
expect(captured).toEqual({ reply: 'via-send' });
122+
});
123+
124+
it('spec-method form (no schema) uses method-keyed return', async () => {
125+
const { a, b } = await makePair();
126+
a.setRequestHandler('ping', () => ({}));
127+
let pingResult: unknown;
128+
b.setRequestHandler(z.object({ method: z.literal('acme/outer') }), async (_req, ctx) => {
129+
pingResult = await ctx.mcpReq.send({ method: 'ping' });
130+
return {};
131+
});
132+
await a.request({ method: 'acme/outer' }, z.object({}));
133+
expect(pingResult).toEqual({});
134+
});
135+
});
136+
111137
describe('notification() mock-assignability', () => {
112138
it('single-signature notification() is assignable from a simple mock (compile-time check)', () => {
113139
const p = new TestProtocol();

0 commit comments

Comments
 (0)