Skip to content

Commit 82de9a6

Browse files
committed
Split StdioClient/ServerTransports into Stdio : Stream
1 parent 065e3c6 commit 82de9a6

14 files changed

+670
-690
lines changed

src/ModelContextProtocol.AspNetCore/McpEndpointRouteBuilderExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static class McpEndpointRouteBuilderExtensions
2727
/// <returns>Returns a builder for configuring additional endpoint conventions like authorization policies.</returns>
2828
public static IEndpointConventionBuilder MapMcp(this IEndpointRouteBuilder endpoints, Func<HttpContext, IMcpServer, CancellationToken, Task>? runSession = null)
2929
{
30-
ConcurrentDictionary<string, SseResponseStreamTransport> _sessions = new(StringComparer.Ordinal);
30+
ConcurrentDictionary<string, SseResponseSessionTransport> _sessions = new(StringComparer.Ordinal);
3131

3232
var loggerFactory = endpoints.ServiceProvider.GetRequiredService<ILoggerFactory>();
3333
var mcpServerOptions = endpoints.ServiceProvider.GetRequiredService<IOptions<McpServerOptions>>();
@@ -43,7 +43,7 @@ public static IEndpointConventionBuilder MapMcp(this IEndpointRouteBuilder endpo
4343
response.Headers.CacheControl = "no-store";
4444

4545
var sessionId = MakeNewSessionId();
46-
await using var transport = new SseResponseStreamTransport(response.Body, $"/message?sessionId={sessionId}");
46+
await using var transport = new SseResponseSessionTransport(response.Body, $"/message?sessionId={sessionId}");
4747
if (!_sessions.TryAdd(sessionId, transport))
4848
{
4949
throw new Exception($"Unreachable given good entropy! Session with ID '{sessionId}' has already been created.");

src/ModelContextProtocol/Protocol/Transport/SseResponseStreamTransport.cs renamed to src/ModelContextProtocol/Protocol/Transport/SseResponseSessionTransport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ namespace ModelContextProtocol.Protocol.Transport;
1313
/// </summary>
1414
/// <param name="sseResponseStream">The stream to write the SSE response body to.</param>
1515
/// <param name="messageEndpoint">The endpoint to send JSON-RPC messages to. Defaults to "/message".</param>
16-
public sealed class SseResponseStreamTransport(Stream sseResponseStream, string messageEndpoint = "/message") : ITransport
16+
public sealed class SseResponseSessionTransport(Stream sseResponseStream, string messageEndpoint = "/message") : ITransport
1717
{
1818
private readonly Channel<IJsonRpcMessage> _incomingChannel = CreateBoundedChannel<IJsonRpcMessage>();
1919
private readonly Channel<SseItem<IJsonRpcMessage?>> _outgoingSseChannel = CreateBoundedChannel<SseItem<IJsonRpcMessage?>>();
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Microsoft.Extensions.Logging;
2+
using ModelContextProtocol.Logging;
3+
using ModelContextProtocol.Protocol.Messages;
4+
using System.Diagnostics;
5+
6+
namespace ModelContextProtocol.Protocol.Transport;
7+
8+
/// <summary>Provides the client side of a stdio-based session transport.</summary>
9+
internal sealed class StdioClientSessionTransport : StreamClientSessionTransport
10+
{
11+
private readonly StdioClientTransportOptions _options;
12+
private readonly Process _process;
13+
14+
public StdioClientSessionTransport(StdioClientTransportOptions options, Process process, string endpointName, ILoggerFactory? loggerFactory)
15+
: base(process.StandardInput, process.StandardOutput, endpointName, loggerFactory)
16+
{
17+
_process = process;
18+
_options = options;
19+
}
20+
21+
/// <inheritdoc/>
22+
public override async Task SendMessageAsync(IJsonRpcMessage message, CancellationToken cancellationToken = default)
23+
{
24+
if (_process.HasExited)
25+
{
26+
Logger.TransportNotConnected(EndpointName);
27+
throw new McpTransportException("Transport is not connected");
28+
}
29+
30+
await base.SendMessageAsync(message, cancellationToken).ConfigureAwait(false);
31+
}
32+
33+
/// <inheritdoc/>
34+
protected override ValueTask CleanupAsync(CancellationToken cancellationToken)
35+
{
36+
StdioClientTransport.DisposeProcess(_process, processStarted: true, Logger, _options.ShutdownTimeout, EndpointName);
37+
38+
return base.CleanupAsync(cancellationToken);
39+
}
40+
}

src/ModelContextProtocol/Protocol/Transport/StdioClientStreamTransport.cs

Lines changed: 0 additions & 326 deletions
This file was deleted.

0 commit comments

Comments
 (0)