@@ -305,11 +305,51 @@ type TimeoutInfo = {
305305 onTimeout : ( ) => void ;
306306} ;
307307
308+ /**
309+ * Declares the request and notification vocabulary a `Protocol` subclass speaks.
310+ *
311+ * Supplying a concrete `ProtocolSpec` as `Protocol`'s second type argument gives method-name
312+ * autocomplete and params/result correlation on the typed overloads of `setRequestHandler`
313+ * and `setNotificationHandler`. The default leaves them string-keyed and untyped.
314+ */
315+ export type ProtocolSpec = {
316+ requests ?: Record < string , { params ?: unknown ; result : unknown } > ;
317+ notifications ?: Record < string , { params ?: unknown } > ;
318+ } ;
319+
320+ /**
321+ * The {@linkcode ProtocolSpec} that describes the standard MCP method vocabulary, derived from
322+ * {@linkcode RequestTypeMap}, {@linkcode ResultTypeMap} and {@linkcode NotificationTypeMap}.
323+ */
324+ export type McpSpec = {
325+ requests : { [ M in RequestMethod ] : { params : RequestTypeMap [ M ] [ 'params' ] ; result : ResultTypeMap [ M ] } } ;
326+ notifications : { [ M in NotificationMethod ] : { params : NotificationTypeMap [ M ] [ 'params' ] } } ;
327+ } ;
328+
329+ type _Requests < SpecT extends ProtocolSpec > = NonNullable < SpecT [ 'requests' ] > ;
330+ type _Notifications < SpecT extends ProtocolSpec > = NonNullable < SpecT [ 'notifications' ] > ;
331+
332+ /**
333+ * Method-name keys from a {@linkcode ProtocolSpec}'s `requests` map, or `never` for the
334+ * unconstrained default `ProtocolSpec`. Making the keys `never` for the default disables the
335+ * spec-typed overloads on `setRequestHandler` until the caller supplies a concrete `SpecT`.
336+ */
337+ export type SpecRequests < SpecT extends ProtocolSpec > = string extends keyof _Requests < SpecT > ? never : keyof _Requests < SpecT > & string ;
338+
339+ /** See {@linkcode SpecRequests}. */
340+ export type SpecNotifications < SpecT extends ProtocolSpec > = string extends keyof _Notifications < SpecT >
341+ ? never
342+ : keyof _Notifications < SpecT > & string ;
343+
308344/**
309345 * Implements MCP protocol framing on top of a pluggable transport, including
310346 * features like request/response linking, notifications, and progress.
347+ *
348+ * `Protocol` is abstract; `Client` and `Server` are the concrete role-specific implementations.
349+ * Subclasses (such as MCP-dialect protocols like MCP Apps) can supply a {@linkcode ProtocolSpec}
350+ * as the second type argument to get method-name autocomplete on their own vocabulary.
311351 */
312- export abstract class Protocol < ContextT extends BaseContext > {
352+ export abstract class Protocol < ContextT extends BaseContext = BaseContext , SpecT extends ProtocolSpec = McpSpec > {
313353 private _transport ?: Transport ;
314354 private _requestMessageId = 0 ;
315355 private _requestHandlers : Map < string , ( request : JSONRPCRequest , ctx : ContextT ) => Promise < Result > > = new Map ( ) ;
@@ -1042,10 +1082,19 @@ export abstract class Protocol<ContextT extends BaseContext> {
10421082 * Any method string; the supplied schema validates incoming `params`. Absent or undefined
10431083 * `params` are normalized to `{}` (after stripping `_meta`) before validation, so for
10441084 * no-params methods use `z.object({})`. `paramsSchema` may be any Standard Schema (Zod,
1045- * Valibot, ArkType, etc.).
1085+ * Valibot, ArkType, etc.). When `method` is listed in this instance's
1086+ * {@linkcode ProtocolSpec}, params and result types are inferred from `SpecT`.
10461087 * - **Zod schema** — `setRequestHandler(RequestZodSchema, (request, ctx) => …)`. The method
10471088 * name is read from the schema's `method` literal; the handler receives the parsed request.
10481089 */
1090+ setRequestHandler < K extends SpecRequests < SpecT > , P extends StandardSchemaV1 < _Requests < SpecT > [ K ] [ 'params' ] > > (
1091+ method : K ,
1092+ paramsSchema : P ,
1093+ handler : (
1094+ params : StandardSchemaV1 . InferOutput < P > ,
1095+ ctx : ContextT
1096+ ) => _Requests < SpecT > [ K ] [ 'result' ] | Promise < _Requests < SpecT > [ K ] [ 'result' ] >
1097+ ) : void ;
10491098 setRequestHandler < M extends RequestMethod > (
10501099 method : M ,
10511100 handler : ( request : RequestTypeMap [ M ] , ctx : ContextT ) => Result | Promise < Result >
@@ -1143,8 +1192,15 @@ export abstract class Protocol<ContextT extends BaseContext> {
11431192 *
11441193 * Mirrors {@linkcode setRequestHandler}: a two-arg spec-method form (handler receives the full
11451194 * notification object), a three-arg form with a `paramsSchema` (handler receives validated
1146- * `params`), and a Zod-schema form (method read from the schema's `method` literal).
1195+ * `params`), and a Zod-schema form (method read from the schema's `method` literal). When the
1196+ * three-arg form's `method` is listed in this instance's {@linkcode ProtocolSpec}, the params
1197+ * type is inferred from `SpecT`.
11471198 */
1199+ setNotificationHandler < K extends SpecNotifications < SpecT > , P extends StandardSchemaV1 < _Notifications < SpecT > [ K ] [ 'params' ] > > (
1200+ method : K ,
1201+ paramsSchema : P ,
1202+ handler : ( params : StandardSchemaV1 . InferOutput < P > ) => void | Promise < void >
1203+ ) : void ;
11481204 setNotificationHandler < M extends NotificationMethod > (
11491205 method : M ,
11501206 handler : ( notification : NotificationTypeMap [ M ] ) => void | Promise < void >
0 commit comments