From 1a5fc78b40366cc6f2b0483cbfb534b4a2af0abb Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 3 Feb 2026 19:32:51 +0000 Subject: [PATCH 1/4] refactor: remove vestigial generic type parameters from Protocol, Server, and Client --- examples/client/src/simpleStreamableHttp.ts | 9 +- packages/client/src/client/client.ts | 60 +---- .../client/src/experimental/tasks/client.ts | 21 +- packages/core/src/shared/protocol.ts | 71 +++--- packages/core/test/shared/protocol.test.ts | 230 +++++++++--------- .../shared/protocolTransportHandling.test.ts | 6 +- .../src/experimental/tasks/interfaces.ts | 18 +- .../server/src/experimental/tasks/server.ts | 18 +- packages/server/src/server/mcp.ts | 6 +- packages/server/src/server/server.ts | 55 +---- 10 files changed, 194 insertions(+), 300 deletions(-) diff --git a/examples/client/src/simpleStreamableHttp.ts b/examples/client/src/simpleStreamableHttp.ts index d4c51ffae..4d2a6e4d6 100644 --- a/examples/client/src/simpleStreamableHttp.ts +++ b/examples/client/src/simpleStreamableHttp.ts @@ -2,6 +2,7 @@ import { createInterface } from 'node:readline'; import type { CallToolRequest, + ElicitResult, GetPromptRequest, ListPromptsRequest, ListResourcesRequest, @@ -268,7 +269,7 @@ async function connect(url?: string): Promise { }; // Set up elicitation request handler with proper validation - client.setRequestHandler('elicitation/create', async request => { + client.setRequestHandler('elicitation/create', async (request): Promise => { if (request.params.mode !== 'form') { throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unsupported elicitation mode: ${request.params.mode}`); } @@ -293,7 +294,7 @@ async function connect(url?: string): Promise { attempts++; console.log(`\nPlease provide the following information (attempt ${attempts}/${maxAttempts}):`); - const content: Record = {}; + const content: Record = {}; let inputCancelled = false; // Collect input for each field @@ -357,7 +358,7 @@ async function connect(url?: string): Promise { // Parse and validate the input try { if (answer === '' && field.default !== undefined) { - content[fieldName] = field.default; + content[fieldName] = field.default as string | number | boolean | string[]; } else if (answer === '' && !isRequired) { // Skip optional empty fields continue; @@ -401,7 +402,7 @@ async function connect(url?: string): Promise { } } - content[fieldName] = parsedValue; + content[fieldName] = parsedValue as string | number | boolean | string[]; } } catch (error) { console.log(`❌ Error: ${error}`); diff --git a/packages/client/src/client/client.ts b/packages/client/src/client/client.ts index 95519a7bc..16439da67 100644 --- a/packages/client/src/client/client.ts +++ b/packages/client/src/client/client.ts @@ -22,15 +22,12 @@ import type { ListToolsRequest, LoggingLevel, MessageExtraInfo, - Notification, NotificationMethod, ProtocolOptions, ReadResourceRequest, - Request, RequestMethod, RequestOptions, RequestTypeMap, - Result, ServerCapabilities, SubscribeRequest, Tool, @@ -193,36 +190,8 @@ export type ClientOptions = ProtocolOptions & { * * The client will automatically begin the initialization flow with the server when connect() is called. * - * To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters: - * - * ```typescript - * // Custom schemas - * const CustomRequestSchema = RequestSchema.extend({...}) - * const CustomNotificationSchema = NotificationSchema.extend({...}) - * const CustomResultSchema = ResultSchema.extend({...}) - * - * // Type aliases - * type CustomRequest = z.infer - * type CustomNotification = z.infer - * type CustomResult = z.infer - * - * // Create typed client - * const client = new Client({ - * name: "CustomClient", - * version: "1.0.0" - * }) - * ``` */ -export class Client< - RequestT extends Request = Request, - NotificationT extends Notification = Notification, - ResultT extends Result = Result -> extends Protocol< - ClientRequest | RequestT, - ClientNotification | NotificationT, - ClientResult | ResultT, - ClientContext -> { +export class Client extends Protocol { private _serverCapabilities?: ServerCapabilities; private _serverVersion?: Implementation; private _capabilities: ClientCapabilities; @@ -231,7 +200,7 @@ export class Client< private _cachedToolOutputValidators: Map> = new Map(); private _cachedKnownTaskTools: Set = new Set(); private _cachedRequiredTaskTools: Set = new Set(); - private _experimental?: { tasks: ExperimentalClientTasks }; + private _experimental?: { tasks: ExperimentalClientTasks }; private _listChangedDebounceTimers: Map> = new Map(); private _pendingListChangedConfig?: ListChangedHandlers; private _enforceStrictCapabilities: boolean; @@ -255,9 +224,9 @@ export class Client< } protected override buildContext( - ctx: BaseContext, + ctx: BaseContext, _transportInfo?: MessageExtraInfo - ): ClientContext { + ): ClientContext { return ctx; } @@ -297,7 +266,7 @@ export class Client< * * @experimental */ - get experimental(): { tasks: ExperimentalClientTasks } { + get experimental(): { tasks: ExperimentalClientTasks } { if (!this._experimental) { this._experimental = { tasks: new ExperimentalClientTasks(this) @@ -324,16 +293,10 @@ export class Client< */ public override setRequestHandler( method: M, - handler: ( - request: RequestTypeMap[M], - ctx: ClientContext - ) => ClientResult | ResultT | Promise + handler: (request: RequestTypeMap[M], ctx: ClientContext) => ClientResult | Promise ): void { if (method === 'elicitation/create') { - const wrappedHandler = async ( - request: RequestTypeMap[M], - ctx: ClientContext - ): Promise => { + const wrappedHandler = async (request: RequestTypeMap[M], ctx: ClientContext): Promise => { const validatedRequest = parseSchema(ElicitRequestSchema, request); if (!validatedRequest.success) { // Type guard: if success is false, error is guaranteed to exist @@ -403,10 +366,7 @@ export class Client< } if (method === 'sampling/createMessage') { - const wrappedHandler = async ( - request: RequestTypeMap[M], - ctx: ClientContext - ): Promise => { + const wrappedHandler = async (request: RequestTypeMap[M], ctx: ClientContext): Promise => { const validatedRequest = parseSchema(CreateMessageRequestSchema, request); if (!validatedRequest.success) { const errorMessage = @@ -533,7 +493,7 @@ export class Client< return this._instructions; } - protected assertCapabilityForMethod(method: RequestT['method']): void { + protected assertCapabilityForMethod(method: string): void { switch (method as ClientRequest['method']) { case 'logging/setLevel': { if (!this._serverCapabilities?.logging) { @@ -596,7 +556,7 @@ export class Client< } } - protected assertNotificationCapability(method: NotificationT['method']): void { + protected assertNotificationCapability(method: string): void { switch (method as ClientNotification['method']) { case 'notifications/roots/list_changed': { if (!this._capabilities.roots?.listChanged) { diff --git a/packages/client/src/experimental/tasks/client.ts b/packages/client/src/experimental/tasks/client.ts index 657ef9b60..8fb16b2c2 100644 --- a/packages/client/src/experimental/tasks/client.ts +++ b/packages/client/src/experimental/tasks/client.ts @@ -9,14 +9,11 @@ import type { AnyObjectSchema, CallToolRequest, CancelTaskResult, - ClientRequest, GetTaskResult, ListTasksResult, - Notification, Request, RequestOptions, ResponseMessage, - Result, SchemaOutput } from '@modelcontextprotocol/core'; import { CallToolResultSchema, ProtocolError, ProtocolErrorCode } from '@modelcontextprotocol/core'; @@ -27,9 +24,9 @@ import type { Client } from '../../client/client.js'; * Internal interface for accessing Client's private methods. * @internal */ -interface ClientInternal { +interface ClientInternal { requestStream( - request: ClientRequest | RequestT, + request: Request, resultSchema: T, options?: RequestOptions ): AsyncGenerator>, void, void>; @@ -48,12 +45,8 @@ interface ClientInternal { * * @experimental */ -export class ExperimentalClientTasks< - RequestT extends Request = Request, - NotificationT extends Notification = Notification, - ResultT extends Result = Result -> { - constructor(private readonly _client: Client) {} +export class ExperimentalClientTasks { + constructor(private readonly _client: Client) {} /** * Calls a tool and returns an AsyncGenerator that yields response messages. @@ -96,7 +89,7 @@ export class ExperimentalClientTasks< options?: RequestOptions ): AsyncGenerator>, void, void> { // Access Client's internal methods - const clientInternal = this._client as unknown as ClientInternal; + const clientInternal = this._client as unknown as ClientInternal; // Add task creation parameters if server supports it and not explicitly provided const optionsWithTask = { @@ -255,14 +248,14 @@ export class ExperimentalClientTasks< * @experimental */ requestStream( - request: ClientRequest | RequestT, + request: Request, resultSchema: T, options?: RequestOptions ): AsyncGenerator>, void, void> { // Delegate to the client's underlying Protocol method type ClientWithRequestStream = { requestStream( - request: ClientRequest | RequestT, + request: Request, resultSchema: U, options?: RequestOptions ): AsyncGenerator>, void, void>; diff --git a/packages/core/src/shared/protocol.ts b/packages/core/src/shared/protocol.ts index fadf5222e..6f7f1e260 100644 --- a/packages/core/src/shared/protocol.ts +++ b/packages/core/src/shared/protocol.ts @@ -5,8 +5,6 @@ import type { AuthInfo, CancelledNotification, ClientCapabilities, - ClientNotification, - ClientRequest, CreateMessageRequest, CreateMessageResult, CreateMessageResultWithTools, @@ -37,8 +35,6 @@ import type { RequestTypeMap, Result, ServerCapabilities, - ServerNotification, - ServerRequest, Task, TaskCreationParams, TaskStatusNotification @@ -266,7 +262,7 @@ export type TaskContext = { /** * Base context provided to all request handlers. */ -export type BaseContext = { +export type BaseContext = { /** * The session ID from the transport, if available. */ @@ -301,14 +297,14 @@ export type BaseContext(request: SendRequestT, resultSchema: U, options?: TaskRequestOptions) => Promise>; + send: (request: Request, resultSchema: U, options?: TaskRequestOptions) => Promise>; /** * Sends a notification that relates to the current request being handled. * * This is used by certain transports to correctly associate related messages. */ - notify: (notification: SendNotificationT) => Promise; + notify: (notification: Notification) => Promise; }; /** @@ -330,10 +326,7 @@ export type BaseContext = BaseContext & { +export type ServerContext = BaseContext & { mcpReq: { /** * Send a log message notification to the client. @@ -378,10 +371,7 @@ export type ServerContext< /** * Context provided to client-side request handlers. */ -export type ClientContext< - SendRequestT extends Request = ClientRequest, - SendNotificationT extends Notification = ClientNotification -> = BaseContext; +export type ClientContext = BaseContext; /** * Information about a request's timeout state @@ -399,15 +389,10 @@ type TimeoutInfo = { * Implements MCP protocol framing on top of a pluggable transport, including * features like request/response linking, notifications, and progress. */ -export abstract class Protocol< - SendRequestT extends Request, - SendNotificationT extends Notification, - SendResultT extends Result, - ContextT extends BaseContext -> { +export abstract class Protocol { private _transport?: Transport; private _requestMessageId = 0; - private _requestHandlers: Map Promise> = new Map(); + private _requestHandlers: Map Promise> = new Map(); private _requestHandlerAbortControllers: Map = new Map(); private _notificationHandlers: Map Promise> = new Map(); private _responseHandlers: Map void> = new Map(); @@ -442,7 +427,7 @@ export abstract class Protocol< /** * A handler to invoke for any request types that do not have their own handler installed. */ - fallbackRequestHandler?: (request: JSONRPCRequest, ctx: ContextT) => Promise; + fallbackRequestHandler?: (request: JSONRPCRequest, ctx: ContextT) => Promise; /** * A handler to invoke for any notification types that do not have their own handler installed. @@ -463,7 +448,7 @@ export abstract class Protocol< this.setRequestHandler( 'ping', // Automatic pong by default. - _request => ({}) as SendResultT + _request => ({}) as Result ); // Install task handlers if TaskStore is provided @@ -480,11 +465,11 @@ export abstract class Protocol< // as the taskId parameter is the source of truth return { ...task - } as unknown as SendResultT; + } as Result; }); this.setRequestHandler('tasks/result', async (request, ctx) => { - const handleTaskResult = async (): Promise => { + const handleTaskResult = async (): Promise => { const taskId = request.params.taskId; // Deliver queued messages @@ -561,7 +546,7 @@ export abstract class Protocol< taskId: taskId } } - } as unknown as SendResultT; + } as Result; } return await handleTaskResult(); @@ -577,7 +562,7 @@ export abstract class Protocol< tasks, nextCursor, _meta: {} - } as unknown as SendResultT; + } as Result; } catch (error) { throw new ProtocolError( ProtocolErrorCode.InvalidParams, @@ -621,7 +606,7 @@ export abstract class Protocol< return { _meta: {}, ...cancelledTask - } as unknown as SendResultT; + } as Result; } catch (error) { // Re-throw ProtocolError as-is if (error instanceof ProtocolError) { @@ -640,7 +625,7 @@ export abstract class Protocol< * Builds the context object for request handlers. Subclasses must override * to return the appropriate context type (e.g., ServerContext adds requestInfo). */ - protected abstract buildContext(ctx: BaseContext, transportInfo?: MessageExtraInfo): ContextT; + protected abstract buildContext(ctx: BaseContext, transportInfo?: MessageExtraInfo): ContextT; private async _oncancel(notification: CancelledNotification): Promise { if (!notification.params.requestId) { @@ -816,7 +801,7 @@ export abstract class Protocol< ? { id: relatedTaskId, store: taskStore, requestedTtl: taskCreationParams?.ttl } : undefined; - const baseCtx: BaseContext = { + const baseCtx: BaseContext = { sessionId: capturedTransport?.sessionId, mcpReq: { id: request.id, @@ -1014,14 +999,14 @@ export abstract class Protocol< * * This should be implemented by subclasses. */ - protected abstract assertCapabilityForMethod(method: SendRequestT['method']): void; + protected abstract assertCapabilityForMethod(method: string): void; /** * A method to check if a notification is supported by the local side, for the given method to be sent. * * This should be implemented by subclasses. */ - protected abstract assertNotificationCapability(method: SendNotificationT['method']): void; + protected abstract assertNotificationCapability(method: string): void; /** * A method to check if a request handler is supported by the local side, for the given method to be handled. @@ -1072,7 +1057,7 @@ export abstract class Protocol< * @experimental Use `client.experimental.tasks.requestStream()` to access this method. */ protected async *requestStream( - request: SendRequestT, + request: Request, resultSchema: T, options?: RequestOptions ): AsyncGenerator>, void, void> { @@ -1172,7 +1157,7 @@ export abstract class Protocol< * * Do not use this method to emit notifications! Use notification() instead. */ - request(request: SendRequestT, resultSchema: T, options?: RequestOptions): Promise> { + request(request: Request, resultSchema: T, options?: RequestOptions): Promise> { const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {}; // Send the request @@ -1335,7 +1320,7 @@ export abstract class Protocol< * @experimental Use `client.experimental.tasks.getTask()` to access this method. */ protected async getTask(params: GetTaskRequest['params'], options?: RequestOptions): Promise { - // @ts-expect-error SendRequestT cannot directly contain GetTaskRequest, but we ensure all type instantiations contain it anyways + return this.request({ method: 'tasks/get', params }, GetTaskResultSchema, options); } @@ -1349,7 +1334,7 @@ export abstract class Protocol< resultSchema: T, options?: RequestOptions ): Promise> { - // @ts-expect-error SendRequestT cannot directly contain GetTaskPayloadRequest, but we ensure all type instantiations contain it anyways + return this.request({ method: 'tasks/result', params }, resultSchema, options); } @@ -1359,7 +1344,7 @@ export abstract class Protocol< * @experimental Use `client.experimental.tasks.listTasks()` to access this method. */ protected async listTasks(params?: { cursor?: string }, options?: RequestOptions): Promise> { - // @ts-expect-error SendRequestT cannot directly contain ListTasksRequest, but we ensure all type instantiations contain it anyways + return this.request({ method: 'tasks/list', params }, ListTasksResultSchema, options); } @@ -1369,14 +1354,14 @@ export abstract class Protocol< * @experimental Use `client.experimental.tasks.cancelTask()` to access this method. */ protected async cancelTask(params: { taskId: string }, options?: RequestOptions): Promise> { - // @ts-expect-error SendRequestT cannot directly contain CancelTaskRequest, but we ensure all type instantiations contain it anyways + return this.request({ method: 'tasks/cancel', params }, CancelTaskResultSchema, options); } /** * Emits a notification, which is a one-way message that does not expect a response. */ - async notification(notification: SendNotificationT, options?: NotificationOptions): Promise { + async notification(notification: Notification, options?: NotificationOptions): Promise { if (!this._transport) { throw new SdkError(SdkErrorCode.NotConnected, 'Not connected'); } @@ -1493,7 +1478,7 @@ export abstract class Protocol< */ setRequestHandler( method: M, - handler: (request: RequestTypeMap[M], ctx: ContextT) => SendResultT | Promise + handler: (request: RequestTypeMap[M], ctx: ContextT) => Result | Promise ): void { this.assertRequestHandlerCapability(method); const schema = getRequestSchema(method); @@ -1683,7 +1668,7 @@ export abstract class Protocol< method: 'notifications/tasks/status', params: task }); - await this.notification(notification as SendNotificationT); + await this.notification(notification as Notification); if (isTerminal(task.status)) { this._cleanupTaskProgressHandler(taskId); @@ -1718,7 +1703,7 @@ export abstract class Protocol< method: 'notifications/tasks/status', params: updatedTask }); - await this.notification(notification as SendNotificationT); + await this.notification(notification as Notification); if (isTerminal(updatedTask.status)) { this._cleanupTaskProgressHandler(taskId); diff --git a/packages/core/test/shared/protocol.test.ts b/packages/core/test/shared/protocol.test.ts index 67502bfcc..4d8f1830f 100644 --- a/packages/core/test/shared/protocol.test.ts +++ b/packages/core/test/shared/protocol.test.ts @@ -150,19 +150,19 @@ function assertQueuedRequest(o?: QueuedMessage): asserts o is QueuedRequest { } describe('protocol tests', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let sendSpy: MockInstance; beforeEach(() => { transport = new MockTransport(); sendSpy = vi.spyOn(transport, 'send'); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -634,12 +634,12 @@ describe('protocol tests', () => { it('should NOT debounce a notification that has parameters', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -660,12 +660,12 @@ describe('protocol tests', () => { it('should NOT debounce a notification that has a relatedRequestId', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -684,12 +684,12 @@ describe('protocol tests', () => { it('should clear pending debounced notifications on connection close', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -713,12 +713,12 @@ describe('protocol tests', () => { it('should debounce multiple synchronous calls when params property is omitted', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -745,12 +745,12 @@ describe('protocol tests', () => { it('should debounce calls when params is explicitly undefined', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -775,12 +775,12 @@ describe('protocol tests', () => { it('should send non-debounced notifications immediately and multiple times', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -813,12 +813,12 @@ describe('protocol tests', () => { it('should handle sequential batches of debounced notifications correctly', async () => { // ARRANGE - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1028,19 +1028,19 @@ describe('mergeCapabilities', () => { }); describe('Task-based execution', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let sendSpy: MockInstance; beforeEach(() => { transport = new MockTransport(); sendSpy = vi.spyOn(transport, 'send'); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1285,12 +1285,12 @@ describe('Task-based execution', () => { // rather than in _meta, and that task management is handled by tool implementors const mockTaskStore = createMockTaskStore(); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1357,12 +1357,12 @@ describe('Task-based execution', () => { } ); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1421,12 +1421,12 @@ describe('Task-based execution', () => { } ); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1470,12 +1470,12 @@ describe('Task-based execution', () => { onList: () => listedTasks.releaseLatch() }); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1506,12 +1506,12 @@ describe('Task-based execution', () => { const mockTaskStore = createMockTaskStore(); mockTaskStore.listTasks.mockRejectedValue(new Error('Invalid cursor: bad-cursor')); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1643,12 +1643,12 @@ describe('Task-based execution', () => { throw new Error('Task not found'); }); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1688,12 +1688,12 @@ describe('Task-based execution', () => { mockTaskStore.getTask.mockResolvedValue(null); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1739,12 +1739,12 @@ describe('Task-based execution', () => { mockTaskStore.updateTaskStatus.mockClear(); mockTaskStore.getTask.mockResolvedValue(completedTask); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1824,12 +1824,12 @@ describe('Task-based execution', () => { params: {} }); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1877,12 +1877,12 @@ describe('Task-based execution', () => { params: {} }); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1929,12 +1929,12 @@ describe('Task-based execution', () => { params: {} }); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -1969,12 +1969,12 @@ describe('Task-based execution', () => { params: {} }); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2017,12 +2017,12 @@ describe('Task-based execution', () => { await mockTaskStore.storeTaskResult(task.taskId, 'completed', testResult); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2063,12 +2063,12 @@ describe('Task-based execution', () => { it('should propagate related-task metadata to handler sendRequest and sendNotification', async () => { const mockTaskStore = createMockTaskStore(); - const serverProtocol = new (class extends Protocol> { + const serverProtocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2142,19 +2142,19 @@ describe('Task-based execution', () => { }); describe('Request Cancellation vs Task Cancellation', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let taskStore: TaskStore; beforeEach(() => { transport = new MockTransport(); taskStore = createMockTaskStore(); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2430,19 +2430,19 @@ describe('Request Cancellation vs Task Cancellation', () => { }); describe('Progress notification support for tasks', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let sendSpy: MockInstance; beforeEach(() => { transport = new MockTransport(); sendSpy = vi.spyOn(transport, 'send'); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2451,12 +2451,12 @@ describe('Progress notification support for tasks', () => { it('should maintain progress token association after CreateTaskResult is returned', async () => { const taskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2547,12 +2547,12 @@ describe('Progress notification support for tasks', () => { it('should stop progress notifications when task reaches terminal status (completed)', async () => { const taskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2686,12 +2686,12 @@ describe('Progress notification support for tasks', () => { it('should stop progress notifications when task reaches terminal status (failed)', async () => { const taskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2787,12 +2787,12 @@ describe('Progress notification support for tasks', () => { it('should stop progress notifications when task is cancelled', async () => { const taskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -2885,12 +2885,12 @@ describe('Progress notification support for tasks', () => { it('should use the same progressToken throughout task lifetime', async () => { const taskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -3157,12 +3157,12 @@ describe('Message interception for task-related notifications', () => { it('should queue notifications with io.modelcontextprotocol/related-task metadata', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3197,12 +3197,12 @@ describe('Message interception for task-related notifications', () => { it('should not queue notifications without related-task metadata', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3227,12 +3227,12 @@ describe('Message interception for task-related notifications', () => { it('should propagate queue overflow errors without failing the task', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3277,12 +3277,12 @@ describe('Message interception for task-related notifications', () => { it('should extract task ID correctly from metadata', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3313,12 +3313,12 @@ describe('Message interception for task-related notifications', () => { it('should preserve message order when queuing multiple notifications', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3358,12 +3358,12 @@ describe('Message interception for task-related requests', () => { it('should queue requests with io.modelcontextprotocol/related-task metadata', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3413,12 +3413,12 @@ describe('Message interception for task-related requests', () => { it('should not queue requests without related-task metadata', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3455,12 +3455,12 @@ describe('Message interception for task-related requests', () => { it('should store request resolver for response routing', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3511,12 +3511,12 @@ describe('Message interception for task-related requests', () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); const queue = new InMemoryTaskMessageQueue(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3579,12 +3579,12 @@ describe('Message interception for task-related requests', () => { it('should log error when resolver is missing for side-channeled request', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3658,12 +3658,12 @@ describe('Message interception for task-related requests', () => { it('should propagate queue overflow errors for requests without failing the task', async () => { const taskStore = createMockTaskStore(); const transport = new MockTransport(); - const server = new (class extends Protocol> { + const server = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} @@ -3715,19 +3715,19 @@ describe('Message interception for task-related requests', () => { }); describe('Message Interception', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let mockTaskStore: TaskStore & { [K in keyof TaskStore]: MockInstance }; beforeEach(() => { transport = new MockTransport(); mockTaskStore = createMockTaskStore(); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4236,19 +4236,19 @@ describe('Message Interception', () => { }); describe('Queue lifecycle management', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let mockTaskStore: TaskStore & { [K in keyof TaskStore]: MockInstance }; beforeEach(() => { transport = new MockTransport(); mockTaskStore = createMockTaskStore(); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4560,12 +4560,12 @@ describe('requestStream() method', () => { test('should yield result immediately for non-task requests', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4606,12 +4606,12 @@ describe('requestStream() method', () => { test('should yield error message on request failure', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4655,12 +4655,12 @@ describe('requestStream() method', () => { test('should handle cancellation via AbortSignal', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4696,12 +4696,12 @@ describe('requestStream() method', () => { describe('Error responses', () => { test('should yield error as terminal message for server error response', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4741,12 +4741,12 @@ describe('requestStream() method', () => { vi.useFakeTimers(); try { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4783,12 +4783,12 @@ describe('requestStream() method', () => { test('should yield error as terminal message for cancellation', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4819,12 +4819,12 @@ describe('requestStream() method', () => { test('should not yield any messages after error message', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4874,12 +4874,12 @@ describe('requestStream() method', () => { test('should yield error as terminal message for task failure', async () => { const transport = new MockTransport(); const mockTaskStore = createMockTaskStore(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4937,12 +4937,12 @@ describe('requestStream() method', () => { test('should yield error as terminal message for network error', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -4968,12 +4968,12 @@ describe('requestStream() method', () => { test('should ensure error is always the final message', async () => { const transport = new MockTransport(); - const protocol = new (class extends Protocol> { + const protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} @@ -5016,7 +5016,7 @@ describe('requestStream() method', () => { }); describe('Error handling for missing resolvers', () => { - let protocol: Protocol>; + let protocol: Protocol; let transport: MockTransport; let taskStore: TaskStore & { [K in keyof TaskStore]: MockInstance }; let taskMessageQueue: TaskMessageQueue; @@ -5027,12 +5027,12 @@ describe('Error handling for missing resolvers', () => { taskMessageQueue = new InMemoryTaskMessageQueue(); errorHandler = vi.fn(); - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(_method: string): void {} protected assertNotificationCapability(_method: string): void {} protected assertRequestHandlerCapability(_method: string): void {} protected assertTaskCapability(_method: string): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(_method: string): void {} diff --git a/packages/core/test/shared/protocolTransportHandling.test.ts b/packages/core/test/shared/protocolTransportHandling.test.ts index 889100e70..adc7e2234 100644 --- a/packages/core/test/shared/protocolTransportHandling.test.ts +++ b/packages/core/test/shared/protocolTransportHandling.test.ts @@ -29,17 +29,17 @@ class MockTransport implements Transport { } describe('Protocol transport handling bug', () => { - let protocol: Protocol>; + let protocol: Protocol; let transportA: MockTransport; let transportB: MockTransport; beforeEach(() => { - protocol = new (class extends Protocol> { + protocol = new (class extends Protocol { protected assertCapabilityForMethod(): void {} protected assertNotificationCapability(): void {} protected assertRequestHandlerCapability(): void {} protected assertTaskCapability(): void {} - protected buildContext(ctx: any) { + protected buildContext(ctx: BaseContext): BaseContext { return ctx; } protected assertTaskHandlerCapability(): void {} diff --git a/packages/server/src/experimental/tasks/interfaces.ts b/packages/server/src/experimental/tasks/interfaces.ts index 5e45ad86f..dee67ed3d 100644 --- a/packages/server/src/experimental/tasks/interfaces.ts +++ b/packages/server/src/experimental/tasks/interfaces.ts @@ -23,21 +23,19 @@ import type { BaseToolCallback } from '../../server/mcp.js'; * Handler for creating a task. * @experimental */ -export type CreateTaskRequestHandler = BaseToolCallback< - SendResultT, - CreateTaskServerContext, - Args ->; +export type CreateTaskRequestHandler< + ResultT extends Result, + Args extends AnySchema | undefined = undefined +> = BaseToolCallback; /** * Handler for task operations (get, getResult). * @experimental */ -export type TaskRequestHandler = BaseToolCallback< - SendResultT, - TaskServerContext, - Args ->; +export type TaskRequestHandler< + ResultT extends Result, + Args extends AnySchema | undefined = undefined +> = BaseToolCallback; /** * Interface for task-based tool handlers. diff --git a/packages/server/src/experimental/tasks/server.ts b/packages/server/src/experimental/tasks/server.ts index d9d887fe3..db53a3036 100644 --- a/packages/server/src/experimental/tasks/server.ts +++ b/packages/server/src/experimental/tasks/server.ts @@ -10,13 +10,11 @@ import type { CancelTaskResult, GetTaskResult, ListTasksResult, - Notification, Request, RequestOptions, - ResponseMessage, Result, - SchemaOutput, - ServerRequest + ResponseMessage, + SchemaOutput } from '@modelcontextprotocol/core'; import type { Server } from '../../server/server.js'; @@ -33,12 +31,8 @@ import type { Server } from '../../server/server.js'; * * @experimental */ -export class ExperimentalServerTasks< - RequestT extends Request = Request, - NotificationT extends Notification = Notification, - ResultT extends Result = Result -> { - constructor(private readonly _server: Server) {} +export class ExperimentalServerTasks { + constructor(private readonly _server: Server) {} /** * Sends a request and returns an AsyncGenerator that yields response messages. @@ -55,14 +49,14 @@ export class ExperimentalServerTasks< * @experimental */ requestStream( - request: ServerRequest | RequestT, + request: Request, resultSchema: T, options?: RequestOptions ): AsyncGenerator & Result>, void, void> { // Delegate to the server's underlying Protocol method type ServerWithRequestStream = { requestStream( - request: ServerRequest | RequestT, + request: Request, resultSchema: U, options?: RequestOptions ): AsyncGenerator & Result>, void, void>; diff --git a/packages/server/src/server/mcp.ts b/packages/server/src/server/mcp.ts index b7df78aec..e5b3eedd3 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -981,12 +981,12 @@ export class ResourceTemplate { } export type BaseToolCallback< - SendResultT extends Result, + ResultT extends Result, Ctx extends ServerContext, Args extends AnySchema | undefined > = Args extends AnySchema - ? (args: SchemaOutput, ctx: Ctx) => SendResultT | Promise - : (ctx: Ctx) => SendResultT | Promise; + ? (args: SchemaOutput, ctx: Ctx) => ResultT | Promise + : (ctx: Ctx) => ResultT | Promise; /** * Callback for a tool handler registered with Server.tool(). diff --git a/packages/server/src/server/server.ts b/packages/server/src/server/server.ts index ba9612ecb..b55f37492 100644 --- a/packages/server/src/server/server.ts +++ b/packages/server/src/server/server.ts @@ -18,15 +18,12 @@ import type { LoggingLevel, LoggingMessageNotification, MessageExtraInfo, - Notification, NotificationOptions, ProtocolOptions, - Request, RequestMethod, RequestOptions, RequestTypeMap, ResourceUpdatedNotification, - Result, ServerCapabilities, ServerContext, ServerNotification, @@ -87,43 +84,15 @@ export type ServerOptions = ProtocolOptions & { * * This server will automatically respond to the initialization flow as initiated from the client. * - * To use with custom types, extend the base Request/Notification/Result types and pass them as type parameters: - * - * ```typescript - * // Custom schemas - * const CustomRequestSchema = RequestSchema.extend({...}) - * const CustomNotificationSchema = NotificationSchema.extend({...}) - * const CustomResultSchema = ResultSchema.extend({...}) - * - * // Type aliases - * type CustomRequest = z.infer - * type CustomNotification = z.infer - * type CustomResult = z.infer - * - * // Create typed server - * const server = new Server({ - * name: "CustomServer", - * version: "1.0.0" - * }) - * ``` * @deprecated Use `McpServer` instead for the high-level API. Only use `Server` for advanced use cases. */ -export class Server< - RequestT extends Request = Request, - NotificationT extends Notification = Notification, - ResultT extends Result = Result -> extends Protocol< - ServerRequest | RequestT, - ServerNotification | NotificationT, - ServerResult | ResultT, - ServerContext -> { +export class Server extends Protocol { private _clientCapabilities?: ClientCapabilities; private _clientVersion?: Implementation; private _capabilities: ServerCapabilities; private _instructions?: string; private _jsonSchemaValidator: jsonSchemaValidator; - private _experimental?: { tasks: ExperimentalServerTasks }; + private _experimental?: { tasks: ExperimentalServerTasks }; /** * Callback for when initialization has fully completed (i.e., the client has sent an `initialized` notification). @@ -160,9 +129,9 @@ export class Server< } protected override buildContext( - ctx: BaseContext, + ctx: BaseContext, transportInfo?: MessageExtraInfo - ): ServerContext { + ): ServerContext { // Only create http when there's actual HTTP transport info or auth info const hasHttpInfo = ctx.http || transportInfo?.requestInfo || transportInfo?.closeSSEStream || transportInfo?.closeStandaloneSSEStream; @@ -192,7 +161,7 @@ export class Server< * * @experimental */ - get experimental(): { tasks: ExperimentalServerTasks } { + get experimental(): { tasks: ExperimentalServerTasks } { if (!this._experimental) { this._experimental = { tasks: new ExperimentalServerTasks(this) @@ -230,16 +199,10 @@ export class Server< */ public override setRequestHandler( method: M, - handler: ( - request: RequestTypeMap[M], - ctx: ServerContext - ) => ServerResult | ResultT | Promise + handler: (request: RequestTypeMap[M], ctx: ServerContext) => ServerResult | Promise ): void { if (method === 'tools/call') { - const wrappedHandler = async ( - request: RequestTypeMap[M], - ctx: ServerContext - ): Promise => { + const wrappedHandler = async (request: RequestTypeMap[M], ctx: ServerContext): Promise => { const validatedRequest = parseSchema(CallToolRequestSchema, request); if (!validatedRequest.success) { const errorMessage = @@ -283,7 +246,7 @@ export class Server< return super.setRequestHandler(method, handler); } - protected assertCapabilityForMethod(method: RequestT['method']): void { + protected assertCapabilityForMethod(method: string): void { switch (method as ServerRequest['method']) { case 'sampling/createMessage': { if (!this._clientCapabilities?.sampling) { @@ -316,7 +279,7 @@ export class Server< } } - protected assertNotificationCapability(method: (ServerNotification | NotificationT)['method']): void { + protected assertNotificationCapability(method: string): void { switch (method as ServerNotification['method']) { case 'notifications/message': { if (!this._capabilities.logging) { From 65852062b94d2c2436ed3ef1703071a64788f5f7 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 3 Feb 2026 19:33:58 +0000 Subject: [PATCH 2/4] refactor: tighten assertCapabilityForMethod/assertNotificationCapability to RequestMethod/NotificationMethod --- packages/client/src/client/client.ts | 4 ++-- packages/core/src/shared/protocol.ts | 8 ++++---- packages/server/src/server/server.ts | 11 +++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/client/src/client/client.ts b/packages/client/src/client/client.ts index 16439da67..042e9bc01 100644 --- a/packages/client/src/client/client.ts +++ b/packages/client/src/client/client.ts @@ -493,7 +493,7 @@ export class Client extends Protocol { return this._instructions; } - protected assertCapabilityForMethod(method: string): void { + protected assertCapabilityForMethod(method: RequestMethod): void { switch (method as ClientRequest['method']) { case 'logging/setLevel': { if (!this._serverCapabilities?.logging) { @@ -556,7 +556,7 @@ export class Client extends Protocol { } } - protected assertNotificationCapability(method: string): void { + protected assertNotificationCapability(method: NotificationMethod): void { switch (method as ClientNotification['method']) { case 'notifications/roots/list_changed': { if (!this._capabilities.roots?.listChanged) { diff --git a/packages/core/src/shared/protocol.ts b/packages/core/src/shared/protocol.ts index 6f7f1e260..0dab24a01 100644 --- a/packages/core/src/shared/protocol.ts +++ b/packages/core/src/shared/protocol.ts @@ -999,14 +999,14 @@ export abstract class Protocol { * * This should be implemented by subclasses. */ - protected abstract assertCapabilityForMethod(method: string): void; + protected abstract assertCapabilityForMethod(method: RequestMethod): void; /** * A method to check if a notification is supported by the local side, for the given method to be sent. * * This should be implemented by subclasses. */ - protected abstract assertNotificationCapability(method: string): void; + protected abstract assertNotificationCapability(method: NotificationMethod): void; /** * A method to check if a request handler is supported by the local side, for the given method to be handled. @@ -1173,7 +1173,7 @@ export abstract class Protocol { if (this._options?.enforceStrictCapabilities === true) { try { - this.assertCapabilityForMethod(request.method); + this.assertCapabilityForMethod(request.method as RequestMethod); // If task creation is requested, also check task capabilities if (task) { @@ -1366,7 +1366,7 @@ export abstract class Protocol { throw new SdkError(SdkErrorCode.NotConnected, 'Not connected'); } - this.assertNotificationCapability(notification.method); + this.assertNotificationCapability(notification.method as NotificationMethod); // Queue notification if related to a task const relatedTaskId = options?.relatedTask?.taskId; diff --git a/packages/server/src/server/server.ts b/packages/server/src/server/server.ts index b55f37492..594478791 100644 --- a/packages/server/src/server/server.ts +++ b/packages/server/src/server/server.ts @@ -18,6 +18,7 @@ import type { LoggingLevel, LoggingMessageNotification, MessageExtraInfo, + NotificationMethod, NotificationOptions, ProtocolOptions, RequestMethod, @@ -26,8 +27,6 @@ import type { ResourceUpdatedNotification, ServerCapabilities, ServerContext, - ServerNotification, - ServerRequest, ServerResult, ToolResultContent, ToolUseContent @@ -246,8 +245,8 @@ export class Server extends Protocol { return super.setRequestHandler(method, handler); } - protected assertCapabilityForMethod(method: string): void { - switch (method as ServerRequest['method']) { + protected assertCapabilityForMethod(method: RequestMethod): void { + switch (method) { case 'sampling/createMessage': { if (!this._clientCapabilities?.sampling) { throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Client does not support sampling (required for ${method})`); @@ -279,8 +278,8 @@ export class Server extends Protocol { } } - protected assertNotificationCapability(method: string): void { - switch (method as ServerNotification['method']) { + protected assertNotificationCapability(method: NotificationMethod): void { + switch (method) { case 'notifications/message': { if (!this._capabilities.logging) { throw new SdkError(SdkErrorCode.CapabilityNotSupported, `Server does not support logging (required for ${method})`); From efc90c9cceed9092ff2683eddb9722f5f34e3e40 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 3 Feb 2026 19:42:11 +0000 Subject: [PATCH 3/4] refactor: add ResultTypeMap for per-method result type inference in setRequestHandler Adds a ResultTypeMap that maps each method string to its specific result type, matching the existing RequestTypeMap pattern. This gives handlers correct return type inference per method, eliminating the need for explicit return type annotations and 'as const' assertions on literal values. ResultTypeMap is applied only on Server/Client overrides (not Protocol base), so wrappedHandlers keep natural return types and no casts are needed. --- examples/client/src/simpleStreamableHttp.ts | 3 +-- packages/client/src/client/client.ts | 3 ++- packages/core/src/types/types.ts | 22 +++++++++++++++++++++ packages/server/src/server/server.ts | 3 ++- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/examples/client/src/simpleStreamableHttp.ts b/examples/client/src/simpleStreamableHttp.ts index 4d2a6e4d6..87e6330c9 100644 --- a/examples/client/src/simpleStreamableHttp.ts +++ b/examples/client/src/simpleStreamableHttp.ts @@ -2,7 +2,6 @@ import { createInterface } from 'node:readline'; import type { CallToolRequest, - ElicitResult, GetPromptRequest, ListPromptsRequest, ListResourcesRequest, @@ -269,7 +268,7 @@ async function connect(url?: string): Promise { }; // Set up elicitation request handler with proper validation - client.setRequestHandler('elicitation/create', async (request): Promise => { + client.setRequestHandler('elicitation/create', async request => { if (request.params.mode !== 'form') { throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unsupported elicitation mode: ${request.params.mode}`); } diff --git a/packages/client/src/client/client.ts b/packages/client/src/client/client.ts index 042e9bc01..dad31dfa3 100644 --- a/packages/client/src/client/client.ts +++ b/packages/client/src/client/client.ts @@ -28,6 +28,7 @@ import type { RequestMethod, RequestOptions, RequestTypeMap, + ResultTypeMap, ServerCapabilities, SubscribeRequest, Tool, @@ -293,7 +294,7 @@ export class Client extends Protocol { */ public override setRequestHandler( method: M, - handler: (request: RequestTypeMap[M], ctx: ClientContext) => ClientResult | Promise + handler: (request: RequestTypeMap[M], ctx: ClientContext) => ResultTypeMap[M] | Promise ): void { if (method === 'elicitation/create') { const wrappedHandler = async (request: RequestTypeMap[M], ctx: ClientContext): Promise => { diff --git a/packages/core/src/types/types.ts b/packages/core/src/types/types.ts index 95638d4c7..f0e35181f 100644 --- a/packages/core/src/types/types.ts +++ b/packages/core/src/types/types.ts @@ -2615,6 +2615,28 @@ export type RequestMethod = ClientRequest['method'] | ServerRequest['method']; export type NotificationMethod = ClientNotification['method'] | ServerNotification['method']; export type RequestTypeMap = MethodToTypeMap; export type NotificationTypeMap = MethodToTypeMap; +export type ResultTypeMap = { + 'ping': EmptyResult; + 'initialize': InitializeResult; + 'completion/complete': CompleteResult; + 'logging/setLevel': EmptyResult; + 'prompts/get': GetPromptResult; + 'prompts/list': ListPromptsResult; + 'resources/list': ListResourcesResult; + 'resources/templates/list': ListResourceTemplatesResult; + 'resources/read': ReadResourceResult; + 'resources/subscribe': EmptyResult; + 'resources/unsubscribe': EmptyResult; + 'tools/call': CallToolResult | CreateTaskResult; + 'tools/list': ListToolsResult; + 'sampling/createMessage': CreateMessageResult | CreateMessageResultWithTools; + 'elicitation/create': ElicitResult; + 'roots/list': ListRootsResult; + 'tasks/get': GetTaskResult; + 'tasks/result': Result; + 'tasks/list': ListTasksResult; + 'tasks/cancel': CancelTaskResult; +}; /* Runtime schema lookup */ type RequestSchemaType = (typeof ClientRequestSchema.options)[number] | (typeof ServerRequestSchema.options)[number]; diff --git a/packages/server/src/server/server.ts b/packages/server/src/server/server.ts index 594478791..0bab07621 100644 --- a/packages/server/src/server/server.ts +++ b/packages/server/src/server/server.ts @@ -25,6 +25,7 @@ import type { RequestOptions, RequestTypeMap, ResourceUpdatedNotification, + ResultTypeMap, ServerCapabilities, ServerContext, ServerResult, @@ -198,7 +199,7 @@ export class Server extends Protocol { */ public override setRequestHandler( method: M, - handler: (request: RequestTypeMap[M], ctx: ServerContext) => ServerResult | Promise + handler: (request: RequestTypeMap[M], ctx: ServerContext) => ResultTypeMap[M] | Promise ): void { if (method === 'tools/call') { const wrappedHandler = async (request: RequestTypeMap[M], ctx: ServerContext): Promise => { From b438302a881222b92fe8d3cdbfd6a665fbdd3cd5 Mon Sep 17 00:00:00 2001 From: Felix Weinberger Date: Tue, 3 Feb 2026 20:19:52 +0000 Subject: [PATCH 4/4] style: fix prettier formatting --- packages/client/src/client/client.ts | 5 +---- packages/core/src/shared/protocol.ts | 4 ---- packages/core/src/types/types.ts | 4 ++-- .../src/experimental/tasks/interfaces.ts | 18 ++++++++++-------- .../server/src/experimental/tasks/server.ts | 2 +- packages/server/src/server/mcp.ts | 6 +----- packages/server/src/server/server.ts | 5 +---- 7 files changed, 16 insertions(+), 28 deletions(-) diff --git a/packages/client/src/client/client.ts b/packages/client/src/client/client.ts index dad31dfa3..7969b1ac7 100644 --- a/packages/client/src/client/client.ts +++ b/packages/client/src/client/client.ts @@ -224,10 +224,7 @@ export class Client extends Protocol { } } - protected override buildContext( - ctx: BaseContext, - _transportInfo?: MessageExtraInfo - ): ClientContext { + protected override buildContext(ctx: BaseContext, _transportInfo?: MessageExtraInfo): ClientContext { return ctx; } diff --git a/packages/core/src/shared/protocol.ts b/packages/core/src/shared/protocol.ts index 0dab24a01..dfa98a171 100644 --- a/packages/core/src/shared/protocol.ts +++ b/packages/core/src/shared/protocol.ts @@ -1320,7 +1320,6 @@ export abstract class Protocol { * @experimental Use `client.experimental.tasks.getTask()` to access this method. */ protected async getTask(params: GetTaskRequest['params'], options?: RequestOptions): Promise { - return this.request({ method: 'tasks/get', params }, GetTaskResultSchema, options); } @@ -1334,7 +1333,6 @@ export abstract class Protocol { resultSchema: T, options?: RequestOptions ): Promise> { - return this.request({ method: 'tasks/result', params }, resultSchema, options); } @@ -1344,7 +1342,6 @@ export abstract class Protocol { * @experimental Use `client.experimental.tasks.listTasks()` to access this method. */ protected async listTasks(params?: { cursor?: string }, options?: RequestOptions): Promise> { - return this.request({ method: 'tasks/list', params }, ListTasksResultSchema, options); } @@ -1354,7 +1351,6 @@ export abstract class Protocol { * @experimental Use `client.experimental.tasks.cancelTask()` to access this method. */ protected async cancelTask(params: { taskId: string }, options?: RequestOptions): Promise> { - return this.request({ method: 'tasks/cancel', params }, CancelTaskResultSchema, options); } diff --git a/packages/core/src/types/types.ts b/packages/core/src/types/types.ts index f0e35181f..2a79944b9 100644 --- a/packages/core/src/types/types.ts +++ b/packages/core/src/types/types.ts @@ -2616,8 +2616,8 @@ export type NotificationMethod = ClientNotification['method'] | ServerNotificati export type RequestTypeMap = MethodToTypeMap; export type NotificationTypeMap = MethodToTypeMap; export type ResultTypeMap = { - 'ping': EmptyResult; - 'initialize': InitializeResult; + ping: EmptyResult; + initialize: InitializeResult; 'completion/complete': CompleteResult; 'logging/setLevel': EmptyResult; 'prompts/get': GetPromptResult; diff --git a/packages/server/src/experimental/tasks/interfaces.ts b/packages/server/src/experimental/tasks/interfaces.ts index dee67ed3d..31a84a0f3 100644 --- a/packages/server/src/experimental/tasks/interfaces.ts +++ b/packages/server/src/experimental/tasks/interfaces.ts @@ -23,19 +23,21 @@ import type { BaseToolCallback } from '../../server/mcp.js'; * Handler for creating a task. * @experimental */ -export type CreateTaskRequestHandler< - ResultT extends Result, - Args extends AnySchema | undefined = undefined -> = BaseToolCallback; +export type CreateTaskRequestHandler = BaseToolCallback< + ResultT, + CreateTaskServerContext, + Args +>; /** * Handler for task operations (get, getResult). * @experimental */ -export type TaskRequestHandler< - ResultT extends Result, - Args extends AnySchema | undefined = undefined -> = BaseToolCallback; +export type TaskRequestHandler = BaseToolCallback< + ResultT, + TaskServerContext, + Args +>; /** * Interface for task-based tool handlers. diff --git a/packages/server/src/experimental/tasks/server.ts b/packages/server/src/experimental/tasks/server.ts index db53a3036..813f4cf28 100644 --- a/packages/server/src/experimental/tasks/server.ts +++ b/packages/server/src/experimental/tasks/server.ts @@ -12,8 +12,8 @@ import type { ListTasksResult, Request, RequestOptions, - Result, ResponseMessage, + Result, SchemaOutput } from '@modelcontextprotocol/core'; diff --git a/packages/server/src/server/mcp.ts b/packages/server/src/server/mcp.ts index e5b3eedd3..e77e55d97 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -980,11 +980,7 @@ export class ResourceTemplate { } } -export type BaseToolCallback< - ResultT extends Result, - Ctx extends ServerContext, - Args extends AnySchema | undefined -> = Args extends AnySchema +export type BaseToolCallback = Args extends AnySchema ? (args: SchemaOutput, ctx: Ctx) => ResultT | Promise : (ctx: Ctx) => ResultT | Promise; diff --git a/packages/server/src/server/server.ts b/packages/server/src/server/server.ts index 0bab07621..613766a58 100644 --- a/packages/server/src/server/server.ts +++ b/packages/server/src/server/server.ts @@ -128,10 +128,7 @@ export class Server extends Protocol { } } - protected override buildContext( - ctx: BaseContext, - transportInfo?: MessageExtraInfo - ): ServerContext { + protected override buildContext(ctx: BaseContext, transportInfo?: MessageExtraInfo): ServerContext { // Only create http when there's actual HTTP transport info or auth info const hasHttpInfo = ctx.http || transportInfo?.requestInfo || transportInfo?.closeSSEStream || transportInfo?.closeStandaloneSSEStream;