Remove warnings from build (#29)
* Remove warnings from build * More fixes. * Using const for transport types
This commit is contained in:
parent
80daa5b73d
commit
7d69499ad5
3 changed files with 277 additions and 263 deletions
|
|
@ -1,7 +1,7 @@
|
|||
namespace McpDotNet.Client;
|
||||
|
||||
using McpDotNet.Protocol.Types;
|
||||
using McpDotNet.Protocol.Messages;
|
||||
using McpDotNet.Protocol.Types;
|
||||
|
||||
/// <summary>
|
||||
/// Represents an instance of the MCP client connecting to a specific server.
|
||||
|
|
@ -35,12 +35,12 @@ public interface IMcpClient : IAsyncDisposable
|
|||
/// <summary>
|
||||
/// Gets or sets the handler for server sampling requests.
|
||||
/// </summary>
|
||||
Func<CreateMessageRequestParams, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
|
||||
Func<CreateMessageRequestParams?, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the handler for providing root URIs to servers.
|
||||
/// </summary>
|
||||
Func<ListRootsRequestParams, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
|
||||
Func<ListRootsRequestParams?, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Establishes a connection to the server.
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
|
||||
using McpDotNet.Protocol.Types;
|
||||
using McpDotNet.Protocol.Transport;
|
||||
using McpDotNet.Protocol.Messages;
|
||||
using System.Text.Json;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using McpDotNet.Logging;
|
||||
using McpDotNet.Configuration;
|
||||
using McpDotNet.Logging;
|
||||
using McpDotNet.Protocol.Messages;
|
||||
using McpDotNet.Protocol.Transport;
|
||||
using McpDotNet.Protocol.Types;
|
||||
using McpDotNet.Shared;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace McpDotNet.Client;
|
||||
|
||||
|
|
@ -46,7 +46,8 @@ internal class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
if (options.Capabilities?.Sampling != null)
|
||||
{
|
||||
SetRequestHandler<CreateMessageRequestParams, CreateMessageResult>("sampling/createMessage",
|
||||
async (request) => {
|
||||
async (request) =>
|
||||
{
|
||||
if (SamplingHandler == null)
|
||||
{
|
||||
// Setting the capability, but not a handler means we have nothing to return to the server
|
||||
|
|
@ -168,7 +169,7 @@ internal class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public async Task PingAsync(CancellationToken cancellationToken)
|
||||
public async Task PingAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
_logger.PingingServer(EndpointName);
|
||||
await SendRequestAsync<dynamic>(
|
||||
|
|
@ -268,7 +269,7 @@ internal class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
}
|
||||
if (argumentValue is null)
|
||||
{
|
||||
_logger.InvalidCompletionArgumentValue(EndpointName, argumentValue);
|
||||
_logger.InvalidCompletionArgumentValue(EndpointName, "null", argumentName);
|
||||
throw new McpClientException("Argument value cannot be null");
|
||||
}
|
||||
|
||||
|
|
@ -330,13 +331,13 @@ internal class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
new JsonRpcRequest
|
||||
{
|
||||
Method = "tools/call",
|
||||
Params = CreateParametersDictionary(toolName, arguments ?? new())
|
||||
Params = CreateParametersDictionary(toolName, arguments ?? [])
|
||||
},
|
||||
cancellationToken
|
||||
).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static Dictionary<string, object?> CreateParametersDictionary(string nameParameter, Dictionary<string, object> arguments)
|
||||
private static Dictionary<string, object?> CreateParametersDictionary(string nameParameter, Dictionary<string, object>? arguments)
|
||||
{
|
||||
var parameters = new Dictionary<string, object?>
|
||||
{
|
||||
|
|
@ -352,10 +353,10 @@ internal class McpClient : McpJsonRpcEndpoint, IMcpClient
|
|||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Func<CreateMessageRequestParams, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
|
||||
public Func<CreateMessageRequestParams?, CancellationToken, Task<CreateMessageResult>>? SamplingHandler { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Func<ListRootsRequestParams, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
|
||||
public Func<ListRootsRequestParams?, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string EndpointName
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ public class McpClientFactory
|
|||
{
|
||||
private readonly Dictionary<string, McpServerConfig> _serverConfigs;
|
||||
private readonly McpClientOptions _clientOptions;
|
||||
private readonly Dictionary<string, IMcpClient> _clients = new();
|
||||
private readonly Dictionary<string, IMcpClient> _clients = [];
|
||||
private readonly Func<McpServerConfig, IClientTransport> _transportFactoryMethod;
|
||||
private readonly Func<IClientTransport, McpServerConfig, McpClientOptions, IMcpClient> _clientFactoryMethod;
|
||||
private readonly ILoggerFactory _loggerFactory;
|
||||
|
|
@ -47,12 +47,9 @@ public class McpClientFactory
|
|||
// Initialize commands for stdio transport, this is to run commands in a shell even if specified directly, as otherwise
|
||||
// the stdio protocol will not work correctly.
|
||||
_logger.InitializingStdioCommands();
|
||||
foreach (var config in _serverConfigs.Values)
|
||||
foreach (var config in _serverConfigs.Values.Where(c => c.TransportType.Equals(TransportTypes.StdIo, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
if (config.TransportType.ToLowerInvariant() == "stdio")
|
||||
{
|
||||
InitializeCommand(config);
|
||||
}
|
||||
InitializeCommand(config);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -97,11 +94,11 @@ public class McpClientFactory
|
|||
{
|
||||
string endpointName = $"Client ({config.Id}: {config.Name})";
|
||||
|
||||
var options = string.Join(", ", config.TransportOptions?.Select(kv => $"{kv.Key}={kv.Value}") ?? Enumerable.Empty<string>());
|
||||
var options = string.Join(", ", config.TransportOptions?.Select(kv => $"{kv.Key}={kv.Value}") ?? []);
|
||||
_logger.CreatingTransport(endpointName, config.TransportType, options);
|
||||
return config.TransportType.ToLowerInvariant() switch
|
||||
{
|
||||
"stdio" => new StdioClientTransport(new StdioClientTransportOptions
|
||||
TransportTypes.StdIo => new StdioClientTransport(new StdioClientTransportOptions
|
||||
{
|
||||
Command = GetCommand(config),
|
||||
Arguments = config.TransportOptions?.GetValueOrDefault("arguments")?.Split(' '),
|
||||
|
|
@ -110,7 +107,7 @@ public class McpClientFactory
|
|||
.Where(kv => kv.Key.StartsWith("env:"))
|
||||
.ToDictionary(kv => kv.Key.Substring(4), kv => kv.Value)
|
||||
}, config, _loggerFactory),
|
||||
"sse" or "http" => new SseClientTransport(
|
||||
TransportTypes.Sse or "http" => new SseClientTransport(
|
||||
new SseClientTransportOptions
|
||||
{
|
||||
ConnectionTimeout = TimeSpan.FromSeconds(ParseOrDefault(config.TransportOptions, "connectionTimeout", 30)),
|
||||
|
|
@ -124,7 +121,7 @@ public class McpClientFactory
|
|||
};
|
||||
}
|
||||
|
||||
private static int ParseOrDefault(IDictionary<string, string>? options, string key, int defaultValue)
|
||||
private static int ParseOrDefault(Dictionary<string, string>? options, string key, int defaultValue)
|
||||
{
|
||||
if (options?.TryGetValue(key, out var value) ?? false)
|
||||
{
|
||||
|
|
@ -135,15 +132,14 @@ public class McpClientFactory
|
|||
return defaultValue;
|
||||
}
|
||||
|
||||
private string? GetCommand(McpServerConfig config)
|
||||
private static string GetCommand(McpServerConfig config)
|
||||
{
|
||||
if (config.TransportOptions == null ||
|
||||
string.IsNullOrEmpty(config.TransportOptions.GetValueOrDefault("command")))
|
||||
{
|
||||
return config.Location!;
|
||||
}
|
||||
var command = config.TransportOptions?.GetValueOrDefault("command");
|
||||
|
||||
return OperatingSystem.IsWindows() ? "cmd.exe" : config.TransportOptions?.GetValueOrDefault("command");
|
||||
if (string.IsNullOrEmpty(command))
|
||||
return config.Location!;
|
||||
|
||||
return OperatingSystem.IsWindows() ? "cmd.exe" : command;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -162,7 +158,7 @@ public class McpClientFactory
|
|||
}
|
||||
|
||||
// On Windows, we need to wrap non-shell commands with cmd.exe /c
|
||||
if (command.ToLowerInvariant().Contains("cmd.exe"))
|
||||
if (command.Contains("cmd.exe", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger.SkippingShellWrapper(endpointName);
|
||||
return;
|
||||
|
|
@ -171,8 +167,8 @@ public class McpClientFactory
|
|||
// If the command is not empty and does not contain cmd.exe, we need to inject /c {command} (usually npx or uvicorn)
|
||||
// This is because the stdio transport will not work correctly if the command is not run in a shell
|
||||
_logger.PromotingCommandToShellArgumentForStdio(endpointName, command, config.TransportOptions!.GetValueOrDefault("arguments") ?? "");
|
||||
config.TransportOptions!["arguments"] = config.TransportOptions.ContainsKey("arguments")
|
||||
? $"/c {command} {config.TransportOptions["arguments"]}"
|
||||
config.TransportOptions!["arguments"] = config.TransportOptions.TryGetValue("arguments", out var args)
|
||||
? $"/c {command} {args}"
|
||||
: $"/c {command}";
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue