diff --git a/src/ModelContextProtocol/Logging/Log.cs b/src/ModelContextProtocol/Logging/Log.cs
index 7a240eee9..b49b4cb59 100644
--- a/src/ModelContextProtocol/Logging/Log.cs
+++ b/src/ModelContextProtocol/Logging/Log.cs
@@ -114,7 +114,7 @@ internal static partial class Log
     internal static partial void TransportNotConnected(this ILogger logger, string endpointName);
 
     [LoggerMessage(Level = LogLevel.Information, Message = "Transport sending message for {endpointName} with ID {messageId}, JSON {json}")]
-    internal static partial void TransportSendingMessage(this ILogger logger, string endpointName, string messageId, string json);
+    internal static partial void TransportSendingMessage(this ILogger logger, string endpointName, string messageId, string? json = null);
 
     [LoggerMessage(Level = LogLevel.Information, Message = "Transport message sent for {endpointName} with ID {messageId}")]
     internal static partial void TransportSentMessage(this ILogger logger, string endpointName, string messageId);
@@ -347,4 +347,35 @@ public static partial void SSETransportPostNotAccepted(
         string endpointName,
         string messageId,
         string responseContent);
+
+    /// 
+    /// Logs the byte representation of a message in UTF-8 encoding.
+    /// 
+    /// The logger to use.
+    /// The name of the endpoint.
+    /// The byte representation as a hex string.
+    [LoggerMessage(EventId = 39000, Level = LogLevel.Trace, Message = "Transport {EndpointName}: Message bytes (UTF-8): {ByteRepresentation}")]
+    private static partial void TransportMessageBytes(this ILogger logger, string endpointName, string byteRepresentation);
+
+    /// 
+    /// Logs the byte representation of a message for diagnostic purposes.
+    /// This is useful for diagnosing encoding issues with non-ASCII characters.
+    /// 
+    /// The logger to use.
+    /// The name of the endpoint.
+    /// The message to log bytes for.
+    internal static void TransportMessageBytesUtf8(this ILogger logger, string endpointName, string message)
+    {
+        if (logger.IsEnabled(LogLevel.Trace))
+        {
+            var bytes = System.Text.Encoding.UTF8.GetBytes(message);
+            var byteRepresentation =
+#if NET
+                Convert.ToHexString(bytes);
+#else
+                BitConverter.ToString(bytes).Replace("-", " ");
+#endif
+            logger.TransportMessageBytes(endpointName, byteRepresentation);
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs
index 5479a3067..49e433017 100644
--- a/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs
+++ b/src/ModelContextProtocol/Protocol/Transport/StdioClientTransport.cs
@@ -1,12 +1,13 @@
-using System.Diagnostics;
-using System.Text.Json;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
 using ModelContextProtocol.Configuration;
 using ModelContextProtocol.Logging;
 using ModelContextProtocol.Protocol.Messages;
 using ModelContextProtocol.Utils;
 using ModelContextProtocol.Utils.Json;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
+using System.Diagnostics;
+using System.Text;
+using System.Text.Json;
 
 namespace ModelContextProtocol.Protocol.Transport;
 
@@ -59,6 +60,8 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
 
             _shutdownCts = new CancellationTokenSource();
 
+            UTF8Encoding noBomUTF8 = new(encoderShouldEmitUTF8Identifier: false);
+
             var startInfo = new ProcessStartInfo
             {
                 FileName = _options.Command,
@@ -68,6 +71,11 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
                 UseShellExecute = false,
                 CreateNoWindow = true,
                 WorkingDirectory = _options.WorkingDirectory ?? Environment.CurrentDirectory,
+                StandardOutputEncoding = noBomUTF8,
+                StandardErrorEncoding = noBomUTF8,
+#if NET
+                StandardInputEncoding = noBomUTF8,
+#endif
             };
 
             if (!string.IsNullOrWhiteSpace(_options.Arguments))
@@ -92,13 +100,35 @@ public async Task ConnectAsync(CancellationToken cancellationToken = default)
             // Set up error logging
             _process.ErrorDataReceived += (sender, args) => _logger.TransportError(EndpointName, args.Data ?? "(no data)");
 
-            if (!_process.Start())
+            // We need both stdin and stdout to use a no-BOM UTF-8 encoding. On .NET Core,
+            // we can use ProcessStartInfo.StandardOutputEncoding/StandardInputEncoding, but
+            // StandardInputEncoding doesn't exist on .NET Framework; instead, it always picks
+            // up the encoding from Console.InputEncoding. As such, when not targeting .NET Core,
+            // we temporarily change Console.InputEncoding to no-BOM UTF-8 around the Process.Start
+            // call, to ensure it picks up the correct encoding.
+#if NET
+            _processStarted = _process.Start();
+#else
+            Encoding originalInputEncoding = Console.InputEncoding;
+            try
+            {
+                Console.InputEncoding = noBomUTF8;
+                _processStarted = _process.Start();
+            }
+            finally
+            {
+                Console.InputEncoding = originalInputEncoding;
+            }
+#endif
+
+            if (!_processStarted)
             {
                 _logger.TransportProcessStartFailed(EndpointName);
                 throw new McpTransportException("Failed to start MCP server process");
             }
+
             _logger.TransportProcessStarted(EndpointName, _process.Id);
-            _processStarted = true;
+            
             _process.BeginErrorReadLine();
 
             // Start reading messages in the background
@@ -134,9 +164,10 @@ public override async Task SendMessageAsync(IJsonRpcMessage message, Cancellatio
         {
             var json = JsonSerializer.Serialize(message, _jsonOptions.GetTypeInfo());
             _logger.TransportSendingMessage(EndpointName, id, json);
+            _logger.TransportMessageBytesUtf8(EndpointName, json);
 
-            // Write the message followed by a newline
-            await _process!.StandardInput.WriteLineAsync(json.AsMemory(), cancellationToken).ConfigureAwait(false);
+            // Write the message followed by a newline using our UTF-8 writer
+            await _process!.StandardInput.WriteLineAsync(json).ConfigureAwait(false);
             await _process.StandardInput.FlushAsync(cancellationToken).ConfigureAwait(false);
 
             _logger.TransportSentMessage(EndpointName, id);
@@ -161,12 +192,10 @@ private async Task ReadMessagesAsync(CancellationToken cancellationToken)
         {
             _logger.TransportEnteringReadMessagesLoop(EndpointName);
 
-            using var reader = _process!.StandardOutput;
-
-            while (!cancellationToken.IsCancellationRequested && !_process.HasExited)
+            while (!cancellationToken.IsCancellationRequested && !_process!.HasExited)
             {
                 _logger.TransportWaitingForMessage(EndpointName);
-                var line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
+                var line = await _process.StandardOutput.ReadLineAsync(cancellationToken).ConfigureAwait(false);
                 if (line == null)
                 {
                     _logger.TransportEndOfStream(EndpointName);
@@ -179,6 +208,7 @@ private async Task ReadMessagesAsync(CancellationToken cancellationToken)
                 }
 
                 _logger.TransportReceivedMessage(EndpointName, line);
+                _logger.TransportMessageBytesUtf8(EndpointName, line);
 
                 await ProcessMessageAsync(line, cancellationToken).ConfigureAwait(false);
             }
@@ -230,28 +260,27 @@ private async Task ProcessMessageAsync(string line, CancellationToken cancellati
     private async Task CleanupAsync(CancellationToken cancellationToken)
     {
         _logger.TransportCleaningUp(EndpointName);
-        if (_process != null && _processStarted && !_process.HasExited)
+
+        if (_process is Process process && _processStarted && !process.HasExited)
         {
             try
             {
-                // Try to close stdin to signal the process to exit
-                _logger.TransportClosingStdin(EndpointName);
-                _process.StandardInput.Close();
-
                 // Wait for the process to exit
                 _logger.TransportWaitingForShutdown(EndpointName);
 
                 // Kill the while process tree because the process may spawn child processes
                 // and Node.js does not kill its children when it exits properly
-                _process.KillTree(_options.ShutdownTimeout);
+                process.KillTree(_options.ShutdownTimeout);
             }
             catch (Exception ex)
             {
                 _logger.TransportShutdownFailed(EndpointName, ex);
             }
-
-            _process.Dispose();
-            _process = null;
+            finally
+            {
+                process.Dispose();
+                _process = null;
+            }
         }
 
         if (_shutdownCts is { } shutdownCts)
@@ -261,29 +290,30 @@ private async Task CleanupAsync(CancellationToken cancellationToken)
             _shutdownCts = null;
         }
 
-        if (_readTask != null)
+        if (_readTask is Task readTask)
         {
             try
             {
                 _logger.TransportWaitingForReadTask(EndpointName);
-                await _readTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
+                await readTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
             }
             catch (TimeoutException)
             {
                 _logger.TransportCleanupReadTaskTimeout(EndpointName);
-                // Continue with cleanup
             }
             catch (OperationCanceledException)
             {
                 _logger.TransportCleanupReadTaskCancelled(EndpointName);
-                // Ignore cancellation
             }
             catch (Exception ex)
             {
                 _logger.TransportCleanupReadTaskFailed(EndpointName, ex);
             }
-            _readTask = null;
-            _logger.TransportReadTaskCleanedUp(EndpointName);
+            finally
+            {
+                _logger.TransportReadTaskCleanedUp(EndpointName);
+                _readTask = null;
+            }
         }
 
         SetConnected(false);
diff --git a/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs b/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs
index d63fe38ec..9b82d4ea0 100644
--- a/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs
+++ b/src/ModelContextProtocol/Protocol/Transport/StdioServerTransport.cs
@@ -1,12 +1,13 @@
-using System.Text.Json;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using Microsoft.Extensions.Options;
 using ModelContextProtocol.Logging;
 using ModelContextProtocol.Protocol.Messages;
 using ModelContextProtocol.Server;
 using ModelContextProtocol.Utils;
 using ModelContextProtocol.Utils.Json;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-using Microsoft.Extensions.Options;
+using System.Text;
+using System.Text.Json;
 
 namespace ModelContextProtocol.Protocol.Transport;
 
@@ -15,12 +16,14 @@ namespace ModelContextProtocol.Protocol.Transport;
 /// 
 public sealed class StdioServerTransport : TransportBase, IServerTransport
 {
+    private static readonly byte[] s_newlineBytes = "\n"u8.ToArray();
+
     private readonly string _serverName;
     private readonly ILogger _logger;
 
     private readonly JsonSerializerOptions _jsonOptions = McpJsonUtilities.DefaultOptions;
-    private readonly TextReader _stdin = Console.In;
-    private readonly TextWriter _stdout = Console.Out;
+    private readonly TextReader _stdInReader;
+    private readonly Stream _stdOutStream;
 
     private Task? _readTask;
     private CancellationTokenSource? _shutdownCts;
@@ -83,16 +86,50 @@ public StdioServerTransport(string serverName, ILoggerFactory? loggerFactory = n
         
         _serverName = serverName;
         _logger = (ILogger?)loggerFactory?.CreateLogger() ?? NullLogger.Instance;
+        
+        // Get raw console streams and wrap them with UTF-8 encoding
+        _stdInReader = new StreamReader(Console.OpenStandardInput(), Encoding.UTF8);
+        _stdOutStream = new BufferedStream(Console.OpenStandardOutput());
+    }
+
+    /// 
+    /// Initializes a new instance of the  class with explicit input/output streams.
+    /// 
+    /// The name of the server.
+    /// The input TextReader to use.
+    /// The output TextWriter to use.
+    /// Optional logger factory used for logging employed by the transport.
+    ///  is .
+    /// 
+    /// 
+    /// This constructor is useful for testing scenarios where you want to redirect input/output.
+    /// 
+    /// 
+    public StdioServerTransport(string serverName, Stream stdinStream, Stream stdoutStream, ILoggerFactory? loggerFactory = null)
+        : base(loggerFactory)
+    {
+        Throw.IfNull(serverName);
+        Throw.IfNull(stdinStream);
+        Throw.IfNull(stdoutStream);
+        
+        _serverName = serverName;
+        _logger = (ILogger?)loggerFactory?.CreateLogger() ?? NullLogger.Instance;
+        
+        _stdInReader = new StreamReader(stdinStream, Encoding.UTF8);
+        _stdOutStream = stdoutStream;
     }
 
     /// 
     public Task StartListeningAsync(CancellationToken cancellationToken = default)
     {
+        _logger.LogDebug("Starting StdioServerTransport listener for {EndpointName}", EndpointName);
+        
         _shutdownCts = new CancellationTokenSource();
 
         _readTask = Task.Run(async () => await ReadMessagesAsync(_shutdownCts.Token).ConfigureAwait(false), CancellationToken.None);
 
         SetConnected(true);
+        _logger.LogDebug("StdioServerTransport now connected for {EndpointName}", EndpointName);
 
         return Task.CompletedTask;
     }
@@ -114,11 +151,11 @@ public override async Task SendMessageAsync(IJsonRpcMessage message, Cancellatio
 
         try
         {
-            var json = JsonSerializer.Serialize(message, _jsonOptions.GetTypeInfo());
-            _logger.TransportSendingMessage(EndpointName, id, json);
+            _logger.TransportSendingMessage(EndpointName, id);
 
-            await _stdout.WriteLineAsync(json.AsMemory(), cancellationToken).ConfigureAwait(false);
-            await _stdout.FlushAsync(cancellationToken).ConfigureAwait(false);
+            await JsonSerializer.SerializeAsync(_stdOutStream, message, _jsonOptions.GetTypeInfo(), cancellationToken).ConfigureAwait(false);
+            await _stdOutStream.WriteAsync(s_newlineBytes, cancellationToken).ConfigureAwait(false);
+            await _stdOutStream.FlushAsync(cancellationToken).ConfigureAwait(false);;
 
             _logger.TransportSentMessage(EndpointName, id);
         }
@@ -146,7 +183,7 @@ private async Task ReadMessagesAsync(CancellationToken cancellationToken)
             {
                 _logger.TransportWaitingForMessage(EndpointName);
 
-                var reader = _stdin;
+                var reader = _stdInReader;
                 var line = await reader.ReadLineAsync(cancellationToken).ConfigureAwait(false);
                 if (line == null)
                 {
@@ -160,6 +197,7 @@ private async Task ReadMessagesAsync(CancellationToken cancellationToken)
                 }
 
                 _logger.TransportReceivedMessage(EndpointName, line);
+                _logger.TransportMessageBytesUtf8(EndpointName, line);
 
                 try
                 {
@@ -207,19 +245,20 @@ private async Task CleanupAsync(CancellationToken cancellationToken)
     {
         _logger.TransportCleaningUp(EndpointName);
 
-        if (_shutdownCts != null)
+        if (_shutdownCts is { } shutdownCts)
         {
-            await _shutdownCts.CancelAsync().ConfigureAwait(false);
-            _shutdownCts.Dispose();
+            await shutdownCts.CancelAsync().ConfigureAwait(false);
+            shutdownCts.Dispose();
+
             _shutdownCts = null;
         }
 
-        if (_readTask != null)
+        if (_readTask is { } readTask)
         {
             try
             {
                 _logger.TransportWaitingForReadTask(EndpointName);
-                await _readTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
+                await readTask.WaitAsync(TimeSpan.FromSeconds(5), cancellationToken).ConfigureAwait(false);
             }
             catch (TimeoutException)
             {
@@ -235,10 +274,16 @@ private async Task CleanupAsync(CancellationToken cancellationToken)
             {
                 _logger.TransportCleanupReadTaskFailed(EndpointName, ex);
             }
-            _readTask = null;
-            _logger.TransportReadTaskCleanedUp(EndpointName);
+            finally
+            {
+                _logger.TransportReadTaskCleanedUp(EndpointName);
+                _readTask = null;
+            }
         }
 
+        _stdInReader?.Dispose();
+        _stdOutStream?.Dispose();
+
         SetConnected(false);
         _logger.TransportCleanedUp(EndpointName);
     }
diff --git a/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs b/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs
index 7a868a6d7..78f98483a 100644
--- a/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs
+++ b/src/ModelContextProtocol/Utils/Json/McpJsonUtilities.cs
@@ -1,7 +1,6 @@
 using ModelContextProtocol.Protocol.Messages;
 using ModelContextProtocol.Protocol.Types;
 using System.Diagnostics.CodeAnalysis;
-using System.Text.Encodings.Web;
 using System.Text.Json;
 using System.Text.Json.Nodes;
 using System.Text.Json.Serialization;
@@ -26,11 +25,6 @@ public static partial class McpJsonUtilities
     /// - Enables string-based enum serialization as implemented by .///
- Enables  as the default ignore condition for properties.///
- Enables  as the default number handling for number types.-    ///
- 
-    /// Enables  when escaping JSON strings.
-    /// Consuming applications must ensure that JSON outputs are adequately escaped before embedding in other document formats,
-    /// such as HTML and XML.
-    /// /// 
     /// 
     /// 
@@ -58,15 +52,13 @@ private static JsonSerializerOptions CreateDefaultOptions()
                 Converters = { new JsonStringEnumConverter() },
                 DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
                 NumberHandling = JsonNumberHandling.AllowReadingFromString,
-                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
             };
         }
         else
         {
+            // Keep in sync with any additional settings above beyond what's in JsonContext below.
             options = new(JsonContext.Default.Options)
             {
-                // Compile-time encoder setting not yet available
-                Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
             };
         }
 
@@ -77,7 +69,8 @@ private static JsonSerializerOptions CreateDefaultOptions()
     internal static JsonTypeInfo GetTypeInfo(this JsonSerializerOptions options) =>
         (JsonTypeInfo)options.GetTypeInfo(typeof(T));
 
-    internal static JsonElement DefaultMcpToolSchema = ParseJsonElement("{\"type\":\"object\"}"u8);
+    internal static JsonElement DefaultMcpToolSchema { get; } = ParseJsonElement("""{"type":"object"}"""u8);
+
     internal static bool IsValidMcpToolSchema(JsonElement element)
     {
         if (element.ValueKind is not JsonValueKind.Object)
@@ -129,5 +122,4 @@ private static JsonElement ParseJsonElement(ReadOnlySpan utf8Json)
         Utf8JsonReader reader = new(utf8Json);
         return JsonElement.ParseValue(ref reader);
     }
-
 }
diff --git a/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs b/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
index 82ce82106..9a6cd64b2 100644
--- a/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
+++ b/tests/ModelContextProtocol.Tests/Transport/StdioServerTransportTests.cs
@@ -1,10 +1,12 @@
-using System.Text.Json;
+using Microsoft.Extensions.Logging.Abstractions;
 using ModelContextProtocol.Protocol.Messages;
 using ModelContextProtocol.Protocol.Transport;
 using ModelContextProtocol.Protocol.Types;
 using ModelContextProtocol.Server;
 using ModelContextProtocol.Utils.Json;
-using Microsoft.Extensions.Logging.Abstractions;
+using System.IO.Pipelines;
+using System.Text;
+using System.Text.Json;
 
 namespace ModelContextProtocol.Tests.Transport;
 
@@ -57,36 +59,33 @@ public async Task StartListeningAsync_Should_Set_Connected_State()
         Assert.True(transport.IsConnected);
     }
 
-    [Fact(Skip = "https://github.com/modelcontextprotocol/csharp-sdk/issues/1")]
+    [Fact]
     public async Task SendMessageAsync_Should_Send_Message()
     {
-        TextReader oldIn = Console.In;
-        TextWriter oldOut = Console.Out;
-        try
-        {
-            using var output = new StringWriter();
-
-            Console.SetIn(new StringReader(""));
-            Console.SetOut(output);
-
-            await using var transport = new StdioServerTransport(_serverOptions, NullLoggerFactory.Instance);
-            await transport.StartListeningAsync(TestContext.Current.CancellationToken);
-
-            var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
+        using var output = new MemoryStream();
+
+        await using var transport = new StdioServerTransport(
+            _serverOptions.ServerInfo.Name,
+            new Pipe().Reader.AsStream(),
+            output,
+            NullLoggerFactory.Instance);
+            
+        await transport.StartListeningAsync(TestContext.Current.CancellationToken);
+        
+        // Ensure transport is fully initialized
+        await Task.Delay(100, TestContext.Current.CancellationToken);
+        
+        // Verify transport is connected
+        Assert.True(transport.IsConnected, "Transport should be connected after StartListeningAsync");
 
+        var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
 
-            await transport.SendMessageAsync(message, TestContext.Current.CancellationToken);
+        await transport.SendMessageAsync(message, TestContext.Current.CancellationToken);
 
-            var result = output.ToString()?.Trim();
-            var expected = JsonSerializer.Serialize(message, McpJsonUtilities.DefaultOptions);
+        var result = Encoding.UTF8.GetString(output.ToArray()).Trim();
+        var expected = JsonSerializer.Serialize(message, McpJsonUtilities.DefaultOptions);
 
-            Assert.Equal(expected, result);
-        }
-        finally
-        {
-            Console.SetOut(oldOut);
-            Console.SetIn(oldIn);
-        }
+        Assert.Equal(expected, result);
     }
 
     [Fact]
@@ -115,29 +114,34 @@ public async Task ReadMessagesAsync_Should_Read_Messages()
         var message = new JsonRpcRequest { Method = "test", Id = RequestId.FromNumber(44) };
         var json = JsonSerializer.Serialize(message, McpJsonUtilities.DefaultOptions);
 
-        TextReader oldIn = Console.In;
-        TextWriter oldOut = Console.Out;
-        try
-        {
-            Console.SetIn(new StringReader(json));
-            Console.SetOut(new StringWriter());
-
-            await using var transport = new StdioServerTransport(_serverOptions);
-            await transport.StartListeningAsync(TestContext.Current.CancellationToken);
-
-            var canRead = await transport.MessageReader.WaitToReadAsync(TestContext.Current.CancellationToken);
+        // Use a reader that won't terminate
+        Pipe pipe = new();
+        using var input = pipe.Reader.AsStream();
 
-            Assert.True(canRead, "Nothing to read here from transport message reader");
-            Assert.True(transport.MessageReader.TryPeek(out var readMessage));
-            Assert.NotNull(readMessage);
-            Assert.IsType(readMessage);
-            Assert.Equal(44, ((JsonRpcRequest)readMessage).Id.AsNumber);
-        }
-        finally
-        {
-            Console.SetOut(oldOut);
-            Console.SetIn(oldIn);
-        }
+        await using var transport = new StdioServerTransport(
+            _serverOptions.ServerInfo.Name,
+            input,
+            Stream.Null,
+            NullLoggerFactory.Instance);
+            
+        await transport.StartListeningAsync(TestContext.Current.CancellationToken);
+        
+        // Ensure transport is fully initialized
+        await Task.Delay(100, TestContext.Current.CancellationToken);
+        
+        // Verify transport is connected
+        Assert.True(transport.IsConnected, "Transport should be connected after StartListeningAsync");
+
+        // Write the message to the reader
+        await pipe.Writer.WriteAsync(Encoding.UTF8.GetBytes($"{json}\n"), TestContext.Current.CancellationToken);
+
+        var canRead = await transport.MessageReader.WaitToReadAsync(TestContext.Current.CancellationToken);
+
+        Assert.True(canRead, "Nothing to read here from transport message reader");
+        Assert.True(transport.MessageReader.TryPeek(out var readMessage));
+        Assert.NotNull(readMessage);
+        Assert.IsType(readMessage);
+        Assert.Equal(44, ((JsonRpcRequest)readMessage).Id.AsNumber);
     }
 
     [Fact]
@@ -150,4 +154,82 @@ public async Task CleanupAsync_Should_Cleanup_Resources()
 
         Assert.False(transport.IsConnected);
     }
+
+    [Fact]
+    public async Task SendMessageAsync_Should_Preserve_Unicode_Characters()
+    {
+        // Use a reader that won't terminate
+        using var output = new MemoryStream();
+
+        await using var transport = new StdioServerTransport(
+            _serverOptions.ServerInfo.Name, 
+            new Pipe().Reader.AsStream(),
+            output, 
+            NullLoggerFactory.Instance);
+            
+        await transport.StartListeningAsync(TestContext.Current.CancellationToken);
+        
+        // Ensure transport is fully initialized
+        await Task.Delay(100, TestContext.Current.CancellationToken);
+        
+        // Verify transport is connected
+        Assert.True(transport.IsConnected, "Transport should be connected after StartListeningAsync");
+
+        // Test 1: Chinese characters (BMP Unicode)
+        var chineseText = "上下文伺服器"; // "Context Server" in Chinese
+        var chineseMessage = new JsonRpcRequest 
+        { 
+            Method = "test", 
+            Id = RequestId.FromNumber(44),
+            Params = new Dictionary
+            {
+                ["text"] = JsonSerializer.SerializeToElement(chineseText)
+            }
+        };
+
+        // Clear output and send message
+        output.SetLength(0);
+        await transport.SendMessageAsync(chineseMessage, TestContext.Current.CancellationToken);
+        
+        // Verify Chinese characters preserved but encoded
+        var chineseResult = Encoding.UTF8.GetString(output.ToArray()).Trim();
+        var expectedChinese = JsonSerializer.Serialize(chineseMessage, McpJsonUtilities.DefaultOptions);
+        Assert.Equal(expectedChinese, chineseResult);
+        Assert.Contains(JsonSerializer.Serialize(chineseText), chineseResult);
+        
+        // Test 2: Emoji (non-BMP Unicode using surrogate pairs)
+        var emojiText = "🔍 🚀 👍"; // Magnifying glass, rocket, thumbs up
+        var emojiMessage = new JsonRpcRequest 
+        { 
+            Method = "test", 
+            Id = RequestId.FromNumber(45),
+            Params = new Dictionary
+            {
+                ["text"] = JsonSerializer.SerializeToElement(emojiText)
+            }
+        };
+
+        // Clear output and send message
+        output.SetLength(0);
+        await transport.SendMessageAsync(emojiMessage, TestContext.Current.CancellationToken);
+        
+        // Verify emoji preserved - might be as either direct characters or escape sequences
+        var emojiResult = Encoding.UTF8.GetString(output.ToArray()).Trim();
+        var expectedEmoji = JsonSerializer.Serialize(emojiMessage, McpJsonUtilities.DefaultOptions);
+        Assert.Equal(expectedEmoji, emojiResult);
+        
+        // Verify surrogate pairs in different possible formats
+        // Magnifying glass emoji: 🔍 (U+1F50D)
+        bool magnifyingGlassFound = 
+            emojiResult.Contains("🔍") || 
+            emojiResult.Contains("\\ud83d\\udd0d", StringComparison.OrdinalIgnoreCase);
+            
+        // Rocket emoji: 🚀 (U+1F680)
+        bool rocketFound = 
+            emojiResult.Contains("🚀") || 
+            emojiResult.Contains("\\ud83d\\ude80", StringComparison.OrdinalIgnoreCase);
+        
+        Assert.True(magnifyingGlassFound, "Magnifying glass emoji not found in result");
+        Assert.True(rocketFound, "Rocket emoji not found in result");
+    }
 }