You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Client-side support for the tasks extension (io.modelcontextprotocol/tasks, SEP-2663) #3226
v2 removed the experimental tasks API in favor of the SEP-2663 extension (io.modelcontextprotocol/tasks), but the SDK currently ships no client-side way to consume task-augmented servers: a tools/call that returns resultType: "task" fails result validation unless every consumer hand-writes a ResultClaim.
The extension surface (ClientExtension.claims()) supports this cleanly. I have a working implementation (~120 lines + tests, exercised against a spec-conformant 2026-07-28 server with server-directed task creation) that:
advertises io.modelcontextprotocol/tasks in per-request capabilities,
claims resultType: "task" on tools/call,
resolves the claim by polling tasks/get (honoring pollIntervalMs, including mid-task changes),
maps failed → a raised error carrying the server's JSON-RPC error, and cancelled → a distinct error,
sends best-effort tasks/cancel when the caller's scope is cancelled (shielded), per the spec's cooperative-cancellation model,
sets Mcp-Name to the taskId on tasks/* requests via name_param (the SEP-2663 routing-header requirement — the Request.name_param docstring in mcp-types already anticipates this).
Happy to send a PR — proposed location mcp/client/extensions/tasks.py. Two design questions I'd like a maintainer opinion on before polishing:
Should input_required tasks surface through the existing elicitation callback plumbing (with tasks/update as the response channel), or is that a follow-up?
Is transparent-polling-inside-call_tool the right default, or should the extension also expose the raw task handle for callers that want to manage polling themselves (e.g. UI progress)?
One porting note: the natural base for the wire models is MCPModel (camelCase alias generator), which mcp_types doesn't currently re-export — part of the value of upstreaming is resolving that properly.
I’ll add client-side support for the io.modelcontextprotocol/tasks extension by introducing the required task claims handling, including:
advertising the tasks capability in client requests
handling resultType: "task" responses from tools/call
polling task status through tasks/get
handling completed, failed, and cancelled task states
supporting cancellation with best-effort tasks/cancel
For the API design, I’ll keep call_tool backward compatible by resolving tasks transparently, while exposing a task handle API for consumers that need progress tracking or manual lifecycle control.
Thanks for writing this up. We're tracking the tasks extension under #2806, so I'm going to close this one as a duplicate to keep everything in one place. Feel free to continue the discussion there :)
Activity
Mahnoor-Zaffar commentedon Jul 31, 2026
Hey, looks like the task support isn't working right, I can add the necessary claims handling
Ecocitizenz commentedon Jul 31, 2026
Mahnoor-Zaffar commentedon Aug 2, 2026
I’d like to work on this implementation.
I’ll add client-side support for the io.modelcontextprotocol/tasks extension by introducing the required task claims handling, including:
advertising the tasks capability in client requests
handling resultType: "task" responses from tools/call
polling task status through tasks/get
handling completed, failed, and cancelled task states
supporting cancellation with best-effort tasks/cancel
For the API design, I’ll keep call_tool backward compatible by resolving tasks transparently, while exposing a task handle API for consumers that need progress tracking or manual lifecycle control.
maxisbey commentedon Oct 1, 2026
Thanks for writing this up. We're tracking the tasks extension under #2806, so I'm going to close this one as a duplicate to keep everything in one place. Feel free to continue the discussion there :)
AI Disclaimer