Skip to content

Conversation

@LucaButBoring
Copy link
Contributor

@LucaButBoring LucaButBoring commented Jan 19, 2026

Implements SEP-1686 (Tasks), from the latest specification release.

Motivation and Context

Tasks address several protocol gaps:

  1. Avoiding tool splitting anti-patterns - No need to create separate start_tool, get_status, get_result tools; a single task-aware tool handles the full lifecycle
  2. Decoupling execution from result retrieval - Clients can dispatch operations immediately and collect results later, without blocking or re-executing if responses are dropped
  3. Moving orchestration to host applications - The polling logic lives in the host application/SDK, not in agents that might hallucinate or fail to follow polling contracts

Usage

Server: Defining a Task-Aware Tool

TaskAwareAsyncToolSpecification.builder()
    .name("long-operation")
    .description("A long-running operation")
    .inputSchema(schema)
    // TaskSupportMode.REQUIRED is the default for task-aware tools
    .createTaskHandler((args, extra) -> {
        return extra.createTask()
            .flatMap(task -> {
                startBackgroundWork(task.taskId(), args);
                return Mono.just(CreateTaskResult.builder().task(task).build());
            });
    })
    .build()

Server: Using TaskContext for Lifecycle Management

TaskContext ctx = extra.createTaskContext(task);
ctx.updateStatus("Processing batch 1 of 10");
ctx.isCancelled().flatMap(cancelled -> {
    if (cancelled) return ctx.fail("Cancelled by user");
    return doWork().then(ctx.complete(result));
});

TaskSupportMode options:

  • REQUIRED (default): Must have task metadata; returns error otherwise
  • OPTIONAL: Works with or without task metadata; auto-polling shim provides backward compatibility
  • FORBIDDEN: No task support (regular tools)

Client: Streaming API (Recommended)

Drop-in replacement for callTool that handles polling automatically:

client.callToolStream(request)
    .subscribe(msg -> switch(msg) {
        case TaskCreatedMessage<CallToolResult> tc -> log.info("Task: {}", tc.task().taskId());
        case TaskStatusMessage<CallToolResult> ts -> log.info("Status: {}", ts.task().status());
        case ResultMessage<CallToolResult> r -> handleResult(r.result());
        case ErrorMessage<CallToolResult> e -> handleError(e.error());
    });

Client: Task-Based API (For Explicit Control)

For consumers who need custom polling behavior, cancellation logic, or batched task management:

// Create task and get immediate response with task ID
CreateTaskResult created = client.callToolTask(request);
String taskId = created.task().taskId();

// Poll for status updates (with custom logic)
GetTaskResult status = client.getTask(taskId);
while (!status.isTerminal()) {
    Thread.sleep(status.pollInterval());
    status = client.getTask(taskId);
}

// Retrieve final result
CallToolResult result = client.getTaskResult(taskId, new TypeRef<>() {});

// Or cancel if needed
client.cancelTask(taskId);

Similar patterns exist for sampling (createMessageStream / createMessageTask) and elicitation (createElicitationStream / createElicitationTask).

Server: Bidirectional Task Flows

Servers can send task-augmented requests to clients, assuming the client has configured its own TaskStore:

// Server requesting sampling from client with task tracking
exchange.createMessageStream(new CreateMessageRequest(..., taskMetadata, null))
    .subscribe(msg -> ...);

// Server requesting elicitation from client with task tracking
exchange.createElicitationStream(new ElicitRequest(..., taskMetadata, null))
    .subscribe(msg -> ...);

Key Design Decisions

  1. Experimental namespace - All task APIs are in io.modelcontextprotocol.experimental.tasks, signaling that the API may change (matches TypeScript/Python SDKs)

  2. TaskStore abstraction - Interface for pluggable storage; InMemoryTaskStore provided for development and testing. The originating request (e.g., CallToolRequest) is stored alongside the task, so tool routing can be derived from stored context rather than maintained as separate mapping state.

  3. Auto-polling shim - OPTIONAL mode tools work transparently for non-task-aware clients

  4. Defense-in-depth session isolation - Session ID required on all TaskStore operations; enforced at both server and storage layers to prevent cross-session task access

    • Passing null for sessionId bypasses validation (single-tenant mode). This is used by McpAsyncClient since clients are inherently single-tenant - there's only one session, so cross-session isolation doesn't apply.

How Has This Been Tested?

  • Unit tests
  • Client-server integration tests for the typical flows
  • Spot-checking compatibility with the TS SDK

