Skip to content

Unify service configuration for ISseEventStreamStore, IMcpTaskStore, and ISessionMigrationHandler#1362

Merged
jeffhandley merged 6 commits intomainfrom
mbuck/unified-configuration
Feb 24, 2026
Merged

Unify service configuration for ISseEventStreamStore, IMcpTaskStore, and ISessionMigrationHandler#1362
jeffhandley merged 6 commits intomainfrom
mbuck/unified-configuration

Conversation

@MackinnonBuck
Copy link
Collaborator

@MackinnonBuck MackinnonBuck commented Feb 23, 2026

Motivation

Three service interfaces had inconsistent configuration patterns:

  • ISseEventStreamStore could only be set via HttpServerTransportOptions.EventStreamStore inside the WithHttpTransport callback. This made it awkward to configure a DistributedCacheEventStreamStore that got its IDistributedCache from DI.

  • IMcpTaskStore could be set via McpServerOptions.TaskStore, but if set, the SDK then reverse-registered it as a DI singleton.

  • ISessionMigrationHandler was resolved exclusively from DI, with no options-based configuration at all.

What changed

All three now follow the same pattern:

  1. Each has a property on the relevant options object (HttpServerTransportOptions or McpServerOptions).
  2. If the property is not explicitly set, an IConfigureOptions implementation automatically populates it from DI.
  3. Explicit options always take precedence over DI.

How to use

ISseEventStreamStore: Register a distributed cache in DI, then call WithDistributedCacheEventStreamStore():

builder.Services.AddDistributedMemoryCache();
builder.Services
    .AddMcpServer()
    .WithHttpTransport()
    .WithDistributedCacheEventStreamStore();

To customize store options:

    .WithDistributedCacheEventStreamStore(options =>
    {
        options.EventSlidingExpiration = TimeSpan.FromMinutes(10);
    });

To use a specific IDistributedCache instance (e.g., when multiple caches are registered):

    .WithDistributedCacheEventStreamStore(options =>
    {
        options.Cache = mySpecificCache;
    });

IMcpTaskStore and ISessionMigrationHandler: Register an implementation in DI and it will be picked up automatically:

builder.Services.AddSingleton<IMcpTaskStore, MyCustomTaskStore>();
builder.Services.AddSingleton<ISessionMigrationHandler, MyMigrationHandler>();
builder.Services
    .AddMcpServer()
    .WithHttpTransport();
// Both are automatically resolved from DI into the options

Or set them directly on options (explicit values always win):

builder.Services
    .AddMcpServer(options => options.TaskStore = myTaskStore)
    .WithHttpTransport(options => options.SessionMigrationHandler = myHandler);

@jeffhandley jeffhandley added this to the 1.0.0 (GA) milestone Feb 24, 2026
halter73
halter73 previously approved these changes Feb 24, 2026
@jeffhandley jeffhandley added the breaking-change This issue or PR introduces a breaking change label Feb 24, 2026
jeffhandley
jeffhandley previously approved these changes Feb 24, 2026
stephentoub
stephentoub previously approved these changes Feb 24, 2026
mikekistler
mikekistler previously approved these changes Feb 24, 2026
Copy link
Contributor

@mikekistler mikekistler left a comment

Choose a reason for hiding this comment

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

I really like the simplicity and consistency of the new API shape.

I can't judge the implementation but from an externals POV this looks good! 👍

Copy link
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

This PR unifies the service configuration pattern for ISseEventStreamStore, IMcpTaskStore, and ISessionMigrationHandler to follow a consistent dependency injection approach. Previously, these three services had inconsistent configuration patterns - ISseEventStreamStore was only settable via options callbacks, IMcpTaskStore used reverse-registration into DI, and ISessionMigrationHandler was only resolvable from DI. Now all three follow the same pattern: configurable via an options property with automatic fallback to DI resolution when not explicitly set, with explicit values always taking precedence.

Changes:

  • Unified service configuration pattern: all three services now support both explicit options-based configuration and automatic DI resolution via IConfigureOptions
  • Refactored DistributedCacheEventStreamStore to use IOptions<DistributedCacheEventStreamStoreOptions> pattern with new Cache property
  • Added WithDistributedCacheEventStreamStore() extension method for simplified configuration

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/ModelContextProtocol/Server/DistributedCacheEventStreamStore.cs Changed constructor to accept IOptions<DistributedCacheEventStreamStoreOptions> instead of IDistributedCache directly
src/ModelContextProtocol/Server/DistributedCacheEventStreamStoreOptions.cs Added Cache property to hold the IDistributedCache instance
src/ModelContextProtocol/McpServerOptionsSetup.cs Added IMcpTaskStore parameter and auto-population logic for TaskStore property
src/ModelContextProtocol/McpServerServiceCollectionExtensions.cs Removed reverse-registration of IMcpTaskStore from options
src/ModelContextProtocol.AspNetCore/HttpServerTransportOptions.cs Added SessionMigrationHandler property with documentation
src/ModelContextProtocol.AspNetCore/HttpServerTransportOptionsSetup.cs New: Configures EventStreamStore and SessionMigrationHandler from DI
src/ModelContextProtocol.AspNetCore/DistributedCacheEventStreamStoreOptionsSetup.cs New: Configures Cache property from DI
src/ModelContextProtocol.AspNetCore/DistributedCacheEventStreamStoreOptionsValidator.cs New: Validates that Cache is set with helpful error message
src/ModelContextProtocol.AspNetCore/HttpMcpServerBuilderExtensions.cs Added WithDistributedCacheEventStreamStore() extension method
src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs Updated to use SessionMigrationHandler from options instead of constructor parameter
tests/ModelContextProtocol.Tests/Server/DistributedCacheEventStreamStoreTests.cs Updated all tests to use new constructor signature with CreateStore helper method
tests/ModelContextProtocol.Tests/Configuration/McpServerOptionsSetupTests.cs Added comprehensive tests for TaskStore DI resolution and precedence
tests/ModelContextProtocol.AspNetCore.Tests/HttpMcpServerBuilderExtensionsTests.cs New: Comprehensive tests for EventStreamStore and SessionMigrationHandler configuration patterns
tests/ModelContextProtocol.AspNetCore.Tests/DistributedCacheResumabilityIntegrationTests.cs Updated to use new constructor with Cache property in options
tests/ModelContextProtocol.ConformanceServer/Program.cs Updated to use simplified WithDistributedCacheEventStreamStore() pattern

@jeffhandley jeffhandley merged commit 669c36b into main Feb 24, 2026
14 checks passed
@jeffhandley jeffhandley deleted the mbuck/unified-configuration branch February 24, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking-change This issue or PR introduces a breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants