This commit is contained in:
2026-03-03 23:49:13 +01:00
parent 1946f96bf8
commit 0ae7f9963f
6446 changed files with 1032754 additions and 34 deletions

View File

@@ -0,0 +1,121 @@
/**
* Experimental client task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import type { Client } from '../../client/index.js';
import type { RequestOptions } from '../../shared/protocol.js';
import type { ResponseMessage } from '../../shared/responseMessage.js';
import type { AnyObjectSchema, SchemaOutput } from '../../server/zod-compat.js';
import type { CallToolRequest, ClientRequest, Notification, Request, Result } from '../../types.js';
import { CallToolResultSchema, type CompatibilityCallToolResultSchema } from '../../types.js';
import type { GetTaskResult, ListTasksResult, CancelTaskResult } from './types.js';
/**
* Experimental task features for MCP clients.
*
* Access via `client.experimental.tasks`:
* ```typescript
* const stream = client.experimental.tasks.callToolStream({ name: 'tool', arguments: {} });
* const task = await client.experimental.tasks.getTask(taskId);
* ```
*
* @experimental
*/
export declare class ExperimentalClientTasks<RequestT extends Request = Request, NotificationT extends Notification = Notification, ResultT extends Result = Result> {
private readonly _client;
constructor(_client: Client<RequestT, NotificationT, ResultT>);
/**
* Calls a tool and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to tool execution, allowing you to
* observe intermediate task status updates for long-running tool calls.
* Automatically validates structured output if the tool has an outputSchema.
*
* @example
* ```typescript
* const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
* for await (const message of stream) {
* switch (message.type) {
* case 'taskCreated':
* console.log('Tool execution started:', message.task.taskId);
* break;
* case 'taskStatus':
* console.log('Tool status:', message.task.status);
* break;
* case 'result':
* console.log('Tool result:', message.result);
* break;
* case 'error':
* console.error('Tool error:', message.error);
* break;
* }
* }
* ```
*
* @param params - Tool call parameters (name and arguments)
* @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
callToolStream<T extends typeof CallToolResultSchema | typeof CompatibilityCallToolResultSchema>(params: CallToolRequest['params'], resultSchema?: T, options?: RequestOptions): AsyncGenerator<ResponseMessage<SchemaOutput<T>>, void, void>;
/**
* Gets the current status of a task.
*
* @param taskId - The task identifier
* @param options - Optional request options
* @returns The task status
*
* @experimental
*/
getTask(taskId: string, options?: RequestOptions): Promise<GetTaskResult>;
/**
* Retrieves the result of a completed task.
*
* @param taskId - The task identifier
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options
* @returns The task result
*
* @experimental
*/
getTaskResult<T extends AnyObjectSchema>(taskId: string, resultSchema?: T, options?: RequestOptions): Promise<SchemaOutput<T>>;
/**
* Lists tasks with optional pagination.
*
* @param cursor - Optional pagination cursor
* @param options - Optional request options
* @returns List of tasks with optional next cursor
*
* @experimental
*/
listTasks(cursor?: string, options?: RequestOptions): Promise<ListTasksResult>;
/**
* Cancels a running task.
*
* @param taskId - The task identifier
* @param options - Optional request options
*
* @experimental
*/
cancelTask(taskId: string, options?: RequestOptions): Promise<CancelTaskResult>;
/**
* Sends a request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to request processing, allowing you to
* observe intermediate task status updates for task-augmented requests.
*
* @param request - The request to send
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
requestStream<T extends AnyObjectSchema>(request: ClientRequest | RequestT, resultSchema: T, options?: RequestOptions): AsyncGenerator<ResponseMessage<SchemaOutput<T>>, void, void>;
}
//# sourceMappingURL=client.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpG,OAAO,EAAE,oBAAoB,EAAE,KAAK,iCAAiC,EAAuB,MAAM,gBAAgB,CAAC;AAEnH,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgBnF;;;;;;;;;;GAUG;AACH,qBAAa,uBAAuB,CAChC,QAAQ,SAAS,OAAO,GAAG,OAAO,EAClC,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,OAAO,SAAS,MAAM,GAAG,MAAM;IAEnB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC;IAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACI,cAAc,CAAC,CAAC,SAAS,OAAO,oBAAoB,GAAG,OAAO,iCAAiC,EAClG,MAAM,EAAE,eAAe,CAAC,QAAQ,CAAC,EACjC,YAAY,GAAE,CAA6B,EAC3C,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;IAyE/D;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAM/E;;;;;;;;;OASG;IACG,aAAa,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAapI;;;;;;;;OAQG;IACG,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IASpF;;;;;;;OAOG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;IASrF;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,CAAC,SAAS,eAAe,EACnC,OAAO,EAAE,aAAa,GAAG,QAAQ,EACjC,YAAY,EAAE,CAAC,EACf,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;CAWlE"}

View File

@@ -0,0 +1,184 @@
/**
* Experimental client task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import { CallToolResultSchema, McpError, ErrorCode } from '../../types.js';
/**
* Experimental task features for MCP clients.
*
* Access via `client.experimental.tasks`:
* ```typescript
* const stream = client.experimental.tasks.callToolStream({ name: 'tool', arguments: {} });
* const task = await client.experimental.tasks.getTask(taskId);
* ```
*
* @experimental
*/
export class ExperimentalClientTasks {
constructor(_client) {
this._client = _client;
}
/**
* Calls a tool and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to tool execution, allowing you to
* observe intermediate task status updates for long-running tool calls.
* Automatically validates structured output if the tool has an outputSchema.
*
* @example
* ```typescript
* const stream = client.experimental.tasks.callToolStream({ name: 'myTool', arguments: {} });
* for await (const message of stream) {
* switch (message.type) {
* case 'taskCreated':
* console.log('Tool execution started:', message.task.taskId);
* break;
* case 'taskStatus':
* console.log('Tool status:', message.task.status);
* break;
* case 'result':
* console.log('Tool result:', message.result);
* break;
* case 'error':
* console.error('Tool error:', message.error);
* break;
* }
* }
* ```
*
* @param params - Tool call parameters (name and arguments)
* @param resultSchema - Zod schema for validating the result (defaults to CallToolResultSchema)
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
async *callToolStream(params, resultSchema = CallToolResultSchema, options) {
// Access Client's internal methods
const clientInternal = this._client;
// Add task creation parameters if server supports it and not explicitly provided
const optionsWithTask = {
...options,
// We check if the tool is known to be a task during auto-configuration, but assume
// the caller knows what they're doing if they pass this explicitly
task: options?.task ?? (clientInternal.isToolTask(params.name) ? {} : undefined)
};
const stream = clientInternal.requestStream({ method: 'tools/call', params }, resultSchema, optionsWithTask);
// Get the validator for this tool (if it has an output schema)
const validator = clientInternal.getToolOutputValidator(params.name);
// Iterate through the stream and validate the final result if needed
for await (const message of stream) {
// If this is a result message and the tool has an output schema, validate it
if (message.type === 'result' && validator) {
const result = message.result;
// If tool has outputSchema, it MUST return structuredContent (unless it's an error)
if (!result.structuredContent && !result.isError) {
yield {
type: 'error',
error: new McpError(ErrorCode.InvalidRequest, `Tool ${params.name} has an output schema but did not return structured content`)
};
return;
}
// Only validate structured content if present (not when there's an error)
if (result.structuredContent) {
try {
// Validate the structured content against the schema
const validationResult = validator(result.structuredContent);
if (!validationResult.valid) {
yield {
type: 'error',
error: new McpError(ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
};
return;
}
}
catch (error) {
if (error instanceof McpError) {
yield { type: 'error', error };
return;
}
yield {
type: 'error',
error: new McpError(ErrorCode.InvalidParams, `Failed to validate structured content: ${error instanceof Error ? error.message : String(error)}`)
};
return;
}
}
}
// Yield the message (either validated result or any other message type)
yield message;
}
}
/**
* Gets the current status of a task.
*
* @param taskId - The task identifier
* @param options - Optional request options
* @returns The task status
*
* @experimental
*/
async getTask(taskId, options) {
return this._client.getTask({ taskId }, options);
}
/**
* Retrieves the result of a completed task.
*
* @param taskId - The task identifier
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options
* @returns The task result
*
* @experimental
*/
async getTaskResult(taskId, resultSchema, options) {
// Delegate to the client's underlying Protocol method
return this._client.getTaskResult({ taskId }, resultSchema, options);
}
/**
* Lists tasks with optional pagination.
*
* @param cursor - Optional pagination cursor
* @param options - Optional request options
* @returns List of tasks with optional next cursor
*
* @experimental
*/
async listTasks(cursor, options) {
// Delegate to the client's underlying Protocol method
return this._client.listTasks(cursor ? { cursor } : undefined, options);
}
/**
* Cancels a running task.
*
* @param taskId - The task identifier
* @param options - Optional request options
*
* @experimental
*/
async cancelTask(taskId, options) {
// Delegate to the client's underlying Protocol method
return this._client.cancelTask({ taskId }, options);
}
/**
* Sends a request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to request processing, allowing you to
* observe intermediate task status updates for task-augmented requests.
*
* @param request - The request to send
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
requestStream(request, resultSchema, options) {
return this._client.requestStream(request, resultSchema, options);
}
}
//# sourceMappingURL=client.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/client.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,47 @@
/**
* Experimental task capability assertion helpers.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
/**
* Type representing the task requests capability structure.
* This is derived from ClientTasksCapability.requests and ServerTasksCapability.requests.
*/
interface TaskRequestsCapability {
tools?: {
call?: object;
};
sampling?: {
createMessage?: object;
};
elicitation?: {
create?: object;
};
}
/**
* Asserts that task creation is supported for tools/call.
* Used by Client.assertTaskCapability and Server.assertTaskHandlerCapability.
*
* @param requests - The task requests capability object
* @param method - The method being checked
* @param entityName - 'Server' or 'Client' for error messages
* @throws Error if the capability is not supported
*
* @experimental
*/
export declare function assertToolsCallTaskCapability(requests: TaskRequestsCapability | undefined, method: string, entityName: 'Server' | 'Client'): void;
/**
* Asserts that task creation is supported for sampling/createMessage or elicitation/create.
* Used by Server.assertTaskCapability and Client.assertTaskHandlerCapability.
*
* @param requests - The task requests capability object
* @param method - The method being checked
* @param entityName - 'Server' or 'Client' for error messages
* @throws Error if the capability is not supported
*
* @experimental
*/
export declare function assertClientRequestTaskCapability(requests: TaskRequestsCapability | undefined, method: string, entityName: 'Server' | 'Client'): void;
export {};
//# sourceMappingURL=helpers.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;GAGG;AACH,UAAU,sBAAsB;IAC5B,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtC,WAAW,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,6BAA6B,CACzC,QAAQ,EAAE,sBAAsB,GAAG,SAAS,EAC5C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAChC,IAAI,CAgBN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iCAAiC,CAC7C,QAAQ,EAAE,sBAAsB,GAAG,SAAS,EAC5C,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,QAAQ,GAAG,QAAQ,GAChC,IAAI,CAsBN"}

View File

@@ -0,0 +1,64 @@
/**
* Experimental task capability assertion helpers.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
/**
* Asserts that task creation is supported for tools/call.
* Used by Client.assertTaskCapability and Server.assertTaskHandlerCapability.
*
* @param requests - The task requests capability object
* @param method - The method being checked
* @param entityName - 'Server' or 'Client' for error messages
* @throws Error if the capability is not supported
*
* @experimental
*/
export function assertToolsCallTaskCapability(requests, method, entityName) {
if (!requests) {
throw new Error(`${entityName} does not support task creation (required for ${method})`);
}
switch (method) {
case 'tools/call':
if (!requests.tools?.call) {
throw new Error(`${entityName} does not support task creation for tools/call (required for ${method})`);
}
break;
default:
// Method doesn't support tasks, which is fine - no error
break;
}
}
/**
* Asserts that task creation is supported for sampling/createMessage or elicitation/create.
* Used by Server.assertTaskCapability and Client.assertTaskHandlerCapability.
*
* @param requests - The task requests capability object
* @param method - The method being checked
* @param entityName - 'Server' or 'Client' for error messages
* @throws Error if the capability is not supported
*
* @experimental
*/
export function assertClientRequestTaskCapability(requests, method, entityName) {
if (!requests) {
throw new Error(`${entityName} does not support task creation (required for ${method})`);
}
switch (method) {
case 'sampling/createMessage':
if (!requests.sampling?.createMessage) {
throw new Error(`${entityName} does not support task creation for sampling/createMessage (required for ${method})`);
}
break;
case 'elicitation/create':
if (!requests.elicitation?.create) {
throw new Error(`${entityName} does not support task creation for elicitation/create (required for ${method})`);
}
break;
default:
// Method doesn't support tasks, which is fine - no error
break;
}
}
//# sourceMappingURL=helpers.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,6BAA6B,CACzC,QAA4C,EAC5C,MAAc,EACd,UAA+B;IAE/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,iDAAiD,MAAM,GAAG,CAAC,CAAC;IAC7F,CAAC;IAED,QAAQ,MAAM,EAAE,CAAC;QACb,KAAK,YAAY;YACb,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;gBACxB,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,gEAAgE,MAAM,GAAG,CAAC,CAAC;YAC5G,CAAC;YACD,MAAM;QAEV;YACI,yDAAyD;YACzD,MAAM;IACd,CAAC;AACL,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,iCAAiC,CAC7C,QAA4C,EAC5C,MAAc,EACd,UAA+B;IAE/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,iDAAiD,MAAM,GAAG,CAAC,CAAC;IAC7F,CAAC;IAED,QAAQ,MAAM,EAAE,CAAC;QACb,KAAK,wBAAwB;YACzB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,EAAE,CAAC;gBACpC,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,4EAA4E,MAAM,GAAG,CAAC,CAAC;YACxH,CAAC;YACD,MAAM;QAEV,KAAK,oBAAoB;YACrB,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,wEAAwE,MAAM,GAAG,CAAC,CAAC;YACpH,CAAC;YACD,MAAM;QAEV;YACI,yDAAyD;YACzD,MAAM;IACd,CAAC;AACL,CAAC"}

View File

@@ -0,0 +1,16 @@
/**
* Experimental task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
export * from './types.js';
export * from './interfaces.js';
export * from './helpers.js';
export * from './client.js';
export * from './server.js';
export * from './mcp-server.js';
export * from './stores/in-memory.js';
export type { ResponseMessage, TaskStatusMessage, TaskCreatedMessage, ResultMessage, ErrorMessage, BaseResponseMessage } from '../../shared/responseMessage.js';
export { takeResult, toArrayAsync } from '../../shared/responseMessage.js';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,cAAc,CAAC;AAG7B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,uBAAuB,CAAC;AAGtC,YAAY,EACR,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,aAAa,EACb,YAAY,EACZ,mBAAmB,EACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC"}

View File

@@ -0,0 +1,20 @@
/**
* Experimental task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
// Re-export spec types for convenience
export * from './types.js';
// SDK implementation interfaces
export * from './interfaces.js';
// Assertion helpers
export * from './helpers.js';
// Wrapper classes
export * from './client.js';
export * from './server.js';
export * from './mcp-server.js';
// Store implementations
export * from './stores/in-memory.js';
export { takeResult, toArrayAsync } from '../../shared/responseMessage.js';
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,uCAAuC;AACvC,cAAc,YAAY,CAAC;AAE3B,gCAAgC;AAChC,cAAc,iBAAiB,CAAC;AAEhC,oBAAoB;AACpB,cAAc,cAAc,CAAC;AAE7B,kBAAkB;AAClB,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAEhC,wBAAwB;AACxB,cAAc,uBAAuB,CAAC;AAWtC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC"}

View File

@@ -0,0 +1,232 @@
/**
* Experimental task interfaces for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*/
import { Task, RequestId, Result, JSONRPCRequest, JSONRPCNotification, JSONRPCResultResponse, JSONRPCErrorResponse, ServerRequest, ServerNotification, CallToolResult, GetTaskResult, ToolExecution, Request } from '../../types.js';
import { CreateTaskResult } from './types.js';
import type { RequestHandlerExtra, RequestTaskStore } from '../../shared/protocol.js';
import type { ZodRawShapeCompat, AnySchema, ShapeOutput } from '../../server/zod-compat.js';
/**
* Extended handler extra with task store for task creation.
* @experimental
*/
export interface CreateTaskRequestHandlerExtra extends RequestHandlerExtra<ServerRequest, ServerNotification> {
taskStore: RequestTaskStore;
}
/**
* Extended handler extra with task ID and store for task operations.
* @experimental
*/
export interface TaskRequestHandlerExtra extends RequestHandlerExtra<ServerRequest, ServerNotification> {
taskId: string;
taskStore: RequestTaskStore;
}
/**
* Base callback type for tool handlers.
* @experimental
*/
export type BaseToolCallback<SendResultT extends Result, ExtraT extends RequestHandlerExtra<ServerRequest, ServerNotification>, Args extends undefined | ZodRawShapeCompat | AnySchema = undefined> = Args extends ZodRawShapeCompat ? (args: ShapeOutput<Args>, extra: ExtraT) => SendResultT | Promise<SendResultT> : Args extends AnySchema ? (args: unknown, extra: ExtraT) => SendResultT | Promise<SendResultT> : (extra: ExtraT) => SendResultT | Promise<SendResultT>;
/**
* Handler for creating a task.
* @experimental
*/
export type CreateTaskRequestHandler<SendResultT extends Result, Args extends undefined | ZodRawShapeCompat | AnySchema = undefined> = BaseToolCallback<SendResultT, CreateTaskRequestHandlerExtra, Args>;
/**
* Handler for task operations (get, getResult).
* @experimental
*/
export type TaskRequestHandler<SendResultT extends Result, Args extends undefined | ZodRawShapeCompat | AnySchema = undefined> = BaseToolCallback<SendResultT, TaskRequestHandlerExtra, Args>;
/**
* Interface for task-based tool handlers.
* @experimental
*/
export interface ToolTaskHandler<Args extends undefined | ZodRawShapeCompat | AnySchema = undefined> {
createTask: CreateTaskRequestHandler<CreateTaskResult, Args>;
getTask: TaskRequestHandler<GetTaskResult, Args>;
getTaskResult: TaskRequestHandler<CallToolResult, Args>;
}
/**
* Task-specific execution configuration.
* taskSupport cannot be 'forbidden' for task-based tools.
* @experimental
*/
export type TaskToolExecution<TaskSupport = ToolExecution['taskSupport']> = Omit<ToolExecution, 'taskSupport'> & {
taskSupport: TaskSupport extends 'forbidden' | undefined ? never : TaskSupport;
};
/**
* Represents a message queued for side-channel delivery via tasks/result.
*
* This is a serializable data structure that can be stored in external systems.
* All fields are JSON-serializable.
*/
export type QueuedMessage = QueuedRequest | QueuedNotification | QueuedResponse | QueuedError;
export interface BaseQueuedMessage {
/** Type of message */
type: string;
/** When the message was queued (milliseconds since epoch) */
timestamp: number;
}
export interface QueuedRequest extends BaseQueuedMessage {
type: 'request';
/** The actual JSONRPC request */
message: JSONRPCRequest;
}
export interface QueuedNotification extends BaseQueuedMessage {
type: 'notification';
/** The actual JSONRPC notification */
message: JSONRPCNotification;
}
export interface QueuedResponse extends BaseQueuedMessage {
type: 'response';
/** The actual JSONRPC response */
message: JSONRPCResultResponse;
}
export interface QueuedError extends BaseQueuedMessage {
type: 'error';
/** The actual JSONRPC error */
message: JSONRPCErrorResponse;
}
/**
* Interface for managing per-task FIFO message queues.
*
* Similar to TaskStore, this allows pluggable queue implementations
* (in-memory, Redis, other distributed queues, etc.).
*
* Each method accepts taskId and optional sessionId parameters to enable
* a single queue instance to manage messages for multiple tasks, with
* isolation based on task ID and session ID.
*
* All methods are async to support external storage implementations.
* All data in QueuedMessage must be JSON-serializable.
*
* @experimental
*/
export interface TaskMessageQueue {
/**
* Adds a message to the end of the queue for a specific task.
* Atomically checks queue size and throws if maxSize would be exceeded.
* @param taskId The task identifier
* @param message The message to enqueue
* @param sessionId Optional session ID for binding the operation to a specific session
* @param maxSize Optional maximum queue size - if specified and queue is full, throws an error
* @throws Error if maxSize is specified and would be exceeded
*/
enqueue(taskId: string, message: QueuedMessage, sessionId?: string, maxSize?: number): Promise<void>;
/**
* Removes and returns the first message from the queue for a specific task.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns The first message, or undefined if the queue is empty
*/
dequeue(taskId: string, sessionId?: string): Promise<QueuedMessage | undefined>;
/**
* Removes and returns all messages from the queue for a specific task.
* Used when tasks are cancelled or failed to clean up pending messages.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns Array of all messages that were in the queue
*/
dequeueAll(taskId: string, sessionId?: string): Promise<QueuedMessage[]>;
}
/**
* Task creation options.
* @experimental
*/
export interface CreateTaskOptions {
/**
* Time in milliseconds to keep task results available after completion.
* If null, the task has unlimited lifetime until manually cleaned up.
*/
ttl?: number | null;
/**
* Time in milliseconds to wait between task status requests.
*/
pollInterval?: number;
/**
* Additional context to pass to the task store.
*/
context?: Record<string, unknown>;
}
/**
* Interface for storing and retrieving task state and results.
*
* Similar to Transport, this allows pluggable task storage implementations
* (in-memory, database, distributed cache, etc.).
*
* @experimental
*/
export interface TaskStore {
/**
* Creates a new task with the given creation parameters and original request.
* The implementation must generate a unique taskId and createdAt timestamp.
*
* TTL Management:
* - The implementation receives the TTL suggested by the requestor via taskParams.ttl
* - The implementation MAY override the requested TTL (e.g., to enforce limits)
* - The actual TTL used MUST be returned in the Task object
* - Null TTL indicates unlimited task lifetime (no automatic cleanup)
* - Cleanup SHOULD occur automatically after TTL expires, regardless of task status
*
* @param taskParams - The task creation parameters from the request (ttl, pollInterval)
* @param requestId - The JSON-RPC request ID
* @param request - The original request that triggered task creation
* @param sessionId - Optional session ID for binding the task to a specific session
* @returns The created task object
*/
createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: Request, sessionId?: string): Promise<Task>;
/**
* Gets the current status of a task.
*
* @param taskId - The task identifier
* @param sessionId - Optional session ID for binding the query to a specific session
* @returns The task object, or null if it does not exist
*/
getTask(taskId: string, sessionId?: string): Promise<Task | null>;
/**
* 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
* @param sessionId - Optional session ID for binding the operation to a specific session
*/
storeTaskResult(taskId: string, status: 'completed' | 'failed', result: Result, sessionId?: string): Promise<void>;
/**
* Retrieves the stored result of a task.
*
* @param taskId - The task identifier
* @param sessionId - Optional session ID for binding the query to a specific session
* @returns The stored result
*/
getTaskResult(taskId: string, sessionId?: 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
* @param sessionId - Optional session ID for binding the operation to a specific session
*/
updateTaskStatus(taskId: string, status: Task['status'], statusMessage?: string, sessionId?: string): Promise<void>;
/**
* Lists tasks, optionally starting from a pagination cursor.
*
* @param cursor - Optional cursor for pagination
* @param sessionId - Optional session ID for binding the query to a specific session
* @returns An object containing the tasks array and an optional nextCursor
*/
listTasks(cursor?: string, sessionId?: string): Promise<{
tasks: Task[];
nextCursor?: string;
}>;
}
/**
* Checks if a task status represents a terminal state.
* Terminal states are those where the task has finished and will not change.
*
* @param status - The task status to check
* @returns True if the status is terminal (completed, failed, or cancelled)
* @experimental
*/
export declare function isTerminal(status: Task['status']): boolean;
//# sourceMappingURL=interfaces.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/interfaces.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,16 @@
/**
* Experimental task interfaces for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*/
/**
* Checks if a task status represents a terminal state.
* Terminal states are those where the task has finished and will not change.
*
* @param status - The task status to check
* @returns True if the status is terminal (completed, failed, or cancelled)
* @experimental
*/
export function isTerminal(status) {
return status === 'completed' || status === 'failed' || status === 'cancelled';
}
//# sourceMappingURL=interfaces.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/interfaces.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmRH;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,MAAsB;IAC7C,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,WAAW,CAAC;AACnF,CAAC"}

View File

@@ -0,0 +1,77 @@
/**
* Experimental McpServer task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import type { McpServer, RegisteredTool } from '../../server/mcp.js';
import type { ZodRawShapeCompat, AnySchema } from '../../server/zod-compat.js';
import type { ToolAnnotations } from '../../types.js';
import type { ToolTaskHandler, TaskToolExecution } from './interfaces.js';
/**
* Experimental task features for McpServer.
*
* Access via `server.experimental.tasks`:
* ```typescript
* server.experimental.tasks.registerToolTask('long-running', config, handler);
* ```
*
* @experimental
*/
export declare class ExperimentalMcpServerTasks {
private readonly _mcpServer;
constructor(_mcpServer: McpServer);
/**
* Registers a task-based tool with a config object and handler.
*
* Task-based tools support long-running operations that can be polled for status
* and results. The handler must implement `createTask`, `getTask`, and `getTaskResult`
* methods.
*
* @example
* ```typescript
* server.experimental.tasks.registerToolTask('long-computation', {
* description: 'Performs a long computation',
* inputSchema: { input: z.string() },
* execution: { taskSupport: 'required' }
* }, {
* createTask: async (args, extra) => {
* const task = await extra.taskStore.createTask({ ttl: 300000 });
* startBackgroundWork(task.taskId, args);
* return { task };
* },
* getTask: async (args, extra) => {
* return extra.taskStore.getTask(extra.taskId);
* },
* getTaskResult: async (args, extra) => {
* return extra.taskStore.getTaskResult(extra.taskId);
* }
* });
* ```
*
* @param name - The tool name
* @param config - Tool configuration (description, schemas, etc.)
* @param handler - Task handler with createTask, getTask, getTaskResult methods
* @returns RegisteredTool for managing the tool's lifecycle
*
* @experimental
*/
registerToolTask<OutputArgs extends undefined | ZodRawShapeCompat | AnySchema>(name: string, config: {
title?: string;
description?: string;
outputSchema?: OutputArgs;
annotations?: ToolAnnotations;
execution?: TaskToolExecution;
_meta?: Record<string, unknown>;
}, handler: ToolTaskHandler<undefined>): RegisteredTool;
registerToolTask<InputArgs extends ZodRawShapeCompat | AnySchema, OutputArgs extends undefined | ZodRawShapeCompat | AnySchema>(name: string, config: {
title?: string;
description?: string;
inputSchema: InputArgs;
outputSchema?: OutputArgs;
annotations?: ToolAnnotations;
execution?: TaskToolExecution;
_meta?: Record<string, unknown>;
}, handler: ToolTaskHandler<InputArgs>): RegisteredTool;
}
//# sourceMappingURL=mcp-server.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAkB,MAAM,qBAAqB,CAAC;AACrF,OAAO,KAAK,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC/E,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAoB1E;;;;;;;;;GASG;AACH,qBAAa,0BAA0B;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,SAAS;IAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACH,gBAAgB,CAAC,UAAU,SAAS,SAAS,GAAG,iBAAiB,GAAG,SAAS,EACzE,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,UAAU,CAAC;QAC1B,WAAW,CAAC,EAAE,eAAe,CAAC;QAC9B,SAAS,CAAC,EAAE,iBAAiB,CAAC;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,EACD,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,GACpC,cAAc;IAEjB,gBAAgB,CAAC,SAAS,SAAS,iBAAiB,GAAG,SAAS,EAAE,UAAU,SAAS,SAAS,GAAG,iBAAiB,GAAG,SAAS,EAC1H,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,SAAS,CAAC;QACvB,YAAY,CAAC,EAAE,UAAU,CAAC;QAC1B,WAAW,CAAC,EAAE,eAAe,CAAC;QAC9B,SAAS,CAAC,EAAE,iBAAiB,CAAC;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACnC,EACD,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,GACpC,cAAc;CAsCpB"}

View File

@@ -0,0 +1,32 @@
/**
* Experimental McpServer task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
/**
* Experimental task features for McpServer.
*
* Access via `server.experimental.tasks`:
* ```typescript
* server.experimental.tasks.registerToolTask('long-running', config, handler);
* ```
*
* @experimental
*/
export class ExperimentalMcpServerTasks {
constructor(_mcpServer) {
this._mcpServer = _mcpServer;
}
registerToolTask(name, config, handler) {
// Validate that taskSupport is not 'forbidden' for task-based tools
const execution = { taskSupport: 'required', ...config.execution };
if (execution.taskSupport === 'forbidden') {
throw new Error(`Cannot register task-based tool '${name}' with taskSupport 'forbidden'. Use registerTool() instead.`);
}
// Access McpServer's internal _createRegisteredTool method
const mcpServerInternal = this._mcpServer;
return mcpServerInternal._createRegisteredTool(name, config.title, config.description, config.inputSchema, config.outputSchema, config.annotations, execution, config._meta, handler);
}
}
//# sourceMappingURL=mcp-server.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyBH;;;;;;;;;GASG;AACH,MAAM,OAAO,0BAA0B;IACnC,YAA6B,UAAqB;QAArB,eAAU,GAAV,UAAU,CAAW;IAAG,CAAC;IAgEtD,gBAAgB,CAIZ,IAAY,EACZ,MAQC,EACD,OAAmC;QAEnC,oEAAoE;QACpE,MAAM,SAAS,GAAkB,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;QAClF,IAAI,SAAS,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,oCAAoC,IAAI,6DAA6D,CAAC,CAAC;QAC3H,CAAC;QAED,2DAA2D;QAC3D,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAA0C,CAAC;QAC1E,OAAO,iBAAiB,CAAC,qBAAqB,CAC1C,IAAI,EACJ,MAAM,CAAC,KAAK,EACZ,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,WAAW,EAClB,MAAM,CAAC,YAAY,EACnB,MAAM,CAAC,WAAW,EAClB,SAAS,EACT,MAAM,CAAC,KAAK,EACZ,OAAwD,CAC3D,CAAC;IACN,CAAC;CACJ"}

View File

@@ -0,0 +1,170 @@
/**
* Experimental server task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import type { Server } from '../../server/index.js';
import type { RequestOptions } from '../../shared/protocol.js';
import type { ResponseMessage } from '../../shared/responseMessage.js';
import type { AnySchema, SchemaOutput } from '../../server/zod-compat.js';
import type { ServerRequest, Notification, Request, Result, GetTaskResult, ListTasksResult, CancelTaskResult, CreateMessageRequestParams, CreateMessageResult, ElicitRequestFormParams, ElicitRequestURLParams, ElicitResult } from '../../types.js';
/**
* Experimental task features for low-level MCP servers.
*
* Access via `server.experimental.tasks`:
* ```typescript
* const stream = server.experimental.tasks.requestStream(request, schema, options);
* ```
*
* For high-level server usage with task-based tools, use `McpServer.experimental.tasks` instead.
*
* @experimental
*/
export declare class ExperimentalServerTasks<RequestT extends Request = Request, NotificationT extends Notification = Notification, ResultT extends Result = Result> {
private readonly _server;
constructor(_server: Server<RequestT, NotificationT, ResultT>);
/**
* Sends a request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to request processing, allowing you to
* observe intermediate task status updates for task-augmented requests.
*
* @param request - The request to send
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
requestStream<T extends AnySchema>(request: ServerRequest | RequestT, resultSchema: T, options?: RequestOptions): AsyncGenerator<ResponseMessage<SchemaOutput<T>>, void, void>;
/**
* Sends a sampling request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
* before the final result.
*
* @example
* ```typescript
* const stream = server.experimental.tasks.createMessageStream({
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
* maxTokens: 100
* }, {
* onprogress: (progress) => {
* // Handle streaming tokens via progress notifications
* console.log('Progress:', progress.message);
* }
* });
*
* 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;
* }
* }
* ```
*
* @param params - The sampling request parameters
* @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
createMessageStream(params: CreateMessageRequestParams, options?: RequestOptions): AsyncGenerator<ResponseMessage<CreateMessageResult>, void, void>;
/**
* Sends an elicitation request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
* and 'taskStatus' messages before the final result.
*
* @example
* ```typescript
* const stream = server.experimental.tasks.elicitInputStream({
* mode: 'url',
* message: 'Please authenticate',
* elicitationId: 'auth-123',
* url: 'https://example.com/auth'
* }, {
* task: { ttl: 300000 } // Task-augmented for long-running auth flow
* });
*
* 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('User action:', message.result.action);
* break;
* case 'error':
* console.error('Error:', message.error);
* break;
* }
* }
* ```
*
* @param params - The elicitation request parameters
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
elicitInputStream(params: ElicitRequestFormParams | ElicitRequestURLParams, options?: RequestOptions): AsyncGenerator<ResponseMessage<ElicitResult>, void, void>;
/**
* Gets the current status of a task.
*
* @param taskId - The task identifier
* @param options - Optional request options
* @returns The task status
*
* @experimental
*/
getTask(taskId: string, options?: RequestOptions): Promise<GetTaskResult>;
/**
* Retrieves the result of a completed task.
*
* @param taskId - The task identifier
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options
* @returns The task result
*
* @experimental
*/
getTaskResult<T extends AnySchema>(taskId: string, resultSchema?: T, options?: RequestOptions): Promise<SchemaOutput<T>>;
/**
* Lists tasks with optional pagination.
*
* @param cursor - Optional pagination cursor
* @param options - Optional request options
* @returns List of tasks with optional next cursor
*
* @experimental
*/
listTasks(cursor?: string, options?: RequestOptions): Promise<ListTasksResult>;
/**
* Cancels a running task.
*
* @param taskId - The task identifier
* @param options - Optional request options
*
* @experimental
*/
cancelTask(taskId: string, options?: RequestOptions): Promise<CancelTaskResult>;
}
//# sourceMappingURL=server.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,KAAK,EACR,aAAa,EACb,YAAY,EACZ,OAAO,EACP,MAAM,EACN,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,0BAA0B,EAC1B,mBAAmB,EACnB,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACf,MAAM,gBAAgB,CAAC;AAGxB;;;;;;;;;;;GAWG;AACH,qBAAa,uBAAuB,CAChC,QAAQ,SAAS,OAAO,GAAG,OAAO,EAClC,aAAa,SAAS,YAAY,GAAG,YAAY,EACjD,OAAO,SAAS,MAAM,GAAG,MAAM;IAEnB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,aAAa,EAAE,OAAO,CAAC;IAE9E;;;;;;;;;;;;;OAaG;IACH,aAAa,CAAC,CAAC,SAAS,SAAS,EAC7B,OAAO,EAAE,aAAa,GAAG,QAAQ,EACjC,YAAY,EAAE,CAAC,EACf,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;IAY/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACH,mBAAmB,CACf,MAAM,EAAE,0BAA0B,EAClC,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc,CAAC,eAAe,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;IAuDnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAyCG;IACH,iBAAiB,CACb,MAAM,EAAE,uBAAuB,GAAG,sBAAsB,EACxD,OAAO,CAAC,EAAE,cAAc,GACzB,cAAc,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC;IAoC5D;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAK/E;;;;;;;;;OASG;IACG,aAAa,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAY9H;;;;;;;;OAQG;IACG,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,eAAe,CAAC;IAQpF;;;;;;;OAOG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAOxF"}

View File

@@ -0,0 +1,246 @@
/**
* Experimental server task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import { CreateMessageResultSchema, ElicitResultSchema } from '../../types.js';
/**
* Experimental task features for low-level MCP servers.
*
* Access via `server.experimental.tasks`:
* ```typescript
* const stream = server.experimental.tasks.requestStream(request, schema, options);
* ```
*
* For high-level server usage with task-based tools, use `McpServer.experimental.tasks` instead.
*
* @experimental
*/
export class ExperimentalServerTasks {
constructor(_server) {
this._server = _server;
}
/**
* Sends a request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* This method provides streaming access to request processing, allowing you to
* observe intermediate task status updates for task-augmented requests.
*
* @param request - The request to send
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
requestStream(request, resultSchema, options) {
return this._server.requestStream(request, resultSchema, options);
}
/**
* Sends a sampling request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* For task-augmented requests, yields 'taskCreated' and 'taskStatus' messages
* before the final result.
*
* @example
* ```typescript
* const stream = server.experimental.tasks.createMessageStream({
* messages: [{ role: 'user', content: { type: 'text', text: 'Hello' } }],
* maxTokens: 100
* }, {
* onprogress: (progress) => {
* // Handle streaming tokens via progress notifications
* console.log('Progress:', progress.message);
* }
* });
*
* 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;
* }
* }
* ```
*
* @param params - The sampling request parameters
* @param options - Optional request options (timeout, signal, task creation params, onprogress, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
createMessageStream(params, options) {
// Access client capabilities via the server
const clientCapabilities = this._server.getClientCapabilities();
// Capability check - only required when tools/toolChoice are provided
if ((params.tools || params.toolChoice) && !clientCapabilities?.sampling?.tools) {
throw new Error('Client does not support sampling tools capability.');
}
// Message structure validation - always validate tool_use/tool_result pairs.
// These may appear even without tools/toolChoice in the current request when
// a previous sampling request returned tool_use and this is a follow-up with results.
if (params.messages.length > 0) {
const lastMessage = params.messages[params.messages.length - 1];
const lastContent = Array.isArray(lastMessage.content) ? lastMessage.content : [lastMessage.content];
const hasToolResults = lastContent.some(c => c.type === 'tool_result');
const previousMessage = params.messages.length > 1 ? params.messages[params.messages.length - 2] : undefined;
const previousContent = previousMessage
? Array.isArray(previousMessage.content)
? previousMessage.content
: [previousMessage.content]
: [];
const hasPreviousToolUse = previousContent.some(c => c.type === 'tool_use');
if (hasToolResults) {
if (lastContent.some(c => c.type !== 'tool_result')) {
throw new Error('The last message must contain only tool_result content if any is present');
}
if (!hasPreviousToolUse) {
throw new Error('tool_result blocks are not matching any tool_use from the previous message');
}
}
if (hasPreviousToolUse) {
// Extract tool_use IDs from previous message and tool_result IDs from current message
const toolUseIds = new Set(previousContent.filter(c => c.type === 'tool_use').map(c => c.id));
const toolResultIds = new Set(lastContent.filter(c => c.type === 'tool_result').map(c => c.toolUseId));
if (toolUseIds.size !== toolResultIds.size || ![...toolUseIds].every(id => toolResultIds.has(id))) {
throw new Error('ids of tool_result blocks and tool_use blocks from previous message do not match');
}
}
}
return this.requestStream({
method: 'sampling/createMessage',
params
}, CreateMessageResultSchema, options);
}
/**
* Sends an elicitation request and returns an AsyncGenerator that yields response messages.
* The generator is guaranteed to end with either a 'result' or 'error' message.
*
* For task-augmented requests (especially URL-based elicitation), yields 'taskCreated'
* and 'taskStatus' messages before the final result.
*
* @example
* ```typescript
* const stream = server.experimental.tasks.elicitInputStream({
* mode: 'url',
* message: 'Please authenticate',
* elicitationId: 'auth-123',
* url: 'https://example.com/auth'
* }, {
* task: { ttl: 300000 } // Task-augmented for long-running auth flow
* });
*
* 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('User action:', message.result.action);
* break;
* case 'error':
* console.error('Error:', message.error);
* break;
* }
* }
* ```
*
* @param params - The elicitation request parameters
* @param options - Optional request options (timeout, signal, task creation params, etc.)
* @returns AsyncGenerator that yields ResponseMessage objects
*
* @experimental
*/
elicitInputStream(params, options) {
// Access client capabilities via the server
const clientCapabilities = this._server.getClientCapabilities();
const mode = params.mode ?? 'form';
// Capability check based on mode
switch (mode) {
case 'url': {
if (!clientCapabilities?.elicitation?.url) {
throw new Error('Client does not support url elicitation.');
}
break;
}
case 'form': {
if (!clientCapabilities?.elicitation?.form) {
throw new Error('Client does not support form elicitation.');
}
break;
}
}
// Normalize params to ensure mode is set for form mode (defaults to 'form' per spec)
const normalizedParams = mode === 'form' && params.mode === undefined ? { ...params, mode: 'form' } : params;
// Cast to ServerRequest needed because TypeScript can't narrow the union type
// based on the discriminated 'method' field when constructing the object literal
return this.requestStream({
method: 'elicitation/create',
params: normalizedParams
}, ElicitResultSchema, options);
}
/**
* Gets the current status of a task.
*
* @param taskId - The task identifier
* @param options - Optional request options
* @returns The task status
*
* @experimental
*/
async getTask(taskId, options) {
return this._server.getTask({ taskId }, options);
}
/**
* Retrieves the result of a completed task.
*
* @param taskId - The task identifier
* @param resultSchema - Zod schema for validating the result
* @param options - Optional request options
* @returns The task result
*
* @experimental
*/
async getTaskResult(taskId, resultSchema, options) {
return this._server.getTaskResult({ taskId }, resultSchema, options);
}
/**
* Lists tasks with optional pagination.
*
* @param cursor - Optional pagination cursor
* @param options - Optional request options
* @returns List of tasks with optional next cursor
*
* @experimental
*/
async listTasks(cursor, options) {
return this._server.listTasks(cursor ? { cursor } : undefined, options);
}
/**
* Cancels a running task.
*
* @param taskId - The task identifier
* @param options - Optional request options
*
* @experimental
*/
async cancelTask(taskId, options) {
return this._server.cancelTask({ taskId }, options);
}
}
//# sourceMappingURL=server.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/server.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,94 @@
/**
* In-memory implementations of TaskStore and TaskMessageQueue.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import { Task, RequestId, Result, Request } from '../../../types.js';
import { TaskStore, TaskMessageQueue, QueuedMessage, CreateTaskOptions } from '../interfaces.js';
/**
* A simple in-memory implementation of TaskStore for demonstration purposes.
*
* This implementation stores all tasks in memory and provides automatic cleanup
* based on the ttl duration specified in the task creation parameters.
*
* Note: This is not suitable for production use as all data is lost on restart.
* For production, consider implementing TaskStore with a database or distributed cache.
*
* @experimental
*/
export declare class InMemoryTaskStore implements TaskStore {
private tasks;
private cleanupTimers;
/**
* Generates a unique task ID.
* Uses 16 bytes of random data encoded as hex (32 characters).
*/
private generateTaskId;
createTask(taskParams: CreateTaskOptions, requestId: RequestId, request: Request, _sessionId?: string): Promise<Task>;
getTask(taskId: string, _sessionId?: string): Promise<Task | null>;
storeTaskResult(taskId: string, status: 'completed' | 'failed', result: Result, _sessionId?: string): Promise<void>;
getTaskResult(taskId: string, _sessionId?: string): Promise<Result>;
updateTaskStatus(taskId: string, status: Task['status'], statusMessage?: string, _sessionId?: string): Promise<void>;
listTasks(cursor?: string, _sessionId?: string): Promise<{
tasks: Task[];
nextCursor?: string;
}>;
/**
* Cleanup all timers (useful for testing or graceful shutdown)
*/
cleanup(): void;
/**
* Get all tasks (useful for debugging)
*/
getAllTasks(): Task[];
}
/**
* A simple in-memory implementation of TaskMessageQueue for demonstration purposes.
*
* This implementation stores messages in memory, organized by task ID and optional session ID.
* Messages are stored in FIFO queues per task.
*
* Note: This is not suitable for production use in distributed systems.
* For production, consider implementing TaskMessageQueue with Redis or other distributed queues.
*
* @experimental
*/
export declare class InMemoryTaskMessageQueue implements TaskMessageQueue {
private queues;
/**
* Generates a queue key from taskId.
* SessionId is intentionally ignored because taskIds are globally unique
* and tasks need to be accessible across HTTP requests/sessions.
*/
private getQueueKey;
/**
* Gets or creates a queue for the given task and session.
*/
private getQueue;
/**
* Adds a message to the end of the queue for a specific task.
* Atomically checks queue size and throws if maxSize would be exceeded.
* @param taskId The task identifier
* @param message The message to enqueue
* @param sessionId Optional session ID for binding the operation to a specific session
* @param maxSize Optional maximum queue size - if specified and queue is full, throws an error
* @throws Error if maxSize is specified and would be exceeded
*/
enqueue(taskId: string, message: QueuedMessage, sessionId?: string, maxSize?: number): Promise<void>;
/**
* Removes and returns the first message from the queue for a specific task.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns The first message, or undefined if the queue is empty
*/
dequeue(taskId: string, sessionId?: string): Promise<QueuedMessage | undefined>;
/**
* Removes and returns all messages from the queue for a specific task.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns Array of all messages that were in the queue
*/
dequeueAll(taskId: string, sessionId?: string): Promise<QueuedMessage[]>;
}
//# sourceMappingURL=in-memory.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"in-memory.d.ts","sourceRoot":"","sources":["../../../../../src/experimental/tasks/stores/in-memory.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,EAAE,SAAS,EAAc,gBAAgB,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAU7G;;;;;;;;;;GAUG;AACH,qBAAa,iBAAkB,YAAW,SAAS;IAC/C,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,aAAa,CAAoD;IAEzE;;;OAGG;IACH,OAAO,CAAC,cAAc;IAIhB,UAAU,CAAC,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA0CrH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAKlE,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCnH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAanE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCpH,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA0BtG;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;CAGxB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,wBAAyB,YAAW,gBAAgB;IAC7D,OAAO,CAAC,MAAM,CAAsC;IAEpD;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;IACH,OAAO,CAAC,QAAQ;IAUhB;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1G;;;;;OAKG;IACG,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAKrF;;;;;OAKG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC;CAMjF"}

View File

@@ -0,0 +1,246 @@
/**
* In-memory implementations of TaskStore and TaskMessageQueue.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
import { isTerminal } from '../interfaces.js';
import { randomBytes } from 'node:crypto';
/**
* A simple in-memory implementation of TaskStore for demonstration purposes.
*
* This implementation stores all tasks in memory and provides automatic cleanup
* based on the ttl duration specified in the task creation parameters.
*
* Note: This is not suitable for production use as all data is lost on restart.
* For production, consider implementing TaskStore with a database or distributed cache.
*
* @experimental
*/
export class InMemoryTaskStore {
constructor() {
this.tasks = new Map();
this.cleanupTimers = new Map();
}
/**
* Generates a unique task ID.
* Uses 16 bytes of random data encoded as hex (32 characters).
*/
generateTaskId() {
return randomBytes(16).toString('hex');
}
async createTask(taskParams, requestId, request, _sessionId) {
// Generate a unique task ID
const taskId = this.generateTaskId();
// Ensure uniqueness
if (this.tasks.has(taskId)) {
throw new Error(`Task with ID ${taskId} already exists`);
}
const actualTtl = taskParams.ttl ?? null;
// Create task with generated ID and timestamps
const createdAt = new Date().toISOString();
const task = {
taskId,
status: 'working',
ttl: actualTtl,
createdAt,
lastUpdatedAt: createdAt,
pollInterval: taskParams.pollInterval ?? 1000
};
this.tasks.set(taskId, {
task,
request,
requestId
});
// Schedule cleanup if ttl is specified
// Cleanup occurs regardless of task status
if (actualTtl) {
const timer = setTimeout(() => {
this.tasks.delete(taskId);
this.cleanupTimers.delete(taskId);
}, actualTtl);
this.cleanupTimers.set(taskId, timer);
}
return task;
}
async getTask(taskId, _sessionId) {
const stored = this.tasks.get(taskId);
return stored ? { ...stored.task } : null;
}
async storeTaskResult(taskId, status, result, _sessionId) {
const stored = this.tasks.get(taskId);
if (!stored) {
throw new Error(`Task with ID ${taskId} not found`);
}
// Don't allow storing results for tasks already in terminal state
if (isTerminal(stored.task.status)) {
throw new Error(`Cannot store result for task ${taskId} in terminal status '${stored.task.status}'. Task results can only be stored once.`);
}
stored.result = result;
stored.task.status = status;
stored.task.lastUpdatedAt = new Date().toISOString();
// Reset cleanup timer to start from now (if ttl is set)
if (stored.task.ttl) {
const existingTimer = this.cleanupTimers.get(taskId);
if (existingTimer) {
clearTimeout(existingTimer);
}
const timer = setTimeout(() => {
this.tasks.delete(taskId);
this.cleanupTimers.delete(taskId);
}, stored.task.ttl);
this.cleanupTimers.set(taskId, timer);
}
}
async getTaskResult(taskId, _sessionId) {
const stored = this.tasks.get(taskId);
if (!stored) {
throw new Error(`Task with ID ${taskId} not found`);
}
if (!stored.result) {
throw new Error(`Task ${taskId} has no result stored`);
}
return stored.result;
}
async updateTaskStatus(taskId, status, statusMessage, _sessionId) {
const stored = this.tasks.get(taskId);
if (!stored) {
throw new Error(`Task with ID ${taskId} not found`);
}
// Don't allow transitions from terminal states
if (isTerminal(stored.task.status)) {
throw new Error(`Cannot update task ${taskId} from terminal status '${stored.task.status}' to '${status}'. Terminal states (completed, failed, cancelled) cannot transition to other states.`);
}
stored.task.status = status;
if (statusMessage) {
stored.task.statusMessage = statusMessage;
}
stored.task.lastUpdatedAt = new Date().toISOString();
// If task is in a terminal state and has ttl, start cleanup timer
if (isTerminal(status) && stored.task.ttl) {
const existingTimer = this.cleanupTimers.get(taskId);
if (existingTimer) {
clearTimeout(existingTimer);
}
const timer = setTimeout(() => {
this.tasks.delete(taskId);
this.cleanupTimers.delete(taskId);
}, stored.task.ttl);
this.cleanupTimers.set(taskId, timer);
}
}
async listTasks(cursor, _sessionId) {
const PAGE_SIZE = 10;
const allTaskIds = Array.from(this.tasks.keys());
let startIndex = 0;
if (cursor) {
const cursorIndex = allTaskIds.indexOf(cursor);
if (cursorIndex >= 0) {
startIndex = cursorIndex + 1;
}
else {
// Invalid cursor - throw error
throw new Error(`Invalid cursor: ${cursor}`);
}
}
const pageTaskIds = allTaskIds.slice(startIndex, startIndex + PAGE_SIZE);
const tasks = pageTaskIds.map(taskId => {
const stored = this.tasks.get(taskId);
return { ...stored.task };
});
const nextCursor = startIndex + PAGE_SIZE < allTaskIds.length ? pageTaskIds[pageTaskIds.length - 1] : undefined;
return { tasks, nextCursor };
}
/**
* Cleanup all timers (useful for testing or graceful shutdown)
*/
cleanup() {
for (const timer of this.cleanupTimers.values()) {
clearTimeout(timer);
}
this.cleanupTimers.clear();
this.tasks.clear();
}
/**
* Get all tasks (useful for debugging)
*/
getAllTasks() {
return Array.from(this.tasks.values()).map(stored => ({ ...stored.task }));
}
}
/**
* A simple in-memory implementation of TaskMessageQueue for demonstration purposes.
*
* This implementation stores messages in memory, organized by task ID and optional session ID.
* Messages are stored in FIFO queues per task.
*
* Note: This is not suitable for production use in distributed systems.
* For production, consider implementing TaskMessageQueue with Redis or other distributed queues.
*
* @experimental
*/
export class InMemoryTaskMessageQueue {
constructor() {
this.queues = new Map();
}
/**
* Generates a queue key from taskId.
* SessionId is intentionally ignored because taskIds are globally unique
* and tasks need to be accessible across HTTP requests/sessions.
*/
getQueueKey(taskId, _sessionId) {
return taskId;
}
/**
* Gets or creates a queue for the given task and session.
*/
getQueue(taskId, sessionId) {
const key = this.getQueueKey(taskId, sessionId);
let queue = this.queues.get(key);
if (!queue) {
queue = [];
this.queues.set(key, queue);
}
return queue;
}
/**
* Adds a message to the end of the queue for a specific task.
* Atomically checks queue size and throws if maxSize would be exceeded.
* @param taskId The task identifier
* @param message The message to enqueue
* @param sessionId Optional session ID for binding the operation to a specific session
* @param maxSize Optional maximum queue size - if specified and queue is full, throws an error
* @throws Error if maxSize is specified and would be exceeded
*/
async enqueue(taskId, message, sessionId, maxSize) {
const queue = this.getQueue(taskId, sessionId);
// Atomically check size and enqueue
if (maxSize !== undefined && queue.length >= maxSize) {
throw new Error(`Task message queue overflow: queue size (${queue.length}) exceeds maximum (${maxSize})`);
}
queue.push(message);
}
/**
* Removes and returns the first message from the queue for a specific task.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns The first message, or undefined if the queue is empty
*/
async dequeue(taskId, sessionId) {
const queue = this.getQueue(taskId, sessionId);
return queue.shift();
}
/**
* Removes and returns all messages from the queue for a specific task.
* @param taskId The task identifier
* @param sessionId Optional session ID for binding the query to a specific session
* @returns Array of all messages that were in the queue
*/
async dequeueAll(taskId, sessionId) {
const key = this.getQueueKey(taskId, sessionId);
const queue = this.queues.get(key) ?? [];
this.queues.delete(key);
return queue;
}
}
//# sourceMappingURL=in-memory.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
/**
* Re-exports of task-related types from the MCP protocol spec.
* WARNING: These APIs are experimental and may change without notice.
*
* These types are defined in types.ts (matching the protocol spec) and
* re-exported here for convenience when working with experimental task features.
*/
export { TaskCreationParamsSchema, RelatedTaskMetadataSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema } from '../../types.js';
export type { Task, TaskCreationParams, RelatedTaskMetadata, CreateTaskResult, TaskStatusNotificationParams, TaskStatusNotification, GetTaskRequest, GetTaskResult, GetTaskPayloadRequest, ListTasksRequest, ListTasksResult, CancelTaskRequest, CancelTaskResult } from '../../types.js';
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/experimental/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACH,wBAAwB,EACxB,yBAAyB,EACzB,UAAU,EACV,sBAAsB,EACtB,kCAAkC,EAClC,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC9B,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACR,IAAI,EACJ,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,4BAA4B,EAC5B,sBAAsB,EACtB,cAAc,EACd,aAAa,EACb,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,gBAAgB,EACnB,MAAM,gBAAgB,CAAC"}

View File

@@ -0,0 +1,10 @@
/**
* Re-exports of task-related types from the MCP protocol spec.
* WARNING: These APIs are experimental and may change without notice.
*
* These types are defined in types.ts (matching the protocol spec) and
* re-exported here for convenience when working with experimental task features.
*/
// Task schemas (Zod)
export { TaskCreationParamsSchema, RelatedTaskMetadataSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema } from '../../types.js';
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/experimental/tasks/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,qBAAqB;AACrB,OAAO,EACH,wBAAwB,EACxB,yBAAyB,EACzB,UAAU,EACV,sBAAsB,EACtB,kCAAkC,EAClC,4BAA4B,EAC5B,oBAAoB,EACpB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,EACtB,qBAAqB,EACrB,uBAAuB,EACvB,sBAAsB,EACtB,2BAA2B,EAC3B,2BAA2B,EAC9B,MAAM,gBAAgB,CAAC"}