SEP-2663: Tasks Extension#2663
Conversation
02b7564 to
7715860
Compare
|
Moving discussion from #2557 over here @CaitieM20 @markdroth @Randgalt @kurtisvg @localden @pja-ant @dsp-ant @maxisbey @maciej-kisiel @ylxlpl (Tagged everyone who commented on #2557) |
|
Thanks for putting this together, @LucaButBoring - I'll post the comment that I was typing earlier in #2557 and let you validate how much of this is still relevant. Some notes beyond the other bits I called out in the review. There's a few places where I think the SEP is a little underspecified:
A couple of schema regressions I noticed too:
|
|
@localden Thanks for the feedback, going through this:
This revision limits edit: updated
This revision does require keys to be unique over the lifetime of a task, and not reused between distinct requests.
Yup, that's how
I struck out that phrasing in this revision, now it can actually be either, as
To deal with that, in this revision,
A TTL in integer seconds makes sense, but I'm not sure if a polling interval in integer seconds does - 500ms would be a reasonable polling interval for a relatively quick, but high-variance (1s-20s) task. A duration is probably better-expressed with units included in the value (e.g. edit: updated to include units in the field names
Noted, I'll update the phrasing here - it actually doesn't really mean the MCP server fell over either, the literal intent is just that if the inner request returns a JSON-RPC error, that's edit: updated
edit: updated, I misinterpreted this - noted here
Ah, I missed that on #2557 - I'll make sure this is handled correctly when I write the schema changes here. |
|
This is great, allows integration of various organizational extensions. |
The option space is:
IMO:
I agree that (4) is non-standard, but IMO we just make it the standard starting now and make sure that TTL lists also adopts this standard. |
|
We've decided not to add it for now, we're holding off until someone very specifically needs an updating value for their use case, as it was adding a lot of requirements to this spec for not much value in exchange. For use cases where you need an arbitrary but unchanging value, you can use the task ID field instead, and do something like encode a JWT or similar into it (this is also true of tasks today). |
Co-authored-by: Caitie McCaffrey <caitiem20@github.com>
Co-authored-by: Caitie McCaffrey <caitiem20@github.com>
|
Ported over all corrections after review round on modelcontextprotocol/experimental-ext-tasks#2 |
There was a problem hiding this comment.
This Looks Good,
A couple things lets mark this as Final -> see comment.
Also I think there are examples in schema/draft/examples we should be deleting as well.
- GetTaskPayloadRequest
- GetTaskPayloadResult
- GetTaskPayloadResultResponse
- TaskInputResponseRequest
- TaskInputResponseRequestParams
Can you do a quick pass and make sure we've deleted all the examples that are tied to the schema we are removing.
Also I think we are missing a changelog comment
Co-authored-by: Caitie McCaffrey <caitiem20@github.com>
Resolve conflicts keeping tasks out of core schema (moved to extension), incorporate SEP-2260 final status, SEP-2549 TTL additions, and add MRTR changelog entry from main. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This SEP defines an extension that allows a server respond to a
tools/callrequest with an asynchronous task handle instead of a final result, allowing the client to retrieve the eventual result by polling. The extension introduces three methods:tasks/get,tasks/update, andtasks/cancel; a polymorphic-result discriminator (resultType: "task"); and aTaskshape that carries a task status, in-progress server-to-client requests, and a final result or error. Task creation is server-directed: the client signals support by including the extension in its per-request capabilities, and the server decides on a per-request basis whether to materialize a task.Tasks will become a foundational building block of MCP and are expected to be supported in future protocol versions. The experimental
tasksfeature in the2025-11-25specification served as a stopgap until the protocol's extension mechanism was available. Now that extensions have been formalized, moving tasks to an official extension gives the feature time to incubate and evolve based on additional real-world implementation feedback, without being constrained by the core specification's release cadence. Once the extension has stabilized and achieved broad adoption, it is intended to be promoted into the core protocol.This proposal removes the version of tasks specified in the
2025-11-25release. It is shaped by implementation feedback since that release and by several changes to the base protocol expected to arrive in the2026-06-30specification:Motivation and Context
The experimental tasks feature served as an alternate execution mode for tool calls, elicitation, and sampling, allowing receivers to return a poll handle instead of blocking until a final result was ready. Implementation experience surfaced several challenges:
The handshake is fragile. Tasks today expose method-level capabilities (
tasks.requests.tools.calldeclares thattools/callMAY be task-augmented) alongside a tool-levelexecution.taskSupportfield that declares whether a particular tool will accept the augmentation. Clients express their own support for tasks by passing ataskparameter on their requests, but MUST NOT include it if the method/tool does not support tasks. A client that wants to opt into tasks must therefore prime its state with atools/listcall before issuing any task-augmented request, and cannot blindly attach ataskparameter to every request to handle tools isomorphically. This is confusing, implicit, and easy to get wrong.tasks/resultis a blocking trap. In the current flow, a client that observesinput_requiredis required to calltasks/resultprematurely so that the server has an SSE stream on which to side-channel elicitation or sampling requests.tasks/resultthen blocks until the entire operation completes. This forces long-lived persistent connections that many clients and servers do not want to implement, and it conflicts with SEP-2260, which disallows unsolicited server-to-client requests outright. Under SEP-2260, the SSE semantics that justified the blocking behavior no longer apply.tasks/listscoping cannot be defined. To avoid clients cancelling or retrieving results for tasks they shouldn't have access to, all tasks should be bound to some sort of "authorization context," the implementation of which is left to individual servers according to their existing bespoke permission models. However, in many cases, it is not possible to perform this binding, in which case the task ID becomes the only line of defense against contamination. In this scenario, it is unsafe for a server to supporttasks/listat all. While it was possible for tasks to instead be bound to a session, SEP-2567 removes sessions from the protocol. There is no other natural scope a server can define unilaterally — task IDs can be unguessable handles that a server can recognize one at a time, but servers cannot reliably correlate two unrelated handles to the same caller without additional state.Beyond implementation challenges, tasks face another structural issue: Client-hosted tasks are no longer expressible. SEP-1686 permitted clients to host tasks for elicitation and sampling, in part to avoid coupling tasks to tool calls. SEP-2260 makes any unsolicited server-to-client request invalid; every server-to-client polling request under client-hosted tasks would be unsolicited by definition.
This proposal intends to solve the above issues by redesigning certain aspects of the feature and moving tasks out to an official extension. Redefining tasks as an official extension gives the feature more time to incubate and evolve independently of the core specification, promoting adoption. As part of the redesign, this proposal consolidates the polling lifecycle into
tasks/getand a newtasks/updateto remove the blockingtasks/resultmethod. The redesign allows servers to return tasks unsolicited (in response to ordinary, non-task-flagged requests) to eliminate the per-request opt-in and thetools/listwarmup, relying instead on the extension capability as the single handshake point. Finally, this proposal removes client-hosted elicitation and sampling tasks in compliance with SEP-2260.How Has This Been Tested?
Conformance test suite: modelcontextprotocol/conformance#262
Breaking Changes
Described in proposal.
Types of changes
Checklist
Additional context
Supersedes #2557.
AI Use Disclosure: The extension SEP document in this PR was initially drafted using
claude.aiwith the previous iteration as a reference. I rewrote/rephrased many sections myself and verified its correctness, usingclaude.aias a reviewer to iteratively scrub out issues.