Breaking Changes

None

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Closes #668

This PR also includes a tweak to how 202 Accepted is handled by the client implementation, which was done to handle how the TypeScript server SDK configures its response headers when accepting JSON-RPC responses and notifications from the client - in particular, sending InitializeNotification produced an exception in the Java SDK client before this, which made testing compatibility with the existing TS SDK's Tasks implementation rather difficult.

@LucaButBoring LucaButBoring force-pushed the feat/tasks branch 2 times, most recently from 4cf98e9 to 82ccfa1 Compare January 19, 2026 10:58
@He-Pin
Copy link
Contributor

He-Pin commented Jan 19, 2026

Nice to have this in, the api seems quite the same as typescript sdk

@chemicL
Copy link
Member

chemicL commented Jan 20, 2026

@LucaButBoring Thanks. I'll try to review the PR. In the meantime, please rebase against main as I have fixed the integration tests setup.

@LucaButBoring
Copy link
Contributor Author

Rebased - this is (unfortunately) a very large PR, but I recommend starting with the code related to the key design decisions, and there's also a new integration test (testExternalAsyncApiPattern) which shows a model use case to help understand the high-level flow before digging into the details.

* @see McpSchema.CallToolResult
* @see McpSchema.CreateMessageResult
*/
public <T extends McpSchema.ServerTaskPayloadResult> T getTaskResult(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be ClientTaskPayloadResult? Regardless, there is no current way to get the input_required request from the client for a task.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the client, so when it calls tasks/result, it will only receive the appropriate server message for the task (currently only CallToolResult).

The input_required-bound request happens asynchronously relative to this but (with SSE) requires the client to invoke tasks/result first.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a lengthy (and admittedly hard to parse) note on the input_required status in the spec explaining the side-channeling here: https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks#input-required-status

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have the typeRef? There's only 1 possible result type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly for consistency with the server version of this interface, and so that we don't need to make a breaking change if (I expect "when") we add more supported client->server methods for Tasks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I left in a comment about sampling here that isn't relevant which probably muddies the waters, I'll adjust that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the client-side documentation, will tweak the server-side documentation in a bit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated documentation for:

  • McpSyncClient.getTask
  • McpSyncClient.getTaskResult
  • McpAsyncClient.getTask
  • McpAsyncClient.getTaskResult
  • McpSyncServerExchange.getTask
  • McpSyncServerExchange.getTaskResult
  • McpAsyncServerExchange.getTask
  • McpAsyncServerExchange.getTaskResult

* @param resultTypeRef Type reference for deserializing the result.
* @return The task result.
*/
public <T extends McpSchema.ServerTaskPayloadResult> T getTaskResult(String taskId, TypeRef<T> resultTypeRef) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above

@Randgalt
Copy link
Contributor

Randgalt commented Jan 22, 2026

I'm testing with our server implementation.

The protocol version in the initialize request is 2025-06-18. Also, tasks support is empty. I think more documentation may be needed here as I'm missing steps that I've had to come here to get answered.

@LucaButBoring
Copy link
Contributor Author

LucaButBoring commented Jan 22, 2026

The protocol version in the initialize request is 2025-06-18.

Will fix this.

Also, tasks support is empty.

That's expected for tool calls from the client - the client only declares a tasks capability when it can accept task creation requests for elicitation or sampling. The server needs to declare a tasks capability when it can accept task creation requests for tool calls.

I'll update the documentation to try and make this more clear.

@Randgalt
Copy link
Contributor

Randgalt commented Jan 22, 2026

That's expected for tool calls from the client - the client only declares a tasks capability when it can accept task creation requests for elicitation or sampling. The server needs to declare a tasks capability when it can accept task creation requests for tool calls.

I ran into an issue with this. I've been developing server support for tasks for a while now. I was testing with the current version of the MCP Inspector which reports protocol version 2025-11-25. However, when my server returned Task information in the Tools model for tools/list the Inspector threw an exception. Maybe this is just a bug in the inspector but you could return {} for tasks in ClientCapabilities and still be compatible. But, then, the spec is not clear on this.

@LucaButBoring
Copy link
Contributor Author

The current version of the inspector doesn't support Tasks, that's being worked on here: modelcontextprotocol/inspector#1013

@Randgalt
Copy link
Contributor

The current version of the inspector doesn't support Tasks, that's being worked on here: modelcontextprotocol/inspector#1013

Yeah, I know. But it still sends protocol version 2025-11-25. Is that a bug?

Also added taskId convenience overloads.
@LucaButBoring
Copy link
Contributor Author

It is, I'm testing my fix for that right now - looks like #733 added the constant for it but the corresponding constant for the latest version wasn't changed to it.

@LucaButBoring
Copy link
Contributor Author

@Randgalt That requires changing a lot of tests, so I'm considering making that change in a separate PR, is that fine? The protocol version change is technically needed for all of the 11/25 spec features, so I don't think this PR should include it (it should've been done independently first, really). For testing right now, you can declare the supported protocol versions when constructing the transport, like this:

var transport = HttpClientStreamableHttpTransport // or WebClientStreamableHttpTransport
    .builder("http://localhost:" + PORT) // use WebClient.builder().baseUrl() here for WebClientStreamableHttpTransport
    .supportedProtocolVersions(List.of(ProtocolVersions.MCP_2025_11_25))
    .build();

@LucaButBoring
Copy link
Contributor Author

Opened #758 to bump the declared protocol version

@Randgalt
Copy link
Contributor

@Randgalt That requires changing a lot of tests, so I'm considering making that change in a separate PR, is that fine?

I can't really test this PR without getting the correct protocol from the client. I'll check #758 and see if I can create a merged branch locally to test with.

@Randgalt
Copy link
Contributor

Randgalt commented Jan 23, 2026

OK - I pulled both PRs and made a temp branch that has both of them and did some testing. I still don't understand how input_required is supposed to work here. I've tried several different things for the INPUT_REQUIRED step to no avail. When status INPUT_REQUIRED is returned by the client there doesn't appear to be anything I can do. Note, when creating the client I'm calling elicitation(_ -> new McpSchema.ElicitResult(ACCEPT, ImmutableMap.of("firstName", name, "lastName", name + "sky"))).

Here's my code:

        CallToolRequest callToolRequest = CallToolRequest.builder()
                .task(McpSchema.TaskMetadata.builder().ttl(Duration.ofDays(1)).build())
                .name("task")
                .build();
        String taskId = client.callToolTask(callToolRequest).task().taskId();

        boolean done = false;
        while (!done) {
            McpSchema.GetTaskResult task = client.getTask(taskId);
            switch (task.status()) {
                case WORKING -> {}  // do nothing
                case INPUT_REQUIRED -> client.getTaskResult(taskId, new TypeRef<CallToolResult>() {});
                case FAILED, CANCELLED -> fail("Task " + taskId + " should not have failed or been cancelled");
                case COMPLETED -> done = true;
            }

            if (!done) {
                SECONDS.sleep(1);
            }
        }

        CallToolResult callToolResult = client.getTaskResult(taskId, new TypeRef<>() {});

The above stays at INPUT_REQUIRED forever.

@Randgalt
Copy link
Contributor

Randgalt commented Jan 23, 2026

I just tried with callToolStream() instead. Our server gets three requests:

  1. tasks/get - we return WORKING
  2. tasks/get - we return INPUT_REQUIRED
  3. tasks/result - we return JsonRpcRequest[jsonrpc=2.0, id=17e9bed8-5420-4ae0-803a-141653492015, method=elicitation/create, params=Optional[ElicitRequestForm[mode=Optional[form], message=Who are you?, requestedSchema={"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"}},"required":["firstName","lastName"]}, meta=Optional[{io.modelcontextprotocol/related-task=69802b8dd9f640bcbe1d127026592b7d}], ttl=OptionalInt.empty]]]

