Update Client.connect(transport:) to automatically send initialize request (#100)

* Update Client to automatically call initialize in connect

* Make Client.connect(transport:) return value discardable

* Fix example usage in README

* Update example code in transports to remove initialize call

* Deprecate initialize method

* Update tests

* Update README

* Fix sampling tests

* Fix race condition tests
This commit is contained in:
Mattt 2025-05-26 06:04:38 -07:00 • committed by GitHub
commit a59b50bf5a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 302 additions and 106 deletions

View file

@ -41,9 +41,6 @@ import Logging
/// let client = Client(name: "MyApp", version: "1.0.0")
/// try await client.connect(transport: transport)
///
/// // Initialize the connection
/// let result = try await client.initialize()
///
/// // The transport will automatically handle SSE events
/// // and deliver them through the client's notification handlers
/// ```

View file

@ -51,9 +51,6 @@ import Logging
/// // Use the transport with an MCP client
/// let client = Client(name: "MyApp", version: "1.0.0")
/// try await client.connect(transport: transport)
///
/// // Initialize the connection
/// let result = try await client.initialize()
/// ```
public actor NetworkTransport: Transport {
/// Represents a heartbeat message for connection health monitoring.

View file

@ -44,9 +44,6 @@ import struct Foundation.Data
/// // Create a transport and connect
/// let transport = StdioTransport()
/// try await client.connect(transport: transport)
///
/// // Initialize the connection
/// let result = try await client.initialize()
/// ```
public actor StdioTransport: Transport {
private let input: FileDescriptor

View file

@ -168,7 +168,8 @@ public actor Client {
}
/// Connect to the server using the given transport
public func connect(transport: any Transport) async throws {
@discardableResult
public func connect(transport: any Transport) async throws -> Initialize.Result {
self.connection = transport
try await self.connection?.connect()
@ -217,6 +218,9 @@ public actor Client {
} while true
await self.logger?.info("Client message handling loop task is terminating.")
}
// Automatically initialize after connecting
return try await _initialize()
}
/// Disconnect the client and cancel all pending requests
@ -480,7 +484,23 @@ public actor Client {
// MARK: - Lifecycle
/// Initialize the connection with the server.
///
/// - Important: This method is deprecated. Initialization now happens automatically
/// when calling `connect(transport:)`. You should use that method instead.
///
/// - Returns: The server's initialization response containing capabilities and server info
@available(
*, deprecated,
message:
"Initialization now happens automatically during connect. Use connect(transport:) instead."
)
public func initialize() async throws -> Initialize.Result {
return try await _initialize()
}
/// Internal initialization implementation
private func _initialize() async throws -> Initialize.Result {
let request = Initialize.request(
.init(
protocolVersion: Version.latest,