Problem
The MCP SDK's requestStream() (@modelcontextprotocol/sdk/shared/protocol.js) only calls getTaskResult() for 'completed' tasks. For 'failed' tasks it yields a generic "Task X failed" error and discards the stored result entirely.
This forces us to store all task results as 'completed' even when they are errors — see res/task_status_workaround.md.
Three fixes needed in the SDK
1. Deliver results for 'failed' tasks
// Current:
if (task.status === 'failed') {
yield { type: 'error', error: new McpError(ErrorCode.InternalError, `Task ${taskId} failed`) };
}
// Fix:
if (task.status === 'failed') {
const result = await this.getTaskResult({ taskId }, resultSchema, options);
yield { type: 'result', result }; // result has isError: true
}
2. Include statusMessage in the error (interim fix)
yield {
type: 'error',
error: new McpError(ErrorCode.InternalError, task.statusMessage || `Task ${taskId} failed`)
};
3. storeTaskResult() should accept an optional statusMessage
Our storeTaskResultWithMessage() calls updateTaskStatus('working', message) then storeTaskResult(status, result) — two non-atomic calls. The SDK should support this in one call.
Impact
Once fixed upstream, we can:
- Store errors as
'failed' (semantically correct)
- Remove the
[error] prefix workaround from statusMessages
- Remove
storeTaskResultWithMessage() helper
References
Problem
The MCP SDK's
requestStream()(@modelcontextprotocol/sdk/shared/protocol.js) only callsgetTaskResult()for'completed'tasks. For'failed'tasks it yields a generic"Task X failed"error and discards the stored result entirely.This forces us to store all task results as
'completed'even when they are errors — seeres/task_status_workaround.md.Three fixes needed in the SDK
1. Deliver results for 'failed' tasks
2. Include statusMessage in the error (interim fix)
3.
storeTaskResult()should accept an optional statusMessageOur
storeTaskResultWithMessage()callsupdateTaskStatus('working', message)thenstoreTaskResult(status, result)— two non-atomic calls. The SDK should support this in one call.Impact
Once fixed upstream, we can:
'failed'(semantically correct)[error]prefix workaround from statusMessagesstoreTaskResultWithMessage()helperReferences
res/task_status_workaround.md— full analysis