That's it, we don't see the elicit result nor another tasks/get as we would expect. callToolStream() returns with 4 entries. The first 3 are the task and the last is an empty CallToolResult.

* @see McpSchema.ResultMessage
* @see McpSchema.ErrorMessage
*/
public List<McpSchema.ResponseMessage<McpSchema.CallToolResult>> callToolStream(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method seems misnamed. It's not returning a stream but a list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I forgot about this - I was a bit on the fence about what the return type on this should be, actually. Conventionally, we convert all Flux<T> into List<T>, but following that causes these awkward cases (also in elicitation/sampling) where we have a *Stream method that doesn't actually return a Stream<T>.

I can change these to return a Stream<T> in the sync interfaces, I'm just not sure if that's a clear method contract for a synchronous method, since streams have an opaque execution contract.

I suppose I can make these into actual streams and just document the underlying behavior more clearly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, Flux.toStream() blocks for each item emitted into the stream, hm. At any rate, I'll just make a stream and we can go from there.

@LucaButBoring
Copy link
Contributor Author

Looks like elicitation/sampling aren't wired up to the message queue correctly, I'm adjusting the implementation/tests to address this and properly detect issues with it (this was also an oversight I made in TS at first but the API differences tripped me up when verifying it). Will update once that's resolved.

@LucaButBoring
Copy link
Contributor Author

Should be fixed, now - wired up the queue properly (and trimmed its API surface down a fair bit) and updated the tests to avoid internal blocking, which was masking the issue before

@Randgalt
Copy link
Contributor

Should be fixed, now - wired up the queue properly (and trimmed its API surface down a fair bit) and updated the tests to avoid internal blocking, which was masking the issue before

It's still behaving somewhat as before. I call callToolStream() in my test and I see:

2026-01-25T10:55:09.921Z	INFO	testing-worker-63	stdout	getTask WORKING
2026-01-25T10:55:24.937Z	INFO	testing-worker-53	stdout	getTask INPUT_REQUIRED
2026-01-25T10:55:24.948Z	INFO	testing-worker-63	stdout	blockUntilTaskResult JsonRpcRequest[jsonrpc=2.0, id=f6109996-fc7b-4a05-af19-63f9fafed7f5, method=elicitation/create, params=Optional[ElicitRequestForm[mode=Optional[form], message=Who are you?, requestedSchema={"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"}},"required":["firstName","lastName"]}, meta=Optional[{io.modelcontextprotocol/related-task=0a9399dd76bb457e87565828a6f69542}], ttl=OptionalInt.empty]]]

