Skip to content

Resolve MCP handler services from the schema in stateless mode - #10379

Merged
glen-84 merged 3 commits into
mainfrom
gai/mcp-stateless-schema-services
Sep 10, 2026
Merged

glen-84 merged 3 commits into
mainfrom
gai/mcp-stateless-schema-services

Conversation

@glen-84

@glen-84 glen-84 commented Sep 10, 2026

Copy link
Copy Markdown
Member

Summary

  • The MCP request handlers resolved McpFeatureRegistry, IRequestExecutor, and IRootServiceProviderAccessor from RequestContext.Services. With HttpServerTransportOptions.Stateless = true the SDK builds the per-request server from the ASP.NET Core request scope, which does not contain those schema-scoped singletons, so every tools/list and tools/call failed against a stateless server.
  • The handlers now take the schema services as a parameter. McpSchemaServiceProvider is 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.
  • Stateful behavior is unchanged. All three services are schema-services singletons, so resolving them from the schema provider rather than from a per-request child scope returns the same instances.

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 let MapGraphQLMcp decide 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

  • Added ListTools_StatelessTransport_ReturnsTools and CallTool_StatelessTransport_ReturnsExpectedResult to IntegrationTestBase, so CoreIntegrationTests and FusionIntegrationTests both run them. Without the fix, tools/list fails with a remote handler error and tools/call returns an error result.
  • HotChocolate.Adapters.Mcp.Tests passes on net8.0, net9.0, net10.0, and net11.0, 258 tests each.

Copilot AI lite review requested due to automatic review settings September 10, 2026 15:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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 IServiceProvider wrapper (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/list and tools/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.

Comment thread src/HotChocolate/Adapters/src/Adapters.Mcp.Core/McpSchemaServiceProvider.cs Outdated
@github-actions

github-actions Bot commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

@glen-84
glen-84 merged commit 1735d83 into main Sep 10, 2026
151 checks passed
@glen-84
glen-84 deleted the gai/mcp-stateless-schema-services branch September 10, 2026 16:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants