This week my biggest win was the creation of a bridge between the .NET MCP SDK and a custom HTTP stack.
The relevant MCP SDK classes
For the implementation I required an interface to get the JSON RPC messages from the HTTP body to the MCP server. I didn't want to implement the complete MCP Server from the ground up so I use the server fromt the SDK.
The creation is handled by the static method McpServerFactory.Create()
.
The method accepts four parameters:
-
ITransport
- Represents a channel that the MCP server uses to read and writeJsonRpcMessages
. -
McpServerOptions
- Configuration for the MCP server like available tools, prompts or the server name and version. -
ILoggerFactory
(optional) - Provides logging capabilities to MCP stack -
IServiceProvider
(optional) - Not important for this system
This method returns an instance of the McpServer
class which implements the IMcpServer
interface. We can use the RunAsync()
method to run the MCP stack which basically represents a long-running task which continuesly reads and process JsonRpcMessages and writes the response back to the transport.
We run two tasks on different ThreadPool
-Threads. The HttpServer task to process http requests and the McpServer task to process JsonRPC requests.
Problem: How to get the JSON messages from the HTTP body to the MCP server?
Channels
A channel represents a tunnle from one thread to another allowing the sender thread to write data into it. The other thread can then read the data.
The channel is basically a queue using the FIFO principle which means the first message that was written to the channel is the first one consumed on the other thread.
For our problem we need two channels:
- One sending from the HTTP thread to the MCP thread
- Another sending the MCP response back to the HTTP thread
The 'ITransport' provides two entities that fit very good to this concept. A ChannelReader<JsonRpcMessage>
which allows the MCP server to read the JSON RPC requests and the SendMessageAsync
to write a RPC response.
So we just give the Reader from the HttpToMcp
channel to our custom ITransport
implementation and the Writer from the McpToHttp
channel is used in the SendMessageAsync
. The counterpart (HTTP thread) is reading the RPC messages from the body and enqueue them in the HttpToMcp
channel. The reader from the other channel is used in the HTTP thread and then writes the JsonRpcMessages to the NetworkStream
.
Conclusion
This project is not finished yet and is just a stateless implementation but I learned a lot:
- How works the .NET MCP SDK
- What is streamable HTTP
- What is the streamable HTTP MCP transport
- How works the custom HTTP-Stack
- .NET Channels
- A better understanding for Multi-Threading
Top comments (0)