Then callToolStream() returns with an empty result.

If I use callToolTask it stays at INPUT_REQUIRED forever.

@@ -1590,7 +2656,7 @@ public record CallToolResult( // @formatter:off
@JsonProperty("content") List<Content> content,
@JsonProperty("isError") Boolean isError,
@JsonProperty("structuredContent") Object structuredContent,
@JsonProperty("_meta") Map<String, Object> meta) implements Result { // @formatter:on
@JsonProperty("_meta") Map<String, Object> meta) implements ServerTaskPayloadResult { // @formatter:on
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

	public record CallToolResult( // @formatter:off
		@JsonProperty("content") List<Content> content,
		@JsonProperty("isError") Boolean isError,
		@JsonProperty("structuredContent") Object structuredContent,
		@JsonProperty("task") Task task,
		@JsonProperty("_meta") Map<String, Object> meta) implements Result, GetTaskPayloadResult {

I think something like this would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean so that CallToolResult implicitly satisfies CreateTaskResult? It seems unintuitive for SDK consumers to have an ambiguous union like that in method signatures.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes,I implemented as this, which is simpler

@LucaButBoring
Copy link
Contributor Author

LucaButBoring commented Jan 26, 2026

@Randgalt I pushed a working client/server example to a separate branch (client; server) - how closely does this match your repro? Trying to figure out where our setups diverge so I can diagnose this effectively.

./mvnw exec:java -pl mcp-example-server
./mvnw exec:java -pl mcp-example-client
[CLIENT] Starting callToolStream...
[CLIENT] Message 1: TaskCreatedMessage
[CLIENT]   -> Task created: 1f2ac04b-f512-4948-a6c6-234862820af7
[CLIENT]   -> Initial status: WORKING
[CLIENT]   -> Poll interval: 100ms
[CLIENT] Message 2: TaskStatusMessage
[CLIENT]   -> Task status update: INPUT_REQUIRED
[CLIENT]   -> Status message: Waiting for elicitation
[CLIENT ELICITATION] ========================================
[CLIENT ELICITATION] Received elicitation request #1!
[CLIENT ELICITATION] Message: What is your favorite number?
[CLIENT ELICITATION] Returning response: value=42
[CLIENT ELICITATION] ========================================
[CLIENT] Message 3: ResultMessage
[CLIENT]   -> RESULT RECEIVED!
[CLIENT]   -> Content: [TextContent[annotations=null, text=Got user input via side-channel: {value=42}, meta=null]]

@Randgalt
Copy link
Contributor

Randgalt commented Jan 26, 2026

@Randgalt I pushed a working client/server example to a separate branch (client; server) - how closely does this match your repro? Trying to figure out where our setups diverge so I can diagnose this effectively.

This helps, thank you. I found one bug in our server and what I think is a bug in your client. We're expecting _meta to have a io.modelcontextprotocol/related-task entry with the TaskId when the ElicitResult is sent. Your ElicitResult doesn't have a _meta at all. We can't relate it to the corresponding task without this.

https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks#associating-task-related-messages

@LucaButBoring
Copy link
Contributor Author

Updated both branches with the relevant fix - metadata added to all task-related results and notifications

@Randgalt
Copy link
Contributor

Randgalt commented Jan 27, 2026

@LucaButBoring we're getting farther, but still not working completely. The elicit request/response loop seems to be working. But, once we receive the ElicitResult we don't get called again and the task times out. Here are the messages we receive:

2026-01-27T14:24:10.819Z	INFO	testing-worker-51	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:10.932Z	INFO	testing-worker-51	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.038Z	INFO	testing-worker-54	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.142Z	INFO	testing-worker-55	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.246Z	INFO	testing-worker-53	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.350Z	INFO	testing-worker-54	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.457Z	INFO	testing-worker-55	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.563Z	INFO	testing-worker-53	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.667Z	INFO	testing-worker-54	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.779Z	INFO	testing-worker-55	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[WORKING]
2026-01-27T14:24:11.882Z	INFO	testing-worker-53	stdout	tasks/get: 297b7a64310e454bbcb6d451c2d726aa Optional[INPUT_REQUIRED]
2026-01-27T14:24:11.888Z	INFO	testing-worker-54	stdout	tasks/result: 297b7a64310e454bbcb6d451c2d726aa
2026-01-27T14:24:11.911Z	INFO	testing-worker-55	stdout	RPC Response: JsonRpcResponse[jsonrpc=2.0, id=115956fc-05a1-40d1-b7ef-55102ad407cc, error=Optional.empty, result=Optional[{action=accept, content={firstName=testListChangeNotifications, lastName=testListChangeNotificationssky}, _meta={io.modelcontextprotocol/related-task=297b7a64310e454bbcb6d451c2d726aa}}]]

Our test code sees the ElicitResponse and then completes the tool/task with our server's Task APIs. But, the MCP client never calls tasks/get again. I'm trying to figure out why, but am having trouble finding it.

Flux/Mono is impossible to debug - awful experience. I'll keep trying.

@Randgalt
Copy link
Contributor

Randgalt commented Jan 27, 2026

@LucaButBoring IMO there seem to be a lot of assumptions in this PR. I did some more testing by calling callToolTask() and it stays forever in the INPUT_REQUIRED state. I don't know the Flux/Mono library well enough to debug but I've been trying. What I see is a lot of assumptions about order of operations. I can't place my finger on the exact problem but I think that's where it lies. The server code we've written was based on the docs and this flowchart: https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks#task-augmented-tool-call-with-elicitation. I think the MCP client needs to be more of a state machine than assuming things happen in a particular order. My 0.02.

@Randgalt
Copy link
Contributor

OK - I think I've proven then issue @LucaButBoring

I modified our server so that when the ElicitRequest is sent to the client we leave the connection open and wait to receive the ElicitResult which will cause our test tool to complete the task. I modified our server to send the task's CallToolResult in the same SSE stream that the ElicitRequest was returned in. When I made all these hacks to our server, this PR's client responded correctly and we see callToolStream() return all the responses we expect.

Per the docs as I read them, however, this is not correct. When the client gets the ElicitRequest from the server it should disconnect and start a new stream. The spec flowchart states "Client closes result stream and resumes polling" after it sends the "elicitation response". Our server is expecting this.

@LucaButBoring
Copy link
Contributor Author

That is a valid flow, but not the only valid flow (rather, if the client disconnects polling still works). The relevant part here is from section 5.6:

When a receiver receives a tasks/result request for a task in any other non-terminal status (working or input_required), it MUST block the response until the task reaches a terminal status.

@Randgalt
Copy link
Contributor

That is a valid flow, but not the only valid flow (rather, if the client disconnects polling still works). The relevant part here is from section 5.6:

When a receiver receives a tasks/result request for a task in any other non-terminal status (working or input_required), it MUST block the response until the task reaches a terminal status.

Ok. If so, that’s unfortunate. I’ll see what can be done to improve the spec. But I’ll adjust our server accordingly and get back to you.

@LucaButBoring
Copy link
Contributor Author

Definitely room for discussion on this, and the incoming Transports WG proposals may very well change this - I'll be discussing this with them in the meeting tomorrow.

@Randgalt
Copy link
Contributor

OK - at long last everything is working. Thanks for all your work on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SEP-1686: Tasks Support

4 participants