Repository navigation
Resolve MCP handler services from the schema in stateless mode - #10379
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
McpSchemaServiceProvider currently allows unguarded rebinding and can be accessed before binding, which can lead to confusing DI failures or subtle concurrency issues.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR fixes MCP request handling when HttpServerTransportOptions.Stateless = true by ensuring MCP handlers resolve schema-scoped singletons from the schema service provider (instead of the ASP.NET Core request scope), preventing tools/list and tools/call failures in stateless mode.
Changes:
- Introduced a schema-bound
IServiceProviderwrapper (McpSchemaServiceProvider) and wired MCP handlers to use it for schema-scoped service resolution. - Updated MCP handler signatures and server builder registrations to pass schema services explicitly.
- Added stateless HTTP transport integration tests (plus snapshot coverage) for
tools/listandtools/call.
File summaries
| File | Description |
|---|---|
| src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/IntegrationTestBase.cs | Adds integration tests validating stateless tools/list and tools/call behavior. |
| src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/Handlers/CallToolHandlerTests.cs | Updates unit tests to pass schema services into the handler after signature change. |
| src/HotChocolate/Adapters/test/Adapters.Mcp.Tests/snapshots/IntegrationTestBase.CallTool_StatelessTransport_ReturnsExpectedResult.json | Adds snapshot for the stateless tools/call result payload. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/McpSchemaServiceProvider.cs | Adds schema-scoped service provider wrapper used by handlers. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Handlers/ReadResourceHandler.cs | Resolves McpFeatureRegistry from schema services instead of request scope services. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Handlers/ListToolsHandler.cs | Switches handler to operate directly on schema services. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Handlers/ListPromptsHandler.cs | Switches handler to operate directly on schema services. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Handlers/GetPromptHandler.cs | Resolves prompt registry from schema services via parameter. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Handlers/CallToolHandler.cs | Resolves registry/executor/root accessor from schema services to support stateless mode. |
| src/HotChocolate/Adapters/src/Adapters.Mcp.Core/Extensions/ServiceCollectionExtensions.cs | Binds schema services once and passes them into MCP handler registrations. |
Review details
- Files reviewed: 10/10 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Patch coverage100.0% of changed lines covered (39/39)
Project coverage: 57.9% (288221/497814 lines) |
Summary
McpFeatureRegistry,IRequestExecutor, andIRootServiceProviderAccessorfromRequestContext.Services. WithHttpServerTransportOptions.Stateless = truethe SDK builds the per-request server from the ASP.NET Core request scope, which does not contain those schema-scoped singletons, so everytools/listandtools/callfailed against a stateless server.McpSchemaServiceProvideris bound to the schema services when the MCP server options are built, which holds in both stateful and stateless mode, and one instance is created per schema-services build so it follows schema swaps.Stateless mode is opted into with
AddMcp(configureServer: b => b.WithHttpTransport(o => o.Stateless = true)). A first-class HotChocolate option for it, which would also letMapGraphQLMcpdecide the GET and DELETE endpoint mapping without building the schema, is a separate change.Reported in #10376, which also asks for the move to v2 of the MCP C# SDK; that update is not part of this change.
Test plan
ListTools_StatelessTransport_ReturnsToolsandCallTool_StatelessTransport_ReturnsExpectedResulttoIntegrationTestBase, soCoreIntegrationTestsandFusionIntegrationTestsboth run them. Without the fix,tools/listfails with a remote handler error andtools/callreturns an error result.HotChocolate.Adapters.Mcp.Testspasses on net8.0, net9.0, net10.0, and net11.0, 258 tests each.