Files
mcp-ssh/src/McpSsh.Server/Ssh/SshClientFactory.cs
2026-05-24 21:18:09 +00:00

71 lines
2.0 KiB
C#

using Renci.SshNet;
namespace McpSsh.Server.Ssh;
public interface ISshClientFactory
{
SshClient CreateSshClient(SshConnectionRequest request);
SftpClient CreateSftpClient(SshConnectionRequest request);
ScpClient CreateScpClient(SshConnectionRequest request);
}
public sealed record SshConnectionRequest(
string Host,
string Username,
int Port,
string? KeyPath,
string? KeyPassphrase,
TimeSpan? Timeout = null);
public sealed class SshNetClientFactory : ISshClientFactory
{
private readonly ISshKeyResolver _keyResolver;
public SshNetClientFactory(ISshKeyResolver keyResolver)
{
_keyResolver = keyResolver;
}
public SshClient CreateSshClient(SshConnectionRequest request)
{
var client = new SshClient(CreateConnectionInfo(request));
ApplyTimeout(client, request.Timeout);
return client;
}
public SftpClient CreateSftpClient(SshConnectionRequest request)
{
var client = new SftpClient(CreateConnectionInfo(request));
ApplyTimeout(client, request.Timeout);
return client;
}
public ScpClient CreateScpClient(SshConnectionRequest request)
{
var client = new ScpClient(CreateConnectionInfo(request));
ApplyTimeout(client, request.Timeout);
return client;
}
private ConnectionInfo CreateConnectionInfo(SshConnectionRequest request)
{
var keyPath = _keyResolver.ResolveKeyPath(request.KeyPath);
var keyFile = string.IsNullOrEmpty(request.KeyPassphrase)
? new PrivateKeyFile(keyPath)
: new PrivateKeyFile(keyPath, request.KeyPassphrase);
var auth = new PrivateKeyAuthenticationMethod(request.Username, keyFile);
return new ConnectionInfo(request.Host, request.Port, request.Username, auth);
}
private static void ApplyTimeout(BaseClient client, TimeSpan? timeout)
{
if (timeout is { } value)
{
client.ConnectionInfo.Timeout = value;
}
}
}