ExMCP.ClientConfig (ex_mcp v0.9.0)
View SourceConfiguration builder for ExMCP clients.
This module provides a fluent interface for building client configurations, ensuring type safety and validation at compile time.
Usage
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_transport(:http)
|> ExMCP.ClientConfig.put_url("https://api.example.com")
|> ExMCP.ClientConfig.put_transport_options(
timeout: 30_000,
pool_size: 10
)
{:ok, client} = ExMCP.Client.connect(config)Transport Configuration
stdio Transport
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_transport(:stdio)
|> ExMCP.ClientConfig.put_command(["python", "server.py"])
|> ExMCP.ClientConfig.put_args(["--verbose"])
|> ExMCP.ClientConfig.put_env([{"DEBUG", "1"}])HTTP Transport
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_transport(:http)
|> ExMCP.ClientConfig.put_url("https://api.example.com")
|> ExMCP.ClientConfig.put_headers([{"Authorization", "Bearer token"}])
|> ExMCP.ClientConfig.put_transport_options(
use_sse: true,
timeout: 10_000
)Advanced Options
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_name(:my_client)
|> ExMCP.ClientConfig.put_handler(MyClientHandler)
|> ExMCP.ClientConfig.put_retry_policy(
max_attempts: 3,
backoff: :exponential
)Basic Usage
# Create a simple HTTP configuration
config = ExMCP.ClientConfig.new(:http, url: "http://localhost:8080")
{:ok, client} = ExMCP.connect(config)Advanced Usage
# Create a production configuration with full settings
config = ExMCP.ClientConfig.new(:production)
|> ExMCP.ClientConfig.put_transport(:http, url: "https://api.example.com")
|> ExMCP.ClientConfig.put_retry_policy(max_attempts: 5, base_interval: 1000)
|> ExMCP.ClientConfig.put_timeout(connect: 10_000, request: 30_000)
|> ExMCP.ClientConfig.put_auth(:bearer, token: "...")
{:ok, client} = ExMCP.connect(config)Configuration Profiles
Built-in profiles:
:development- For local development with debugging:test- For testing with fast timeouts:production- For production with robust retry policies:http- HTTP transport with sensible defaults:stdio- Stdio transport configuration:native- Native BEAM transport configuration
Summary
Functions
Timeout configuration for ExMCP operations.
Adds a fallback transport configuration.
Gets the list of all transport configurations (primary + fallbacks).
Creates a new client configuration.
Configures authentication settings.
Sets client information.
Adds custom configuration options.
Configures observability settings.
Configures connection pooling settings.
Configures retry policy settings.
Configures timeout settings.
Configures the transport settings.
Converts the configuration to a keyword list suitable for client APIs.
Validates the configuration and returns errors if any.
Types
@type auth_config() :: %{ type: auth_type(), token: String.t() | nil, username: String.t() | nil, password: String.t() | nil, headers: %{required(String.t()) => String.t()}, refresh_token: String.t() | nil, client_id: String.t() | nil, client_secret: String.t() | nil, custom_handler: {module(), atom(), [any()]} | nil }
@type auth_type() :: :none | :bearer | :basic | :oauth | :custom
@type log_level() :: :debug | :info | :warn | :error | :none
@type observability_config() :: %{ logging: %{ enabled: boolean(), level: log_level(), format: :text | :json, include_request_id: boolean(), include_metadata: boolean() }, telemetry: %{ enabled: boolean(), prefix: [atom()], include_system_metrics: boolean() }, tracing: %{ enabled: boolean(), sampler: atom() | {module(), atom(), [any()]}, propagators: [atom()] } }
@type pool_config() :: %{ enabled: boolean(), size: pos_integer(), max_overflow: non_neg_integer(), checkout_timeout: pos_integer(), idle_timeout: pos_integer() }
@type profile() :: atom()
@type retry_policy() :: %{ enabled: boolean(), max_attempts: pos_integer(), base_interval: pos_integer(), max_interval: pos_integer(), backoff_type: :linear | :exponential | :fixed, jitter: boolean() }
@type t() :: %ExMCP.ClientConfig{ auth: auth_config(), client_info: %{name: String.t(), version: String.t(), user_agent: String.t()}, custom_options: %{required(atom()) => any()}, fallback_transports: [transport_config()], observability: observability_config(), pool: pool_config(), profile: profile() | nil, retry_policy: retry_policy(), timeouts: timeout_config(), transport: transport_config() }
@type timeout_config() :: %{ total: pos_integer(), connect: pos_integer(), request: pos_integer(), stream: %{handshake: pos_integer(), idle: pos_integer()}, pool: %{checkout: pos_integer(), idle: pos_integer()} }
@type transport_type() :: :http | :stdio | :sse | :native | :beam
Functions
Timeout configuration for ExMCP operations.
total: Maximum time for an entire logical operation, including all retries (ms)connect: Time to establish initial TCP/TLS connection (ms)request: Time for a single request-response cycle (ms)stream: Timeouts specific to persistent streams like SSEhandshake: Time to wait for stream handshake after connection (ms)idle: Time a stream can be idle before being considered dead (ms)
pool: Connection pool related timeoutscheckout: Time to wait for a connection from the pool (ms)idle: Time a connection can sit idle in the pool (ms)
@spec add_fallback(t(), transport_type(), keyword()) :: t()
Adds a fallback transport configuration.
Examples
config = ExMCP.ClientConfig.new(:http, url: "http://primary:8080")
|> ExMCP.ClientConfig.add_fallback(:http, url: "http://backup:8080")
|> ExMCP.ClientConfig.add_fallback(:stdio, command: "local-server")
@spec get_all_transports(t()) :: [transport_config()]
Gets the list of all transport configurations (primary + fallbacks).
Examples
transports = ExMCP.ClientConfig.get_all_transports(config)
# Try connecting to each transport in order
@spec new() :: t()
Creates a new client configuration.
Examples
# Use a predefined profile
config = ExMCP.ClientConfig.new(:production)
# Create HTTP configuration with custom options
config = ExMCP.ClientConfig.new(:http, url: "http://localhost:8080")
# Create stdio configuration
config = ExMCP.ClientConfig.new(:stdio, command: ["python", "server.py"])
# Start with empty configuration
config = ExMCP.ClientConfig.new()
@spec new(profile() | transport_type()) :: t()
@spec new( transport_type(), keyword() ) :: t()
Configures authentication settings.
Examples
# Bearer token
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_auth(:bearer, token: "your-token")
# Basic auth
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_auth(:basic, username: "user", password: "pass")
# Custom headers
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_auth(:custom, headers: %{"X-API-Key" => "key"})
Sets client information.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_client_info(
name: "MyApp MCP Client",
version: "1.0.0"
)
Adds custom configuration options.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_custom(:my_option, "value")
|> ExMCP.ClientConfig.put_custom(:another_option, %{key: "value"})
Configures observability settings.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_observability(
logging: [enabled: true, level: :info],
telemetry: [enabled: true, prefix: [:my_app, :mcp]]
)
Configures connection pooling settings.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_pool(
enabled: true,
size: 10,
max_overflow: 5
)
Configures retry policy settings.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_retry_policy(
max_attempts: 5,
base_interval: 1000,
backoff_type: :exponential
)
Configures timeout settings.
Examples
# Basic timeouts
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_timeout(
total: 120_000,
connect: 10_000,
request: 30_000
)
# Advanced timeouts with stream and pool settings
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_timeout(
total: 120_000,
connect: 10_000,
request: 30_000,
stream: [handshake: 15_000, idle: 60_000],
pool: [checkout: 5_000, idle: 300_000]
)Timeout Types
total: Maximum time for entire operation including retries (ms)connect: Time to establish TCP/TLS connection (ms)request: Time for single request-response cycle (ms)stream.handshake: Time to wait for SSE handshake completion (ms)stream.idle: Time stream can be idle before considered dead (ms)pool.checkout: Time to wait for connection from pool (ms)pool.idle: Time connection can idle in pool before cleanup (ms)
@spec put_transport(t(), transport_type(), keyword()) :: t()
Configures the transport settings.
Examples
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_transport(:http, url: "http://localhost:8080")
config = ExMCP.ClientConfig.new()
|> ExMCP.ClientConfig.put_transport(:stdio, command: ["python", "server.py"])
Converts the configuration to a keyword list suitable for client APIs.
Examples
config = ExMCP.ClientConfig.new(:http, url: "http://localhost:8080")
opts = ExMCP.ClientConfig.to_client_opts(config)
{:ok, client} = ExMCP.Client.start_link(opts)
Validates the configuration and returns errors if any.
Examples
case ExMCP.ClientConfig.validate(config) do
:ok -> {:ok, client} = ExMCP.connect(config)
{:error, errors} -> handle_config_errors(errors)
end