| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443 |
- import { AnySchema, AnyObjectSchema, SchemaOutput } from '../server/zod-compat.js';
- import { ClientCapabilities, GetTaskRequest, GetTaskPayloadRequest, ListTasksResultSchema, CancelTaskResultSchema, JSONRPCRequest, Progress, RequestId, Result, ServerCapabilities, RequestMeta, RequestInfo, GetTaskResult, TaskCreationParams, RelatedTaskMetadata, Task, Request, Notification } from '../types.js';
- import { Transport, TransportSendOptions } from './transport.js';
- import { AuthInfo } from '../server/auth/types.js';
- import { TaskStore, TaskMessageQueue, CreateTaskOptions } from '../experimental/tasks/interfaces.js';
- import { ResponseMessage } from './responseMessage.js';
- /**
- * Callback for progress notifications.
- */
- export type ProgressCallback = (progress: Progress) => void;
- /**
- * Additional initialization options.
- */
- export type ProtocolOptions = {
- /**
- * Whether to restrict emitted requests to only those that the remote side has indicated that they can handle, through their advertised capabilities.
- *
- * Note that this DOES NOT affect checking of _local_ side capabilities, as it is considered a logic error to mis-specify those.
- *
- * Currently this defaults to false, for backwards compatibility with SDK versions that did not advertise capabilities correctly. In future, this will default to true.
- */
- enforceStrictCapabilities?: boolean;
- /**
- * An array of notification method names that should be automatically debounced.
- * Any notifications with a method in this list will be coalesced if they
- * occur in the same tick of the event loop.
- * e.g., ['notifications/tools/list_changed']
- */
- debouncedNotificationMethods?: string[];
- /**
- * Optional task storage implementation. If provided, enables task-related request handlers
- * and provides task storage capabilities to request handlers.
- */
- taskStore?: TaskStore;
- /**
- * Optional task message queue implementation for managing server-initiated messages
- * that will be delivered through the tasks/result response stream.
- */
- taskMessageQueue?: TaskMessageQueue;
- /**
- * Default polling interval (in milliseconds) for task status checks when no pollInterval
- * is provided by the server. Defaults to 5000ms if not specified.
- */
- defaultTaskPollInterval?: number;
- /**
- * Maximum number of messages that can be queued per task for side-channel delivery.
- * If undefined, the queue size is unbounded.
- * When the limit is exceeded, the TaskMessageQueue implementation's enqueue() method
- * will throw an error. It's the implementation's responsibility to handle overflow
- * appropriately (e.g., by failing the task, dropping messages, etc.).
- */
- maxTaskQueueSize?: number;
- };
- /**
- * The default request timeout, in miliseconds.
- */
- export declare const DEFAULT_REQUEST_TIMEOUT_MSEC = 60000;
- /**
- * Options that can be given per request.
- */
- export type RequestOptions = {
- /**
- * If set, requests progress notifications from the remote end (if supported). When progress notifications are received, this callback will be invoked.
- *
- * For task-augmented requests: progress notifications continue after CreateTaskResult is returned and stop automatically when the task reaches a terminal status.
- */
- onprogress?: ProgressCallback;
- /**
- * Can be used to cancel an in-flight request. This will cause an AbortError to be raised from request().
- */
- signal?: AbortSignal;
- /**
- * A timeout (in milliseconds) for this request. If exceeded, an McpError with code `RequestTimeout` will be raised from request().
- *
- * If not specified, `DEFAULT_REQUEST_TIMEOUT_MSEC` will be used as the timeout.
- */
- timeout?: number;
- /**
- * If true, receiving a progress notification will reset the request timeout.
- * This is useful for long-running operations that send periodic progress updates.
- * Default: false
- */
- resetTimeoutOnProgress?: boolean;
- /**
- * Maximum total time (in milliseconds) to wait for a response.
- * If exceeded, an McpError with code `RequestTimeout` will be raised, regardless of progress notifications.
- * If not specified, there is no maximum total timeout.
- */
- maxTotalTimeout?: number;
- /**
- * If provided, augments the request with task creation parameters to enable call-now, fetch-later execution patterns.
- */
- task?: TaskCreationParams;
- /**
- * If provided, associates this request with a related task.
- */
- relatedTask?: RelatedTaskMetadata;
- } & TransportSendOptions;
- /**
- * Options that can be given per notification.
- */
- export type NotificationOptions = {
- /**
- * May be used to indicate to the transport which incoming request to associate this outgoing notification with.
- */
- relatedRequestId?: RequestId;
- /**
- * If provided, associates this notification with a related task.
- */
- relatedTask?: RelatedTaskMetadata;
- };
- /**
- * Options that can be given per request.
- */
- export type TaskRequestOptions = Omit<RequestOptions, 'relatedTask'>;
- /**
- * Request-scoped TaskStore interface.
- */
- export interface RequestTaskStore {
- /**
- * Creates a new task with the given creation parameters.
- * The implementation generates a unique taskId and createdAt timestamp.
- *
- * @param taskParams - The task creation parameters from the request
- * @returns The created task object
- */
- createTask(taskParams: CreateTaskOptions): Promise<Task>;
- /**
- * Gets the current status of a task.
- *
- * @param taskId - The task identifier
- * @returns The task object
- * @throws If the task does not exist
- */
- getTask(taskId: string): Promise<Task>;
- /**
- * Stores the result of a task and sets its final status.
- *
- * @param taskId - The task identifier
- * @param status - The final status: 'completed' for success, 'failed' for errors
- * @param result - The result to store
- */
- storeTaskResult(taskId: string, status: 'completed' | 'failed', result: Result): Promise<void>;
- /**
- * Retrieves the stored result of a task.
- *
- * @param taskId - The task identifier
- * @returns The stored result
- */
- getTaskResult(taskId: string): Promise<Result>;
- /**
- * Updates a task's status (e.g., to 'cancelled', 'failed', 'completed').
- *
- * @param taskId - The task identifier
- * @param status - The new status
- * @param statusMessage - Optional diagnostic message for failed tasks or other status information
- */
- updateTaskStatus(taskId: string, status: Task['status'], statusMessage?: string): Promise<void>;
- /**
- * Lists tasks, optionally starting from a pagination cursor.
- *
- * @param cursor - Optional cursor for pagination
- * @returns An object containing the tasks array and an optional nextCursor
- */
- listTasks(cursor?: string): Promise<{
- tasks: Task[];
- nextCursor?: string;
- }>;
- }
- /**
- * Extra data given to request handlers.
- */
- export type RequestHandlerExtra<SendRequestT extends Request, SendNotificationT extends Notification> = {
- /**
- * An abort signal used to communicate if the request was cancelled from the sender's side.
- */
- signal: AbortSignal;
- /**
- * Information about a validated access token, provided to request handlers.
- */
- authInfo?: AuthInfo;
- /**
- * The session ID from the transport, if available.
- */
- sessionId?: string;
- /**
- * Metadata from the original request.
- */
- _meta?: RequestMeta;
- /**
- * The JSON-RPC ID of the request being handled.
- * This can be useful for tracking or logging purposes.
- */
- requestId: RequestId;
- taskId?: string;
- taskStore?: RequestTaskStore;
- taskRequestedTtl?: number;
- /**
- * The original HTTP request.
- */
- requestInfo?: RequestInfo;
- /**
- * Sends a notification that relates to the current request being handled.
- *
- * This is used by certain transports to correctly associate related messages.
- */
- sendNotification: (notification: SendNotificationT) => Promise<void>;
- /**
- * Sends a request that relates to the current request being handled.
- *
- * This is used by certain transports to correctly associate related messages.
- */
- sendRequest: <U extends AnySchema>(request: SendRequestT, resultSchema: U, options?: TaskRequestOptions) => Promise<SchemaOutput<U>>;
- /**
- * Closes the SSE stream for this request, triggering client reconnection.
- * Only available when using StreamableHTTPServerTransport with eventStore configured.
- * Use this to implement polling behavior during long-running operations.
- */
- closeSSEStream?: () => void;
- /**
- * Closes the standalone GET SSE stream, triggering client reconnection.
- * Only available when using StreamableHTTPServerTransport with eventStore configured.
- * Use this to implement polling behavior for server-initiated notifications.
- */
- closeStandaloneSSEStream?: () => void;
- };
- /**
- * Implements MCP protocol framing on top of a pluggable transport, including
- * features like request/response linking, notifications, and progress.
- */
- export declare abstract class Protocol<SendRequestT extends Request, SendNotificationT extends Notification, SendResultT extends Result> {
- private _options?;
- private _transport?;
- private _requestMessageId;
- private _requestHandlers;
- private _requestHandlerAbortControllers;
- private _notificationHandlers;
- private _responseHandlers;
- private _progressHandlers;
- private _timeoutInfo;
- private _pendingDebouncedNotifications;
- private _taskProgressTokens;
- private _taskStore?;
- private _taskMessageQueue?;
- private _requestResolvers;
- /**
- * Callback for when the connection is closed for any reason.
- *
- * This is invoked when close() is called as well.
- */
- onclose?: () => void;
- /**
- * Callback for when an error occurs.
- *
- * Note that errors are not necessarily fatal; they are used for reporting any kind of exceptional condition out of band.
- */
- onerror?: (error: Error) => void;
- /**
- * A handler to invoke for any request types that do not have their own handler installed.
- */
- fallbackRequestHandler?: (request: JSONRPCRequest, extra: RequestHandlerExtra<SendRequestT, SendNotificationT>) => Promise<SendResultT>;
- /**
- * A handler to invoke for any notification types that do not have their own handler installed.
- */
- fallbackNotificationHandler?: (notification: Notification) => Promise<void>;
- constructor(_options?: ProtocolOptions | undefined);
- private _oncancel;
- private _setupTimeout;
- private _resetTimeout;
- private _cleanupTimeout;
- /**
- * Attaches to the given transport, starts it, and starts listening for messages.
- *
- * The Protocol object assumes ownership of the Transport, replacing any callbacks that have already been set, and expects that it is the only user of the Transport instance going forward.
- */
- connect(transport: Transport): Promise<void>;
- private _onclose;
- private _onerror;
- private _onnotification;
- private _onrequest;
- private _onprogress;
- private _onresponse;
- get transport(): Transport | undefined;
- /**
- * Closes the connection.
- */
- close(): Promise<void>;
- /**
- * A method to check if a capability is supported by the remote side, for the given method to be called.
- *
- * This should be implemented by subclasses.
- */
- protected abstract assertCapabilityForMethod(method: SendRequestT['method']): 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;
- /**
- * A method to check if a request handler is supported by the local side, for the given method to be handled.
- *
- * This should be implemented by subclasses.
- */
- protected abstract assertRequestHandlerCapability(method: string): void;
- /**
- * A method to check if task creation is supported for the given request method.
- *
- * This should be implemented by subclasses.
- */
- protected abstract assertTaskCapability(method: string): void;
- /**
- * A method to check if task handler is supported by the local side, for the given method to be handled.
- *
- * This should be implemented by subclasses.
- */
- protected abstract assertTaskHandlerCapability(method: string): void;
- /**
- * Sends a request and returns an AsyncGenerator that yields response messages.
- * The generator is guaranteed to end with either a 'result' or 'error' message.
- *
- * @example
- * ```typescript
- * const stream = protocol.requestStream(request, resultSchema, options);
- * for await (const message of stream) {
- * switch (message.type) {
- * case 'taskCreated':
- * console.log('Task created:', message.task.taskId);
- * break;
- * case 'taskStatus':
- * console.log('Task status:', message.task.status);
- * break;
- * case 'result':
- * console.log('Final result:', message.result);
- * break;
- * case 'error':
- * console.error('Error:', message.error);
- * break;
- * }
- * }
- * ```
- *
- * @experimental Use `client.experimental.tasks.requestStream()` to access this method.
- */
- protected requestStream<T extends AnySchema>(request: SendRequestT, resultSchema: T, options?: RequestOptions): AsyncGenerator<ResponseMessage<SchemaOutput<T>>, void, void>;
- /**
- * Sends a request and waits for a response.
- *
- * Do not use this method to emit notifications! Use notification() instead.
- */
- request<T extends AnySchema>(request: SendRequestT, resultSchema: T, options?: RequestOptions): Promise<SchemaOutput<T>>;
- /**
- * Gets the current status of a task.
- *
- * @experimental Use `client.experimental.tasks.getTask()` to access this method.
- */
- protected getTask(params: GetTaskRequest['params'], options?: RequestOptions): Promise<GetTaskResult>;
- /**
- * Retrieves the result of a completed task.
- *
- * @experimental Use `client.experimental.tasks.getTaskResult()` to access this method.
- */
- protected getTaskResult<T extends AnySchema>(params: GetTaskPayloadRequest['params'], resultSchema: T, options?: RequestOptions): Promise<SchemaOutput<T>>;
- /**
- * Lists tasks, optionally starting from a pagination cursor.
- *
- * @experimental Use `client.experimental.tasks.listTasks()` to access this method.
- */
- protected listTasks(params?: {
- cursor?: string;
- }, options?: RequestOptions): Promise<SchemaOutput<typeof ListTasksResultSchema>>;
- /**
- * Cancels a specific task.
- *
- * @experimental Use `client.experimental.tasks.cancelTask()` to access this method.
- */
- protected cancelTask(params: {
- taskId: string;
- }, options?: RequestOptions): Promise<SchemaOutput<typeof CancelTaskResultSchema>>;
- /**
- * Emits a notification, which is a one-way message that does not expect a response.
- */
- notification(notification: SendNotificationT, options?: NotificationOptions): Promise<void>;
- /**
- * Registers a handler to invoke when this protocol object receives a request with the given method.
- *
- * Note that this will replace any previous request handler for the same method.
- */
- setRequestHandler<T extends AnyObjectSchema>(requestSchema: T, handler: (request: SchemaOutput<T>, extra: RequestHandlerExtra<SendRequestT, SendNotificationT>) => SendResultT | Promise<SendResultT>): void;
- /**
- * Removes the request handler for the given method.
- */
- removeRequestHandler(method: string): void;
- /**
- * Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
- */
- assertCanSetRequestHandler(method: string): void;
- /**
- * Registers a handler to invoke when this protocol object receives a notification with the given method.
- *
- * Note that this will replace any previous notification handler for the same method.
- */
- setNotificationHandler<T extends AnyObjectSchema>(notificationSchema: T, handler: (notification: SchemaOutput<T>) => void | Promise<void>): void;
- /**
- * Removes the notification handler for the given method.
- */
- removeNotificationHandler(method: string): void;
- /**
- * Cleans up the progress handler associated with a task.
- * This should be called when a task reaches a terminal status.
- */
- private _cleanupTaskProgressHandler;
- /**
- * Enqueues a task-related message for side-channel delivery via tasks/result.
- * @param taskId The task ID to associate the message with
- * @param message The message to enqueue
- * @param sessionId Optional session ID for binding the operation to a specific session
- * @throws Error if taskStore is not configured or if enqueue fails (e.g., queue overflow)
- *
- * Note: If enqueue fails, it's the TaskMessageQueue implementation's responsibility to handle
- * the error appropriately (e.g., by failing the task, logging, etc.). The Protocol layer
- * simply propagates the error.
- */
- private _enqueueTaskMessage;
- /**
- * Clears the message queue for a task and rejects any pending request resolvers.
- * @param taskId The task ID whose queue should be cleared
- * @param sessionId Optional session ID for binding the operation to a specific session
- */
- private _clearTaskQueue;
- /**
- * Waits for a task update (new messages or status change) with abort signal support.
- * Uses polling to check for updates at the task's configured poll interval.
- * @param taskId The task ID to wait for
- * @param signal Abort signal to cancel the wait
- * @returns Promise that resolves when an update occurs or rejects if aborted
- */
- private _waitForTaskUpdate;
- private requestTaskStore;
- }
- export declare function mergeCapabilities(base: ServerCapabilities, additional: Partial<ServerCapabilities>): ServerCapabilities;
- export declare function mergeCapabilities(base: ClientCapabilities, additional: Partial<ClientCapabilities>): ClientCapabilities;
- //# sourceMappingURL=protocol.d.ts.map
|