SDKMCPClient
SDKMCPClient is the production MCPClient that ships with AgentSquadMCP. It wraps the official MCP Swift SDK (Client + HTTPClientTransport) and confines the SDK entirely to this type — nothing above the MCPClient seam ever imports it.
You rarely construct SDKMCPClient directly. The MCPServer(url:) convenience initializers create one for you. Use the direct initializer only when you need to customize clientName, clientVersion, or streaming and then pass the client to MCPToolProvider(client:).
Initializer
Section titled “Initializer”public init( endpoint: URL, clientName: String = SDKMCPClient.defaultClientName, // "AgentSquad" clientVersion: String = SDKMCPClient.defaultClientVersion, // "0.1.0" tokenProvider: (@Sendable () async -> String?)? = nil, streaming: Bool = true)| Parameter | Default | Notes |
|---|---|---|
endpoint | — | The MCP server URL |
clientName | "AgentSquad" | Identity sent on the MCP initialize handshake |
clientVersion | "0.1.0" | Identity sent on the MCP initialize handshake |
tokenProvider | nil | Async closure returning a Bearer token; called once per connect() |
streaming | true | Whether the transport uses HTTP streaming |
Default identity constants
Section titled “Default identity constants”public static let defaultClientName = "AgentSquad"public static let defaultClientVersion = "0.1.0"These constants are shared between SDKMCPClient and the MCPServer(url:) convenience initializers so the two construction paths never drift apart.
Authentication
Section titled “Authentication”SDKMCPClient fetches the Bearer token from tokenProvider at connect() and injects it via the transport’s synchronous requestModifier, making the token fixed for the session. A mid-session 401 surfaces as a thrown error from the call site; the MCPToolProvider recover path is disconnect() + connect(), which fetches a fresh token.
Pagination
Section titled “Pagination”listTools() paginates to completion automatically. It guards against cursor cycles (A → B → A) by tracking every cursor it has seen and breaking the loop on a repeat. No configuration is required.
Error handling
Section titled “Error handling”SDKMCPClient throws MCPClientError for infrastructure-level failures:
| Case | When |
|---|---|
.notConnected | A method is called before connect() succeeds |
.emptyResource(String) | readResource returns no content for the given URI |
These are transport or protocol failures, not tool-level errors. They propagate as thrown errors; MCPToolProvider does not wrap them in a ToolResult.
Via the convenience initializers (typical)
Section titled “Via the convenience initializers (typical)”The MCPServer(url:) overloads on MCPToolProvider construct an SDKMCPClient for you:
import AgentSquadimport AgentSquadMCP
// String overloadlet tools = MCPServer(url: "https://mcp.example.com/sse")
// URL overload with authlet tools = MCPServer( url: URL(string: "https://mcp.example.com/sse")!, tokenProvider: { await TokenStore.shared.currentToken() })Direct construction (custom identity or transport mode)
Section titled “Direct construction (custom identity or transport mode)”import AgentSquadMCP
let client = SDKMCPClient( endpoint: URL(string: "https://mcp.example.com/sse")!, clientName: "MyApp", clientVersion: "2.0.0", tokenProvider: { await TokenStore.shared.currentToken() }, streaming: false // fall back to request/response if SSE is not supported)
let tools = MCPToolProvider( client: client, hostArguments: ["session_id": .string(sessionId)])Related pages
Section titled “Related pages”- MCP overview —
MCPToolProvider,MCPServer, supporting types, host arguments, and MCP Apps UI. - Custom MCP client — replace
SDKMCPClientwith your own transport or a test double. - Tools overview — the
ToolProviderprotocol thatMCPToolProviderimplements.