@modelcontextprotocol/sdk
Version:
Model Context Protocol implementation for TypeScript
189 lines • 7.98 kB
JavaScript
;
/**
* Experimental client task features for MCP SDK.
* WARNING: These APIs are experimental and may change without notice.
*
* @experimental
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExperimentalClientTasks = void 0;
const types_js_1 = require("../../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
*/
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 = types_js_1.CallToolResultSchema, options) {
var _a;
// 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: (_a = options === null || options === void 0 ? void 0 : options.task) !== null && _a !== void 0 ? _a : (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 types_js_1.McpError(types_js_1.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 types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Structured content does not match the tool's output schema: ${validationResult.errorMessage}`)
};
return;
}
}
catch (error) {
if (error instanceof types_js_1.McpError) {
yield { type: 'error', error };
return;
}
yield {
type: 'error',
error: new types_js_1.McpError(types_js_1.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);
}
}
exports.ExperimentalClientTasks = ExperimentalClientTasks;
//# sourceMappingURL=client.js.map