Skip to content

How do I resolve an instance of IMcpServer when using WithHttpTransport? #768

Open

Description

@jamespchadwick

Consider this example repository, which implements an MCP server communicating over Streamable HTTP and uses Semantic Kernel.

This example draws inspiration from

When I try to implement this example of sampling from the Semantic Kernel demo, I encounter the following exception (described in Issue #564)

System.InvalidOperationException: Unable to resolve service for type 'ModelContextProtocol.Server.IMcpServer'

Question
How do I correctly resolve an instance of the IMcpServer when using WithHttpTransport? Is there a recommended pattern?

Activity

  1. mikekistler commented on Sep 14, 2025

    @mikekistler
    Contributor

    I have a sample project that illustrates how to get the HttpContext for a request:

    https://github.com/mikekistler/mcp-howto/tree/main/HttpContext

    I've been planning to add this to the formal docs and just hadn't gotten to that yet. Please let me know if the doc / code in this sample is clear and I'll prioritize moving it to the docs.

  2. jamespchadwick commented on Sep 14, 2025

    @jamespchadwick
    Author

    Hi @mikekistler ! I really appreciate the response.

    The sample you provided is clear, but I'm having a hard time wrapping my head around how I can go from the HttpContext to an IMcpServer.

    I realized my initial question may not have been entirely clear, and that I should have also linked to this example of sampling from the Semantic Kernel repository that I'm trying to emulate.

    I understand when using stdio transport, there's only going to be one client / IMcpServer (as indicated in this comment by @stephentoub ), but I'm still having a hard time understanding how to implement sampling when using Streamable HTTP transport since there can be multiple sessions/clients

  3. PederHP commented on Sep 14, 2025

    @PederHP
    Member

    Hi @mikekistler ! I really appreciate the response.

    The sample you provided is clear, but I'm having a hard time wrapping my head around how I can go from the HttpContext to an IMcpServer.

    I realized my initial question may not have been entirely clear, and that I should have also linked to this example of sampling from the Semantic Kernel repository that I'm trying to emulate.

    I understand when using stdio transport, there's only going to be one client / IMcpServer (as indicated in this comment by @stephentoub ), but I'm still having a hard time understanding how to implement sampling when using Streamable HTTP transport since there can be multiple sessions/clients

    If you look at this sample, which isn't entirely what you want:
    https://github.com/modelcontextprotocol/csharp-sdk/blob/main/samples/AspNetCoreMcpPerSessionTools/Program.cs

    And instead of using ConfigureSessionOptions (which only gives the options), you use RunSessionHandler:
    https://github.com/modelcontextprotocol/csharp-sdk/blob/main/src/ModelContextProtocol.AspNetCore/HttpServerTransportOptions.cs#L17

    Then you get your mapping from HttpContext to IMcpServer. However, setting this means that the default handler isn't used:
    https://github.com/modelcontextprotocol/csharp-sdk/blob/main/src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs#L241

    So I am not sure if this will actually work in practice. You can try it out. But I agree it should be easier in a Streamable HTTP Server to use Sampling from inside a Tool for example.

    Maybe you can resolve it like this:
    https://github.com/modelcontextprotocol/csharp-sdk/blob/d344c651203841ec1c9e828736d234a6e4aebd07/samples/EverythingServer/Tools/SampleLlmTool.cs

    But I'm unsure if this will work outside of a Stdio server.

  4. mikekistler commented on Sep 14, 2025

    @mikekistler
    Contributor

    @jamespchadwick Sorry ... I guess I misread your question. If what you want is the IMcpServer, I think you just include this in the parameter list of your tool method (or other handler). Here's a link to how this is done:

    https://github.com/mikekistler/mcp-howto/blob/main/Elicitation/server/Tools/InteractiveTools.cs#L16

  5. jamespchadwick commented on Sep 14, 2025

    @jamespchadwick
    Author

    @jamespchadwick Sorry ... I guess I misread your question. If what you want is the IMcpServer, I think you just include this in the parameter list of your tool method (or other handler). Here's a link to how this is done:

    https://github.com/mikekistler/mcp-howto/blob/main/Elicitation/server/Tools/InteractiveTools.cs#L16

    @mikekistler I already tried this with no success.

    I should point out that because I'm using Semantic Kernel for orchestration, my tools aren't decorated with [McpServerTool]. The tools are implemented as Semantic Kernel [KernelFunction]s, and when I'm registering services, I'm using a simplified version of what was implemented in the Semantic Kernel demo, which calls McpServerTool.Create and passes it an AIFunction

    Based on this comment, I understand that the IMcpServer isn't registered with the DI Container, but this comment led me to believe that the sdk would handle injecting the dependency and bind them to the arguments for the tool function

    The IMcpServer is not coming from the DI container, and hence doesn't work. We use ActivatorUtilities.CreateInstance, and have not done work to enable injecting other things. For methods, IMcpServer, CancellationToken, and a few other types are manually handled to support binding them to the arguments of the methods.

    I had also considered implementing a custom WithCallToolHandler so that I could attempt to access the IMcpServer by way of the RequestContext

    @PederHP, this was very helpful! If I implement a custom RunSessionHandler, I can see an instantiated instance of IMcpServer when attempting to connect to the server via Mcp Inspector, but since this is happening when I attempt to connect, and not when I attempt to call the tool, I'm trying to understand how I'd be able to resolve the IMcpServer when calling my tool.

    When it comes to stdio, this comment leads me to believe that an IMcpServer instance is registered with the DI container and reused because there's only ever one client. Are there patterns or guidance for how to manage IMcpServer instances when using Streamable HTTP?

  6. jeffhandley commented on Jul 14, 2026

    @jeffhandley
    Contributor

    Apologies this sat unanswered for so long — that's on us, and thank you for the thorough write-up.

    Since you filed this we restructured the endpoint/client/server types (#723): the IMcpServer interface was replaced by the McpServer abstract class (and IMcpEndpoint → McpSession, McpClientFactory.CreateAsync → McpClient.CreateAsync). So the exact APIs you were wrestling with have since changed, and we're honestly not sure whether you're still blocked — but here's an approach that might work for your scenario.

    The idea is to reach the server at tool-call time from the request-scoped service provider the SDK passes into each invocation, rather than from the root container (which is why it wasn't resolvable there).

    For a Semantic Kernel [KernelFunction] registered via McpServerTool.Create(function), you can add a Kernel parameter and resolve from kernel.Services:

    [KernelFunction, Description("...")]
    public async Task<string> MyTool(Kernel kernel /*, your args */)
    {
        var request = kernel.Services.GetRequiredService<RequestContext<CallToolRequestParams>>();
        var server  = request.Server;   // the per-call McpServer (formerly IMcpServer)
        // request.Params, server.SendNotificationAsync(...), elicitation, sampling, ...
    }

    For a plain AIFunctionFactory.Create tool (no Semantic Kernel), take an AIFunctionArguments args parameter and use args.Services.GetRequiredService<…>().

    In a minimal repro on ModelContextProtocol 1.4.1 against a Streamable HTTP server, both a plain AIFunction tool and an SK [KernelFunction] resolved the per-call McpServer (a request-scoped DestinationBoundMcpServer) and RequestContext<CallToolRequestParams> this way — though your full Semantic Kernel configuration may differ from my minimal test.

    Are you still working on this, or can we consider it resolved on current bits?

  7. added this to the 2.x milestone on Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs confirmationUnclear if still relevantquestionFurther information is requested

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions