diff --git a/examples/client/src/simpleStreamableHttp.ts b/examples/client/src/simpleStreamableHttp.ts index d4c51ffae..87e6330c9 100644 --- a/examples/client/src/simpleStreamableHttp.ts +++ b/examples/client/src/simpleStreamableHttp.ts @@ -293,7 +293,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 +357,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 +401,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..7969b1ac7 100644 --- a/packages/client/src/client/client.ts +++ b/packages/client/src/client/client.ts @@ -22,15 +22,13 @@ import type { ListToolsRequest, LoggingLevel, MessageExtraInfo, - Notification, NotificationMethod, ProtocolOptions, ReadResourceRequest, - Request, RequestMethod, RequestOptions, RequestTypeMap, - Result, + ResultTypeMap, ServerCapabilities, SubscribeRequest, Tool, @@ -193,36 +191,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 +201,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; @@ -254,10 +224,7 @@ export class Client< } } - protected override buildContext( - ctx: BaseContext, - _transportInfo?: MessageExtraInfo - ): ClientContext { + protected override buildContext(ctx: BaseContext, _transportInfo?: MessageExtraInfo): ClientContext { return ctx; } @@ -297,7 +264,7 @@ export class Client< * * @experimental */ - get experimental(): { tasks: ExperimentalClientTasks } { + get experimental(): { tasks: ExperimentalClientTasks } { if (!this._experimental) { this._experimental = { tasks: new ExperimentalClientTasks(this) @@ -324,16 +291,10 @@ export class Client< */ public override setRequestHandler( method: M, - handler: ( - request: RequestTypeMap[M], - ctx: ClientContext - ) => ClientResult | ResultT | Promise + handler: (request: RequestTypeMap[M], ctx: ClientContext) => ResultTypeMap[M] | 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 +364,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 +491,7 @@ export class Client< return this._instructions; } - protected assertCapabilityForMethod(method: RequestT['method']): void { + protected assertCapabilityForMethod(method: RequestMethod): void { switch (method as ClientRequest['method']) { case 'logging/setLevel': { if (!this._serverCapabilities?.logging) { @@ -596,7 +554,7 @@ export class Client< } } - protected assertNotificationCapability(method: NotificationT['method']): 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/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..dfa98a171 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: 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: SendNotificationT['method']): 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. @@ -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 @@ -1188,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) { @@ -1335,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 { - // @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 +1333,6 @@ 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 +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> { - // @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,19 +1351,18 @@ 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'); } - this.assertNotificationCapability(notification.method); + this.assertNotificationCapability(notification.method as NotificationMethod); // Queue notification if related to a task const relatedTaskId = options?.relatedTask?.taskId; @@ -1493,7 +1474,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 +1664,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 +1699,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/src/types/types.ts b/packages/core/src/types/types.ts index 95638d4c7..2a79944b9 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/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..31a84a0f3 100644 --- a/packages/server/src/experimental/tasks/interfaces.ts +++ b/packages/server/src/experimental/tasks/interfaces.ts @@ -23,8 +23,8 @@ import type { BaseToolCallback } from '../../server/mcp.js'; * Handler for creating a task. * @experimental */ -export type CreateTaskRequestHandler = BaseToolCallback< - SendResultT, +export type CreateTaskRequestHandler = BaseToolCallback< + ResultT, CreateTaskServerContext, Args >; @@ -33,8 +33,8 @@ export type CreateTaskRequestHandler = BaseToolCallback< - SendResultT, +export type TaskRequestHandler = BaseToolCallback< + ResultT, TaskServerContext, Args >; diff --git a/packages/server/src/experimental/tasks/server.ts b/packages/server/src/experimental/tasks/server.ts index d9d887fe3..813f4cf28 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 + 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..e77e55d97 100644 --- a/packages/server/src/server/mcp.ts +++ b/packages/server/src/server/mcp.ts @@ -980,13 +980,9 @@ export class ResourceTemplate { } } -export type BaseToolCallback< - SendResultT extends Result, - Ctx extends ServerContext, - Args extends AnySchema | undefined -> = Args extends AnySchema - ? (args: SchemaOutput, ctx: Ctx) => SendResultT | Promise - : (ctx: Ctx) => SendResultT | Promise; +export type BaseToolCallback = Args extends AnySchema + ? (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..613766a58 100644 --- a/packages/server/src/server/server.ts +++ b/packages/server/src/server/server.ts @@ -18,19 +18,16 @@ import type { LoggingLevel, LoggingMessageNotification, MessageExtraInfo, - Notification, + NotificationMethod, NotificationOptions, ProtocolOptions, - Request, RequestMethod, RequestOptions, RequestTypeMap, ResourceUpdatedNotification, - Result, + ResultTypeMap, ServerCapabilities, ServerContext, - ServerNotification, - ServerRequest, ServerResult, ToolResultContent, ToolUseContent @@ -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). @@ -159,10 +128,7 @@ export class Server< } } - 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; @@ -192,7 +158,7 @@ export class Server< * * @experimental */ - get experimental(): { tasks: ExperimentalServerTasks } { + get experimental(): { tasks: ExperimentalServerTasks } { if (!this._experimental) { this._experimental = { tasks: new ExperimentalServerTasks(this) @@ -230,16 +196,10 @@ export class Server< */ public override setRequestHandler( method: M, - handler: ( - request: RequestTypeMap[M], - ctx: ServerContext - ) => ServerResult | ResultT | Promise + handler: (request: RequestTypeMap[M], ctx: ServerContext) => ResultTypeMap[M] | 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,8 +243,8 @@ export class Server< return super.setRequestHandler(method, handler); } - protected assertCapabilityForMethod(method: RequestT['method']): 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})`); @@ -316,8 +276,8 @@ export class Server< } } - protected assertNotificationCapability(method: (ServerNotification | NotificationT)['method']): 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})`);