Skip to content

[Schema][Client][Server] Add the Tasks extension (SEP-2663) - #428

Open
chr-hertel wants to merge 1 commit into
modelcontextprotocol:mainfrom
chr-hertel:feat-ext-tasks
Open

[Schema][Client][Server] Add the Tasks extension (SEP-2663)#428
chr-hertel wants to merge 1 commit into
modelcontextprotocol:mainfrom
chr-hertel:feat-ext-tasks

Conversation

@chr-hertel

@chr-hertel chr-hertel commented Aug 17, 2026

Copy link
Copy Markdown
Member
Q A
Bug fix? no
New feature? yes
Docs? yes
Issues Closes #345, #346, #347, #348, #349 — refs #335

Adds io.modelcontextprotocol/tasks (SEP-2663), server and client, without the core learning about it.

Generic seams (core, extension-agnostic)

  • MethodProvidingExtensionInterface: an extension's message classes go to the MessageFactory, its handlers to the server, via Builder::enableExtension().
  • ArgumentProvidingExtensionInterface: an extension hands handlers objects of its own — injected by ReferenceHandler like a RequestContext, left out of generated input schemas by SchemaGenerator.
  • CallToolHandler / GetPromptHandler / ReadResourceHandler pass any ResultInterface a handler returns through untouched.
  • MissingRequiredClientCapabilityException thrown from handler code is answered as -32021 (handlers and Protocol).
  • Client::request() sends any request; the typed API is unchanged.
  • Response / RequestHandlerInterface covariant in their result type; extension settings serialize as {} rather than [] when empty.

Tasks extension (on those seams)

  • Schema: Task (fromArray()), TaskStatus, ResultType::Task, CreateTaskResult / TaskResult (flat), TasksGet/Update/CancelRequest.
  • TasksExtension (Server\Task): tasks/get / tasks/update / tasks/cancel handlers gated with -32021, TaskStoreInterface with InMemoryTaskStore (bounded) and Psr16TaskStore, and a TaskContext provided to handlers: isSupported(), create() (stores before handing out; refuses undeclared clients), getStore(). Advancing a task is the application's job.
  • Client: Client\Builder::enableExtension(new TasksExtension()) declares it; Client\Task\TaskClient speaks it — callTool() / getPrompt() / readResource() returning CreateTaskResult when the server answered with a task, get() / update() / cancel().
  • tests/Integration/TasksTest runs the loop against a stdio fixture: handle → poll → completed, input_requiredupdate → completed, failed, cancel, both -32021 refusals, sync fallback, unknown task, prompt-as-task.
  • Docs in docs/extensions.md (server and client), CHANGELOG.

Design decisions vs. the original issue sketches are recorded in the rewritten #345#349.

@chr-hertel
chr-hertel force-pushed the feat-ext-tasks branch 2 times, most recently from 8f72d47 to 027d67d Compare August 17, 2026 23:55
@chr-hertel chr-hertel changed the title [Schema][Server] Add the Tasks extension (SEP-2663) [Schema][Client][Server] Add the Tasks extension (SEP-2663) Aug 17, 2026
`io.modelcontextprotocol/tasks`: `Task` and `TaskStatus`, `ResultType::Task`,
the `CreateTaskResult` / `TaskResult` wire shapes, the `tasks/get` /
`tasks/update` / `tasks/cancel` handlers behind `TasksExtension`,
`TaskStoreInterface` with in-memory and PSR-16 stores, and a `TaskContext`
handed to handlers for creating tasks — refused with -32021 for a client that
did not declare the extension.

The core stays extension-agnostic: `MethodProvidingExtensionInterface` and
`ArgumentProvidingExtensionInterface` let an extension register its messages,
handlers and injectable handler arguments; the core handlers pass any
`ResultInterface` through; a `MissingRequiredClientCapabilityException` from
handler code becomes -32021; `Client::request()` sends any request. On the
client, `TaskClient` speaks the extension. Covered end to end by an integration
test against a stdio fixture server. Extension settings serialize as `{}`
rather than `[]` when empty.
chr-hertel added a commit to chr-hertel/php-sdk that referenced this pull request Aug 18, 2026
Squashed WIP: the modern (SEP-2575) stateless lifecycle end to end - server
dispatcher, per-era wire codec, standard header validation, multi round-trip
requests, subscriptions, cache policy, the generic extensions framework, and a
client that speaks it. Tasks (SEP-2663) is carved out to modelcontextprotocol#428. To be decomposed
before review.
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.

[Schema] SEP-2663 Tasks: Task shape, resultType discriminator, tasks/* request/result types

1 participant