Is your feature request related to a problem? Please describe.
WithTasks creates a durable task record through IMcpTaskStore, but executes the tool in a process-local Task.Run.
This prevents servers from delegating task execution to durable systems such as Temporal, Orleans, Hangfire, or an external queue. A durable IMcpTaskStore preserves task state, but it cannot control how execution is started.
Replacing the call-tool handler is not a suitable alternative because it relies on experimental alternate-result APIs and replaces parts of the standard MCP tool pipeline.
Describe the solution you'd like
Add a stable extension point that allows WithTasks to delegate execution after the task record has been created.
The extension point should provide:
- The created task information, including task ID.
- The matched tool request and request context.
- Access to the normal tool invocation pipeline when local execution is desired.
- Clear ownership of request-scoped services and disposal.
- Defined ordering for authorization and request filters.
- Cancellation information.
The existing process-local behavior should remain the default.
A custom executor should be able to submit the task to an external durable runtime without invoking the tool body in the MCP server process. Existing tasks/get, tasks/update, and tasks/cancel handling should continue to use IMcpTaskStore.
The exact interface is open for discussion. Conceptually:
public interface IMcpTaskExecutor
{
ValueTask StartAsync(
McpTaskExecutionContext context,
CancellationToken cancellationToken);
}
Describe alternatives you've considered
- Custom
IMcpTaskStore: persists state but cannot replace the process-local execution mechanism.
- Custom
CallToolWithAlternateHandler: uses experimental APIs and replaces the normal tool pipeline.
- Forking or reimplementing
WithTasks: duplicates task negotiation, filtering, DI-scope, cancellation, and result-handling behavior.
- Keeping execution process-local: unsuitable for tasks that must survive server process replacement.
Additional context
The extension point should preserve existing behavior for applications that do not configure a custom executor.
A useful acceptance scenario would be:
- An MCP task is created.
- A custom executor submits it to an external durable runtime.
- The original MCP server process exits.
- Another server instance continues serving
tasks/get, tasks/update, and tasks/cancel.
- The task reaches a terminal state without depending on the original process.
Is your feature request related to a problem? Please describe.
WithTaskscreates a durable task record throughIMcpTaskStore, but executes the tool in a process-localTask.Run.This prevents servers from delegating task execution to durable systems such as Temporal, Orleans, Hangfire, or an external queue. A durable
IMcpTaskStorepreserves task state, but it cannot control how execution is started.Replacing the call-tool handler is not a suitable alternative because it relies on experimental alternate-result APIs and replaces parts of the standard MCP tool pipeline.
Describe the solution you'd like
Add a stable extension point that allows
WithTasksto delegate execution after the task record has been created.The extension point should provide:
The existing process-local behavior should remain the default.
A custom executor should be able to submit the task to an external durable runtime without invoking the tool body in the MCP server process. Existing
tasks/get,tasks/update, andtasks/cancelhandling should continue to useIMcpTaskStore.The exact interface is open for discussion. Conceptually:
Describe alternatives you've considered
IMcpTaskStore: persists state but cannot replace the process-local execution mechanism.CallToolWithAlternateHandler: uses experimental APIs and replaces the normal tool pipeline.WithTasks: duplicates task negotiation, filtering, DI-scope, cancellation, and result-handling behavior.Additional context
The extension point should preserve existing behavior for applications that do not configure a custom executor.
A useful acceptance scenario would be:
tasks/get,tasks/update, andtasks/cancel.