* 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 awa
(
request: SendRequestT,
resultSchema: T,
options?: RequestOptions
)
| 1006 | * @experimental Use `client.experimental.tasks.requestStream()` to access this method. |
| 1007 | */ |
| 1008 | protected async *requestStream<T extends AnySchema>( |
| 1009 | request: SendRequestT, |
| 1010 | resultSchema: T, |
| 1011 | options?: RequestOptions |
| 1012 | ): AsyncGenerator<ResponseMessage<SchemaOutput<T>>, void, void> { |
| 1013 | const { task } = options ?? {}; |
| 1014 | |
| 1015 | // For non-task requests, just yield the result |
| 1016 | if (!task) { |
| 1017 | try { |
| 1018 | const result = await this.request(request, resultSchema, options); |
| 1019 | yield { type: 'result', result }; |
| 1020 | } catch (error) { |
| 1021 | yield { |
| 1022 | type: 'error', |
| 1023 | error: error instanceof McpError ? error : new McpError(ErrorCode.InternalError, String(error)) |
| 1024 | }; |
| 1025 | } |
| 1026 | return; |
| 1027 | } |
| 1028 | |
| 1029 | // For task-augmented requests, we need to poll for status |
| 1030 | // First, make the request to create the task |
| 1031 | let taskId: string | undefined; |
| 1032 | try { |
| 1033 | // Send the request and get the CreateTaskResult |
| 1034 | const createResult = await this.request(request, CreateTaskResultSchema, options); |
| 1035 | |
| 1036 | // Extract taskId from the result |
| 1037 | if (createResult.task) { |
| 1038 | taskId = createResult.task.taskId; |
| 1039 | yield { type: 'taskCreated', task: createResult.task }; |
| 1040 | } else { |
| 1041 | throw new McpError(ErrorCode.InternalError, 'Task creation did not return a task'); |
| 1042 | } |
| 1043 | |
| 1044 | // Poll for task completion |
| 1045 | while (true) { |
| 1046 | // Get current task status |
| 1047 | const task = await this.getTask({ taskId }, options); |
| 1048 | yield { type: 'taskStatus', task }; |
| 1049 | |
| 1050 | // Check if task is terminal |
| 1051 | if (isTerminal(task.status)) { |
| 1052 | if (task.status === 'completed') { |
| 1053 | // Get the final result |
| 1054 | const result = await this.getTaskResult({ taskId }, resultSchema, options); |
| 1055 | yield { type: 'result', result }; |
| 1056 | } else if (task.status === 'failed') { |
| 1057 | yield { |
| 1058 | type: 'error', |
| 1059 | error: new McpError(ErrorCode.InternalError, `Task ${taskId} failed`) |
| 1060 | }; |
| 1061 | } else if (task.status === 'cancelled') { |
| 1062 | yield { |
| 1063 | type: 'error', |
| 1064 | error: new McpError(ErrorCode.InternalError, `Task ${taskId} was cancelled`) |
| 1065 | }; |
nothing calls this directly
no test coverage detected
searching dependent graphs…