-
Notifications
You must be signed in to change notification settings - Fork 664
Description
Describe the bug
When a tool method uses [TaskSupport = ToolTaskSupport.Required]
The framework's ExecuteToolAsTaskAsync disposes the request-scoped IServiceProvider before attempting to instantiate the tool class via DI. This happens regardless of whether IMcpTaskStore is registered as a singleton, because the RequestServiceProvider wrapper throws when its underlying scope is disposed.
This also affects static methods with IMcpTaskStore as a method parameter — any DI resolution goes through the disposed RequestServiceProvider.
To Reproduce
Create an ASP.NET Core MCP server with HTTP transport
Implement a custom IMcpTaskStore
Call the tool via an MCP client with task metadata
Expected behavior
The tool should be invoked successfully. The framework should either:
Not dispose the request IServiceProvider before invoking the tool in ExecuteToolAsTaskAsync, or
Resolve DI services from the root IServiceProvider (not the request-scoped one) when executing tools as tasks, or
Document that TaskSupport = Required is incompatible with tools that return McpTask (explicit task creation pattern)
Logs
Additional context
Package version: ModelContextProtocol 1.1.0 / ModelContextProtocol.AspNetCore 1.1.0
Target framework: net8.0
Transport: HTTP (Streamable HTTP via .WithHttpTransport())
Workarounds attempted:
Registering IMcpTaskStore as singleton → still fails (disposed scope wrapper)
Making the method static with IMcpTaskStore as method parameter → still fails (same RequestServiceProvider disposal)
Using a static property set at startup (bypassing DI entirely) → avoids the exception but task status is never updated by the framework
Removing TaskSupport = Required and keeping just [McpServerTool] with McpTask return type works on v1.0.0 but not on v1.1.0
The docs example for explicit task creation uses constructor injection with IMcpTaskStore, which triggers this bug when TaskSupport = Required is set