|
2 | 2 | /** |
3 | 3 | * Registering vendor-specific (non-spec) JSON-RPC methods on a `Server`. |
4 | 4 | * |
5 | | - * Custom methods use the Zod-schema form of `setRequestHandler` / `setNotificationHandler`: |
6 | | - * pass a Zod object schema whose `method` field is `z.literal('<method>')`. The same overload |
7 | | - * is available on `Client` (for server→client custom methods). |
| 5 | + * Custom methods use the 3-arg form of `setRequestHandler` / `setNotificationHandler`: |
| 6 | + * pass the method string, a params schema, and the handler. The same overload is |
| 7 | + * available on `Client` (for server→client custom methods) — you do NOT need a raw |
| 8 | + * `Protocol` instance for this. |
8 | 9 | * |
9 | 10 | * To call these from the client side, use: |
10 | 11 | * await client.request({ method: 'acme/search', params: { query: 'widgets' } }, SearchResult) |
|
15 | 16 | import { Server, StdioServerTransport } from '@modelcontextprotocol/server'; |
16 | 17 | import { z } from 'zod'; |
17 | 18 |
|
18 | | -const SearchRequest = z.object({ |
19 | | - method: z.literal('acme/search'), |
20 | | - params: z.object({ query: z.string() }) |
21 | | -}); |
22 | | - |
23 | | -const TickNotification = z.object({ |
24 | | - method: z.literal('acme/tick'), |
25 | | - params: z.object({ n: z.number() }) |
26 | | -}); |
| 19 | +const SearchParams = z.object({ query: z.string() }); |
| 20 | +const TickParams = z.object({ n: z.number() }); |
27 | 21 |
|
28 | 22 | const server = new Server({ name: 'custom-method-server', version: '1.0.0' }, { capabilities: {} }); |
29 | 23 |
|
30 | | -server.setRequestHandler(SearchRequest, async (request, ctx) => { |
31 | | - console.log('[server] acme/search query=' + request.params.query); |
| 24 | +server.setRequestHandler('acme/search', SearchParams, async (params, ctx) => { |
| 25 | + console.log('[server] acme/search query=' + params.query); |
32 | 26 | await ctx.mcpReq.notify({ method: 'acme/searchProgress', params: { stage: 'start', pct: 0 } }); |
33 | | - const hits = [request.params.query, request.params.query + '-result']; |
| 27 | + const hits = [params.query, params.query + '-result']; |
34 | 28 | await ctx.mcpReq.notify({ method: 'acme/searchProgress', params: { stage: 'done', pct: 100 } }); |
35 | 29 | return { hits }; |
36 | 30 | }); |
37 | 31 |
|
38 | | -server.setNotificationHandler(TickNotification, n => { |
39 | | - console.log('[server] acme/tick n=' + n.params.n); |
| 32 | +server.setNotificationHandler('acme/tick', TickParams, p => { |
| 33 | + console.log('[server] acme/tick n=' + p.n); |
40 | 34 | }); |
41 | 35 |
|
42 | 36 | await server.connect(new StdioServerTransport()); |
0 commit comments