Refactor transports to help enable graceful shutdown (#142)
- This also paves the way for better multi-session support - We should definitely rethink names for the transport API - For now, I kept the names similar as possible, so we can focus on the API shape Co-authored-by: Stephen Toub <stoub@microsoft.com>
This commit is contained in:
parent
d47c834fa9
commit
2ab9db0878
3 changed files with 2015 additions and 1847 deletions
|
|
@ -1,31 +0,0 @@
|
|||
using ModelContextProtocol.Server;
|
||||
using ModelContextProtocol.Utils;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace ModelContextProtocol.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Hosted service for the MCP server.
|
||||
/// </summary>
|
||||
public class McpServerHostedService : BackgroundService
|
||||
{
|
||||
private readonly IMcpServer _server;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the McpServerHostedService.
|
||||
/// </summary>
|
||||
/// <param name="server">The MCP server instance</param>
|
||||
/// <exception cref="ArgumentNullException"></exception>
|
||||
public McpServerHostedService(IMcpServer server)
|
||||
{
|
||||
Throw.IfNull(server);
|
||||
|
||||
_server = server;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
await _server.StartAsync(stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using ModelContextProtocol.Protocol.Transport;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
namespace ModelContextProtocol.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Hosted service for a multi-session (i.e. HTTP) MCP server.
|
||||
/// </summary>
|
||||
internal sealed class McpServerMultiSessionHostedService : BackgroundService
|
||||
{
|
||||
private readonly IServerTransport _serverTransport;
|
||||
private readonly McpServerOptions _serverOptions;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
|
||||
public McpServerMultiSessionHostedService(
|
||||
IServerTransport serverTransport,
|
||||
IOptions<McpServerOptions> serverOptions,
|
||||
ILoggerFactory loggerFactory,
|
||||
IServiceProvider serviceProvider)
|
||||
{
|
||||
_serverTransport = serverTransport;
|
||||
_serverOptions = serverOptions.Value;
|
||||
_loggerFactory = loggerFactory;
|
||||
_serviceProvider = serviceProvider;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
while (await AcceptSessionAsync(stoppingToken).ConfigureAwait(false) is { } server)
|
||||
{
|
||||
// TODO: Track all running sessions and wait for all sessions to complete for graceful shutdown.
|
||||
_ = server.RunAsync(stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
private Task<IMcpServer> AcceptSessionAsync(CancellationToken cancellationToken)
|
||||
=> McpServerFactory.AcceptAsync(_serverTransport, _serverOptions, _loggerFactory, _serviceProvider, cancellationToken);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
namespace ModelContextProtocol.Hosting;
|
||||
|
||||
/// <summary>
|
||||
/// Hosted service for a single-session (i.e stdio) MCP server.
|
||||
/// </summary>
|
||||
internal sealed class McpServerSingleSessionHostedService(IMcpServer session) : BackgroundService
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken) => session.RunAsync(stoppingToken);
|
||||
}
|
||||
Loading…
Reference in a new issue