@@ -19,11 +19,11 @@ public protocol Transport: Actor {
1919 /// Disconnects from the transport
2020 func disconnect( ) async
2121
22- /// Sends a message string
23- func send( _ message : String ) async throws
22+ /// Sends data
23+ func send( _ data : Data ) async throws
2424
25- /// Receives message strings as an async sequence
26- func receive( ) -> AsyncThrowingStream < String , Swift . Error >
25+ /// Receives data in an async sequence
26+ func receive( ) -> AsyncThrowingStream < Data , Swift . Error >
2727}
2828
2929/// Standard input/output transport implementation
@@ -33,8 +33,8 @@ public actor StdioTransport: Transport {
3333 public nonisolated let logger : Logger
3434
3535 private var isConnected = false
36- private let messageStream : AsyncStream < String >
37- private let messageContinuation : AsyncStream < String > . Continuation
36+ private let messageStream : AsyncStream < Data >
37+ private let messageContinuation : AsyncStream < Data > . Continuation
3838
3939 public init (
4040 input: FileDescriptor = FileDescriptor . standardInput,
@@ -50,7 +50,7 @@ public actor StdioTransport: Transport {
5050 factory: { _ in SwiftLogNoOpLogHandler ( ) } )
5151
5252 // Create message stream
53- var continuation : AsyncStream < String > . Continuation !
53+ var continuation : AsyncStream < Data > . Continuation !
5454 self . messageStream = AsyncStream { continuation = $0 }
5555 self . messageContinuation = continuation
5656 }
@@ -105,15 +105,13 @@ public actor StdioTransport: Transport {
105105 let messageData = pendingData [ ..< newlineIndex]
106106 pendingData = pendingData [ ( newlineIndex + 1 ) ... ]
107107
108- if let message = String ( data: messageData, encoding: . utf8) ,
109- !message. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty
110- {
111- logger. debug ( " Message received " , metadata: [ " message " : " \( message) " ] )
112- messageContinuation. yield ( message)
108+ if !messageData. isEmpty {
109+ logger. debug ( " Message received " , metadata: [ " size " : " \( messageData. count) " ] )
110+ messageContinuation. yield ( Data ( messageData) )
113111 }
114112 }
115113 } catch let error where Error . isResourceTemporarilyUnavailable ( error) {
116- try ? await Task . sleep ( nanoseconds : 10_000_000 ) // 10ms backoff
114+ try ? await Task . sleep ( for : . milliseconds ( 10 ) )
117115 continue
118116 } catch {
119117 if !Task. isCancelled {
@@ -133,17 +131,16 @@ public actor StdioTransport: Transport {
133131 logger. info ( " Transport disconnected " )
134132 }
135133
136- public func send( _ message: String ) async throws {
134+ public func send( _ message: Data ) async throws {
137135 guard isConnected else {
138136 throw Error . transportError ( Errno . socketNotConnected)
139137 }
140138
141- let message = message + " \n "
142- guard let data = message. data ( using: . utf8) else {
143- throw Error . transportError ( Errno . invalidArgument)
144- }
139+ // Add newline as delimiter
140+ var messageWithNewline = message
141+ messageWithNewline. append ( UInt8 ( ascii: " \n " ) )
145142
146- var remaining = data
143+ var remaining = messageWithNewline
147144 while !remaining. isEmpty {
148145 do {
149146 let written = try remaining. withUnsafeBytes { buffer in
@@ -153,15 +150,15 @@ public actor StdioTransport: Transport {
153150 remaining = remaining. dropFirst ( written)
154151 }
155152 } catch let error where Error . isResourceTemporarilyUnavailable ( error) {
156- try await Task . sleep ( nanoseconds : 10_000_000 ) // 10ms backoff
153+ try await Task . sleep ( for : . milliseconds ( 10 ) )
157154 continue
158155 } catch {
159156 throw Error . transportError ( error)
160157 }
161158 }
162159 }
163160
164- public func receive( ) -> AsyncThrowingStream < String , Swift . Error > {
161+ public func receive( ) -> AsyncThrowingStream < Data , Swift . Error > {
165162 return AsyncThrowingStream { continuation in
166163 Task {
167164 for await message in messageStream {
@@ -182,8 +179,8 @@ public actor StdioTransport: Transport {
182179 public nonisolated let logger : Logger
183180
184181 private var isConnected = false
185- private let messageStream : AsyncThrowingStream < String , Swift . Error >
186- private let messageContinuation : AsyncThrowingStream < String , Swift . Error > . Continuation
182+ private let messageStream : AsyncThrowingStream < Data , Swift . Error >
183+ private let messageContinuation : AsyncThrowingStream < Data , Swift . Error > . Continuation
187184
188185 // Track connection state for continuations
189186 private var connectionContinuationResumed = false
@@ -198,7 +195,7 @@ public actor StdioTransport: Transport {
198195 )
199196
200197 // Create message stream
201- var continuation : AsyncThrowingStream < String , Swift . Error > . Continuation !
198+ var continuation : AsyncThrowingStream < Data , Swift . Error > . Continuation !
202199 self . messageStream = AsyncThrowingStream { continuation = $0 }
203200 self . messageContinuation = continuation
204201 }
@@ -289,14 +286,14 @@ public actor StdioTransport: Transport {
289286 logger. info ( " Network transport disconnected " )
290287 }
291288
292- public func send( _ message: String ) async throws {
289+ public func send( _ message: Data ) async throws {
293290 guard isConnected else {
294291 throw MCP . Error. internalError ( " Transport not connected " )
295292 }
296293
297- guard let data = ( message + " \n " ) . data ( using : . utf8 ) else {
298- throw MCP . Error . internalError ( " Failed to encode message" )
299- }
294+ // Add newline as delimiter
295+ var messageWithNewline = message
296+ messageWithNewline . append ( UInt8 ( ascii : " \n " ) )
300297
301298 // Use a local actor-isolated variable to track continuation state
302299 var sendContinuationResumed = false
@@ -309,7 +306,7 @@ public actor StdioTransport: Transport {
309306 }
310307
311308 connection. send (
312- content: data ,
309+ content: messageWithNewline ,
313310 completion: . contentProcessed { [ weak self] error in
314311 guard let self = self else { return }
315312
@@ -329,7 +326,7 @@ public actor StdioTransport: Transport {
329326 }
330327 }
331328
332- public func receive( ) -> AsyncThrowingStream < String , Swift . Error > {
329+ public func receive( ) -> AsyncThrowingStream < Data , Swift . Error > {
333330 return AsyncThrowingStream { continuation in
334331 Task {
335332 do {
@@ -357,11 +354,10 @@ public actor StdioTransport: Transport {
357354 let messageData = buffer [ ..< newlineIndex]
358355 buffer = buffer [ ( newlineIndex + 1 ) ... ]
359356
360- if let message = String ( data: messageData, encoding: . utf8) ,
361- !message. trimmingCharacters ( in: . whitespacesAndNewlines) . isEmpty
362- {
363- logger. debug ( " Message received " , metadata: [ " message " : " \( message) " ] )
364- messageContinuation. yield ( message)
357+ if !messageData. isEmpty {
358+ logger. debug (
359+ " Message received " , metadata: [ " size " : " \( messageData. count) " ] )
360+ messageContinuation. yield ( Data ( messageData) )
365361 }
366362 }
367363 } catch let error as NWError {
0 commit comments