Skip to content

fix: disable InMemoryMcpTaskStore to avoid ObjectDisposedException (upstream SDK bug)#411

Merged
jongalloway merged 2 commits intomainfrom
fix/disable-task-store-di-scope-bug
Mar 18, 2026
Merged

fix: disable InMemoryMcpTaskStore to avoid ObjectDisposedException (upstream SDK bug)#411
jongalloway merged 2 commits intomainfrom
fix/disable-task-store-di-scope-bug

Conversation

@jongalloway
Copy link
Copy Markdown
Owner

Problem

MCP SDK v1.1.0's ExecuteToolAsTaskAsync disposes the request-scoped IServiceProvider before the background task resolves services, causing ObjectDisposedException on every tool call when InMemoryMcpTaskStore is registered — not just dotnet_project, but also dotnet_solution and any other tool the client invokes.

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
   at McpServerBuilderExtensions.CreateTarget(IServiceProvider services, Type type)
   at McpServerImpl.ExecuteToolAsTaskAsync...

Root Cause

This is an upstream SDK bug: modelcontextprotocol/csharp-sdk#1430

Fix

Comment out InMemoryMcpTaskStore registration. Without a task store, the SDK runs all tools synchronously inline — reliable and compatible with all clients.

  • Program.cs: commented-out registration with TODO and upstream link
  • DotNetCliTools.Misc.cs: AsyncTasks = false in ServerCapabilities
  • McpConformanceTests.cs: task lifecycle tests replaced with graceful degradation tests
  • ServerCapabilitiesTests.cs: updated assertions

TaskSupport = ToolTaskSupport.Optional is kept on dotnet_project so it's ready to activate when the upstream fix ships.

Tracking issue: #410

Testing

55/55 conformance + capabilities tests pass.

MCP SDK v1.1.0's ExecuteToolAsTaskAsync disposes the request-scoped
IServiceProvider before the background task resolves services, causing
ObjectDisposedException on every tool call when a task store is registered.

Comment out InMemoryMcpTaskStore registration until the upstream SDK
fixes the DI scope lifetime issue.

Upstream: modelcontextprotocol/csharp-sdk#1430

TaskSupport = Optional is kept on dotnet_project so the attribute is
ready to activate when the store is re-enabled.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Disables MCP Task support in the .NET MCP server as a workaround for an upstream MCP SDK v1.1.0 DI scope disposal bug that triggers ObjectDisposedException during tool execution.

Changes:

  • Commented out InMemoryMcpTaskStore registration to force synchronous tool execution.
  • Updated dotnet_server_capabilities to report supports.asyncTasks = false.
  • Adjusted conformance/capabilities tests to validate graceful degradation (no tasks capability advertised) and updated assertions.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
DotNetMcp/Program.cs Disables task store registration with TODO + upstream issue reference.
DotNetMcp/Tools/Cli/DotNetCliTools.Misc.cs Reports AsyncTasks = false in server capabilities output.
DotNetMcp.Tests/Server/McpConformanceTests.cs Replaces task lifecycle tests with degradation/synchronous execution checks.
DotNetMcp.Tests/Server/ServerCapabilitiesTests.cs Updates assertions to expect asyncTasks to be false.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines +72 to +74
Telemetry = true, // SDK v0.6+ supports request duration logging and OpenTelemetry semantic conventions
Metrics = true, // In-memory per-tool metrics via MCP message filter (dotnet_server_metrics tool)
AsyncTasks = true, // MCP Task support enabled: long-running operations (build, test, publish) can run as async tasks
AsyncTasks = false, // Disabled: MCP SDK DI scope bug (https://github.com/modelcontextprotocol/csharp-sdk/issues/1430)
Comment on lines +744 to +746
// Assert - the tool attribute declares TaskSupport = Optional so it's ready when
// task support is enabled via Features:EnableTaskSupport. Without a task store
// registered, the SDK runs it synchronously inline (graceful degradation).
@jongalloway
Copy link
Copy Markdown
Owner Author

@copilot

…ding comment

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 18, 2026

@copilot

Addressed both review comments in commit 5117fca:

  1. DotNetCliTools.Misc.cs – Added optional IMcpTaskStore? parameter to the DotNetCliTools constructor and stored it in _taskStore. AsyncTasks is now derived at runtime from _taskStore != null, so dotnet_server_capabilities always reflects the actual DI configuration and can't drift when the task store is re-enabled.

  2. McpConformanceTests.cs – Replaced the non-existent "Features:EnableTaskSupport" reference with a direct mention of un-commenting the IMcpTaskStore registration in Program.cs and the upstream SDK issue link.

All 55 conformance + capabilities tests continue to pass.

@jongalloway jongalloway merged commit d282b1c into main Mar 18, 2026
4 checks passed
@jongalloway jongalloway deleted the fix/disable-task-store-di-scope-bug branch March 18, 2026 03:15
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.

3 participants