diff --git a/README.MD b/README.MD index 3038774..96dc9ce 100644 --- a/README.MD +++ b/README.MD @@ -166,7 +166,6 @@ while (true) - Performance optimization - SSE server support - Authentication -- Linux/Mac support for stdio transport ## License diff --git a/src/mcpdotnet/Client/McpClientFactory.cs b/src/mcpdotnet/Client/McpClientFactory.cs index 20a80ad..5aedc11 100644 --- a/src/mcpdotnet/Client/McpClientFactory.cs +++ b/src/mcpdotnet/Client/McpClientFactory.cs @@ -135,7 +135,7 @@ public class McpClientFactory return defaultValue; } - private string GetCommand(McpServerConfig config) + private string? GetCommand(McpServerConfig config) { if (config.TransportOptions == null || string.IsNullOrEmpty(config.TransportOptions.GetValueOrDefault("command"))) @@ -143,7 +143,7 @@ public class McpClientFactory return config.Location!; } - return $"cmd.exe"; + return OperatingSystem.IsWindows() ? "cmd.exe" : config.TransportOptions?.GetValueOrDefault("command"); } /// @@ -151,29 +151,28 @@ public class McpClientFactory /// private void InitializeCommand(McpServerConfig config) { - string endpointName = $"Client ({config.Id}: {config.Name})"; // If the command is empty or already contains cmd.exe, we don't need to do anything var command = config.TransportOptions?.GetValueOrDefault("command"); - if (string.IsNullOrEmpty(command)) + + if (string.IsNullOrEmpty(command) || !OperatingSystem.IsWindows()) { return; } - if (command.Contains("cmd.exe")) + // On Windows, we need to wrap non-shell commands with cmd.exe /c + if (command.ToLowerInvariant().Contains("cmd.exe")) { _logger.SkippingShellWrapper(endpointName); return; } - // If the command is not empty and does not contain cmd.exe, we need to inject /c {command} - if (config.TransportOptions != null && !string.IsNullOrEmpty(command)) - { - _logger.PromotingCommandToShellArgumentForStdio(endpointName, command, config.TransportOptions.GetValueOrDefault("arguments") ?? ""); - config.TransportOptions["arguments"] = config.TransportOptions.ContainsKey("arguments") - ? $"/c {command} {config.TransportOptions["arguments"]}" - : $"/c {command}"; - } + // 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"]}" + : $"/c {command}"; } } \ No newline at end of file diff --git a/src/mcpdotnet/Logging/Log.cs b/src/mcpdotnet/Logging/Log.cs index 1038cab..c0cf0c2 100644 --- a/src/mcpdotnet/Logging/Log.cs +++ b/src/mcpdotnet/Logging/Log.cs @@ -1,5 +1,4 @@ -using McpDotNet.Configuration; -using McpDotNet.Protocol.Messages; +using McpDotNet.Protocol.Messages; using Microsoft.Extensions.Logging; namespace McpDotNet.Logging; diff --git a/src/mcpdotnet/Protocol/Transport/SseClientTransport.cs b/src/mcpdotnet/Protocol/Transport/SseClientTransport.cs index 8118bc7..f50ca83 100644 --- a/src/mcpdotnet/Protocol/Transport/SseClientTransport.cs +++ b/src/mcpdotnet/Protocol/Transport/SseClientTransport.cs @@ -1,6 +1,4 @@ - -using System.Diagnostics.Tracing; -using System.Text.Json; +using System.Text.Json; using System.Text; using McpDotNet.Protocol.Messages; using McpDotNet.Configuration; @@ -9,7 +7,6 @@ using McpDotNet.Logging; using System.Net.Http.Headers; using System.Text.Json.Serialization; using McpDotNet.Utils.Json; -using System.Threading; namespace McpDotNet.Protocol.Transport; diff --git a/src/mcpdotnet/Protocol/Transport/StdioClientTransport.cs b/src/mcpdotnet/Protocol/Transport/StdioClientTransport.cs index a576f1a..d88b197 100644 --- a/src/mcpdotnet/Protocol/Transport/StdioClientTransport.cs +++ b/src/mcpdotnet/Protocol/Transport/StdioClientTransport.cs @@ -61,7 +61,7 @@ public sealed class StdioClientTransport : TransportBase, IClientTransport RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true, - CreateNoWindow = true, + CreateNoWindow = OperatingSystem.IsWindows(), WorkingDirectory = _options.WorkingDirectory ?? Environment.CurrentDirectory, }; diff --git a/src/mcpdotnet/mcpdotnet.csproj b/src/mcpdotnet/mcpdotnet.csproj index bdad25a..bd46eb5 100644 --- a/src/mcpdotnet/mcpdotnet.csproj +++ b/src/mcpdotnet/mcpdotnet.csproj @@ -9,7 +9,7 @@ mcpdotnet - 1.0.0.1 + 1.0.1.1 PederHP .NET client library for the Model Context Protocol (MCP) https://github.com/PederHP/mcpdotnet