Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a59b50b

Browse files
authoredMay 26, 2025··
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
1 parent 3b505ee commit a59b50b

File tree

9 files changed

+302
-106
lines changed

9 files changed

+302
-106
lines changed
 

‎README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,19 @@ let client = Client(name: "MyApp", version: "1.0.0")
5454

5555
// Create a transport and connect
5656
let transport = StdioTransport()
57-
try await client.connect(transport: transport)
58-
59-
// Initialize the connection
60-
let result = try await client.initialize()
57+
let result = try await client.connect(transport: transport)
6158

6259
// Check server capabilities
6360
if result.capabilities.tools != nil {
6461
// Server supports tools (implicitly including tool calling if the 'tools' capability object is present)
6562
}
6663
```
6764

65+
> [!NOTE]
66+
> The `Client.connect(transport:)` method returns the initialization result.
67+
> This return value is discardable,
68+
> so you can ignore it if you don't need to check server capabilities.
69+
6870
### Transport Options for Clients
6971

7072
#### Stdio Transport
@@ -278,7 +280,7 @@ Handle common client errors:
278280

279281
```swift
280282
do {
281-
let result = try await client.initialize()
283+
try await client.connect(transport: transport)
282284
// Success
283285
} catch let error as MCPError {
284286
print("MCP Error: \(error.localizedDescription)")
@@ -402,7 +404,7 @@ The server component allows your application to host model capabilities and resp
402404
```swift
403405
import MCP
404406

405-
// Initialize the server with capabilities
407+
// Create a server with given capabilities
406408
let server = Server(
407409
name: "MyModelServer",
408410
version: "1.0.0",

‎Sources/MCP/Base/Transports/HTTPClientTransport.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ import Logging
4141
/// let client = Client(name: "MyApp", version: "1.0.0")
4242
/// try await client.connect(transport: transport)
4343
///
44-
/// // Initialize the connection
45-
/// let result = try await client.initialize()
46-
///
4744
/// // The transport will automatically handle SSE events
4845
/// // and deliver them through the client's notification handlers
4946
/// ```

‎Sources/MCP/Base/Transports/NetworkTransport.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@ import Logging
5151
/// // Use the transport with an MCP client
5252
/// let client = Client(name: "MyApp", version: "1.0.0")
5353
/// try await client.connect(transport: transport)
54-
///
55-
/// // Initialize the connection
56-
/// let result = try await client.initialize()
5754
/// ```
5855
public actor NetworkTransport: Transport {
5956
/// Represents a heartbeat message for connection health monitoring.

‎Sources/MCP/Base/Transports/StdioTransport.swift

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,6 @@ import struct Foundation.Data
4444
/// // Create a transport and connect
4545
/// let transport = StdioTransport()
4646
/// try await client.connect(transport: transport)
47-
///
48-
/// // Initialize the connection
49-
/// let result = try await client.initialize()
5047
/// ```
5148
public actor StdioTransport: Transport {
5249
private let input: FileDescriptor

‎Sources/MCP/Client/Client.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ public actor Client {
168168
}
169169

170170
/// Connect to the server using the given transport
171-
public func connect(transport: any Transport) async throws {
171+
@discardableResult
172+
public func connect(transport: any Transport) async throws -> Initialize.Result {
172173
self.connection = transport
173174
try await self.connection?.connect()
174175

@@ -217,6 +218,9 @@ public actor Client {
217218
} while true
218219
await self.logger?.info("Client message handling loop task is terminating.")
219220
}
221+
222+
// Automatically initialize after connecting
223+
return try await _initialize()
220224
}
221225

222226
/// Disconnect the client and cancel all pending requests
@@ -480,7 +484,23 @@ public actor Client {
480484

481485
// MARK: - Lifecycle
482486

487+
/// Initialize the connection with the server.
488+
///
489+
/// - Important: This method is deprecated. Initialization now happens automatically
490+
/// when calling `connect(transport:)`. You should use that method instead.
491+
///
492+
/// - Returns: The server's initialization response containing capabilities and server info
493+
@available(
494+
*, deprecated,
495+
message:
496+
"Initialization now happens automatically during connect. Use connect(transport:) instead."
497+
)
483498
public func initialize() async throws -> Initialize.Result {
499+
return try await _initialize()
500+
}
501+
502+
/// Internal initialization implementation
503+
private func _initialize() async throws -> Initialize.Result {
484504
let request = Initialize.request(
485505
.init(
486506
protocolVersion: Version.latest,

‎Tests/MCPTests/ClientTests.swift

Lines changed: 271 additions & 60 deletions
Large diffs are not rendered by default.

‎Tests/MCPTests/HTTPClientTransportTests.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -653,11 +653,8 @@ import Testing
653653
}
654654
}
655655

656-
// Execute the complete flow
657-
try await client.connect(transport: transport)
658-
659656
// Step 1: Initialize client
660-
let initResult = try await client.initialize()
657+
let initResult = try await client.connect(transport: transport)
661658
#expect(initResult.protocolVersion == Version.latest)
662659
#expect(initResult.capabilities.tools != nil)
663660

‎Tests/MCPTests/RoundtripTests.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,9 @@ struct RoundtripTests {
9999
let client = Client(name: "TestClient", version: "1.0")
100100

101101
try await server.start(transport: serverTransport)
102-
try await client.connect(transport: clientTransport)
103102

104103
let initTask = Task {
105-
let result = try await client.initialize()
104+
let result = try await client.connect(transport: clientTransport)
106105

107106
#expect(result.serverInfo.name == "TestServer")
108107
#expect(result.serverInfo.version == "1.0.0")

‎Tests/MCPTests/SamplingTests.swift

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -587,30 +587,6 @@ struct SamplingIntegrationTests {
587587
try await server.start(transport: serverTransport)
588588
try await client.connect(transport: clientTransport)
589589

590-
// Test initialization and capability negotiation
591-
let initTask = Task {
592-
let result = try await client.initialize()
593-
594-
#expect(result.serverInfo.name == "SamplingTestServer")
595-
#expect(result.serverInfo.version == "1.0.0")
596-
#expect(
597-
result.capabilities.sampling != nil, "Server should advertise sampling capability")
598-
#expect(result.protocolVersion == Version.latest)
599-
}
600-
601-
try await withThrowingTaskGroup(of: Void.self) { group in
602-
group.addTask {
603-
try await Task.sleep(for: .seconds(1))
604-
initTask.cancel()
605-
throw CancellationError()
606-
}
607-
group.addTask {
608-
try await initTask.value
609-
}
610-
try await group.next()
611-
group.cancelAll()
612-
}
613-
614590
await server.stop()
615591
await client.disconnect()
616592
try? clientToServerRead.close()

0 commit comments

Comments
 (0)
Please sign in to comment.