feat: implement support for SEP-1686 Tasks #755
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implements SEP-1686 (Tasks), from the latest specification release.
Motivation and Context
Tasks address several protocol gaps:
start_tool,get_status,get_resulttools; a single task-aware tool handles the full lifecycleUsage
Server: Defining a Task-Aware Tool
Server: Using TaskContext for Lifecycle Management
TaskSupportMode options:
REQUIRED(default): Must have task metadata; returns error otherwiseOPTIONAL: Works with or without task metadata; auto-polling shim provides backward compatibilityFORBIDDEN: No task support (regular tools)Client: Streaming API (Recommended)
Drop-in replacement for
callToolthat handles polling automatically:Client: Task-Based API (For Explicit Control)
For consumers who need custom polling behavior, cancellation logic, or batched task management:
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:Key Design Decisions
Experimental namespace - All task APIs are in
io.modelcontextprotocol.experimental.tasks, signaling that the API may change (matches TypeScript/Python SDKs)TaskStore abstraction - Interface for pluggable storage;
InMemoryTaskStoreprovided 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.Auto-polling shim -
OPTIONALmode tools work transparently for non-task-aware clientsDefense-in-depth session isolation - Session ID required on all TaskStore operations; enforced at both server and storage layers to prevent cross-session task access
nullforsessionIdbypasses validation (single-tenant mode). This is used byMcpAsyncClientsince clients are inherently single-tenant - there's only one session, so cross-session isolation doesn't apply.How Has This Been Tested?
Breaking Changes
None
Types of changes
Checklist
Additional context
Closes #668
This PR also includes a tweak to how
202 Acceptedis 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, sendingInitializeNotificationproduced an exception in the Java SDK client before this, which made testing compatibility with the existing TS SDK's Tasks implementation rather difficult.