feat: MVC controller support#1311
Open
jtarquino wants to merge 1 commit intomodelcontextprotocol:mainfrom
Open
feat: MVC controller support#1311jtarquino wants to merge 1 commit intomodelcontextprotocol:mainfrom
jtarquino wants to merge 1 commit intomodelcontextprotocol:mainfrom
Conversation
halter73
reviewed
Feb 19, 2026
Contributor
There was a problem hiding this comment.
@mikekistler @stephentoub Do you have any opinions on introducing a public API like the following for use in custom endpoints like controller actions?
namespace ModelContextProtocol.AspNetCore;
public interface IStreamableHttpHandler
{
Task HandlePostRequestAsync(HttpContext context);
Task HandleGetRequestAsync(HttpContext context);
Task HandleDeletetRequestAsync(HttpContext context);
}
// Or just
public interface IStreamableHttpHandler
{
Task HandleRequest(HttpContext);
}
// Or maybe instead of registering it as a singleton, we could have a factory
public static class McpRequestDelegateFactory
{
public RequestDelegate Create(McpServerOptions? serverOptions = null,
HttpServerTransportOptions? transportOptions = null,
IServiceProvider? applicationServices = null);
}I was hesitant to do this right after MCP's transition from "HTTP+SSE" to "Streamable HTTP" as the web-based transport, because I wasn't sure if a new kind of transport would cause us to want to create a completely different kind of interface.
I'm leaning towards my last proposal with the factory. I think having a way to create a RequestDelegate from McpServerOptions makes a lot of sense though. It's very general, so long as you can handle the routing without any input from the SDK. It reminds me a bit of RequestDelegateFactory.Create
6bedd92 to
8b5f0a7
Compare
Make StreamableHttpHandler public so it can be injected into traditional ASP.NET Core MVC controllers, enabling MCP server scenarios without minimal APIs. Changes: - StreamableHttpHandler: internal -> public, constructor takes IServiceProvider - Updated WithHttpTransport() XML docs to mention controller injection - Added 'Using with MVC Controllers' section to AspNetCore README - New sample: AspNetCoreMcpControllerServer - New integration tests: McpControllerTests (connect, call tool, list tools) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8b5f0a7 to
d25782f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
McpRequestDelegateFactory— a static factory that creates aRequestDelegatefor handling MCP Streamable HTTP transport requests. This enables MCP integration with traditional MVC controllers and other request-handling patterns without requiring minimal APIs (MapMcp()).Motivation and Context
The
ModelContextProtocol.AspNetCorepackage currently only exposes MCP HTTP endpoints viaMapMcp()— a minimal API extension method. Users whose applications rely on traditional MVC controllers (AddControllers()+MapControllers()) cannot integrate MCP without also adopting minimal APIs. This change adds aMcpRequestDelegateFactory.Create()method that returns a standardRequestDelegate, following the same pattern as ASP.NET Core's ownRequestDelegateFactory.Usage
How Has This Been Tested?
McpControllerTests) covering connect, tool call, and tool listing via an MVC controller — all passing on net9.0.initialize,notifications/initialized,tools/list, andtools/call(echo) via HTTP POST against the MVC controller endpoint.Breaking Changes
None. This is a purely additive change — a new public static class
McpRequestDelegateFactoryis added. No existing APIs were modified.Types of changes
Checklist
Additional context
McpRequestDelegateFactory) instead of exposing the handler directly or via an interface. This approach is future-proof — if the MCP transport changes, theRequestDelegateabstraction remains stable.StreamableHttpHandlerremainsinternalwith its original primary constructor — no internal types are exposed.samples/AspNetCoreMcpControllerServer/) demonstrates the pattern.