You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
How do I resolve an instance of IMcpServer when using WithHttpTransport? #768
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.
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
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
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.
@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:
@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:
@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?
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 IMcpServerinterface 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("...")]publicasyncTask<string>MyTool(Kernelkernel/*, your args */){varrequest=kernel.Services.GetRequiredService<RequestContext<CallToolRequestParams>>();varserver=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?
Activity
mikekistler commentedon Sep 14, 2025
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.
jamespchadwick commentedon Sep 14, 2025
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
HttpContextto anIMcpServer.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
PederHP commentedon Sep 14, 2025
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 useRunSessionHandler:https://github.com/modelcontextprotocol/csharp-sdk/blob/main/src/ModelContextProtocol.AspNetCore/HttpServerTransportOptions.cs#L17
Then you get your mapping from
HttpContexttoIMcpServer. 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.
mikekistler commentedon Sep 14, 2025
@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
jamespchadwick commentedon Sep 14, 2025
@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 callsMcpServerTool.Createand passes it anAIFunctionBased 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
I had also considered implementing a custom
WithCallToolHandlerso that I could attempt to access theIMcpServerby way of theRequestContext@PederHP, this was very helpful! If I implement a custom
RunSessionHandler, I can see an instantiated instance ofIMcpServerwhen 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 theIMcpServerwhen calling my tool.When it comes to stdio, this comment leads me to believe that an
IMcpServerinstance is registered with the DI container and reused because there's only ever one client. Are there patterns or guidance for how to manageIMcpServerinstances when using Streamable HTTP?jeffhandley commentedon Jul 14, 2026
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
IMcpServerinterface was replaced by theMcpServerabstract class (andIMcpEndpoint→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 viaMcpServerTool.Create(function), you can add aKernelparameter and resolve fromkernel.Services:For a plain
AIFunctionFactory.Createtool (no Semantic Kernel), take anAIFunctionArguments argsparameter and useargs.Services.GetRequiredService<…>().In a minimal repro on
ModelContextProtocol1.4.1 against a Streamable HTTP server, both a plain AIFunction tool and an SK[KernelFunction]resolved the per-callMcpServer(a request-scopedDestinationBoundMcpServer) andRequestContext<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?