Module: MCPClient

Defined in:
lib/mcp_client.rb,
lib/mcp_client/auth.rb,
lib/mcp_client/root.rb,
lib/mcp_client/task.rb,
lib/mcp_client/tool.rb,
lib/mcp_client/client.rb,
lib/mcp_client/errors.rb,
lib/mcp_client/prompt.rb,
lib/mcp_client/version.rb,
lib/mcp_client/resource.rb,
lib/mcp_client/server_sse.rb,
lib/mcp_client/server_base.rb,
lib/mcp_client/server_http.rb,
lib/mcp_client/oauth_client.rb,
lib/mcp_client/server_stdio.rb,
lib/mcp_client/audio_content.rb,
lib/mcp_client/config_parser.rb,
lib/mcp_client/resource_link.rb,
lib/mcp_client/server_factory.rb,
lib/mcp_client/json_rpc_common.rb,
lib/mcp_client/resource_content.rb,
lib/mcp_client/schema_validator.rb,
lib/mcp_client/resource_template.rb,
lib/mcp_client/auth/browser_oauth.rb,
lib/mcp_client/auth/oauth_provider.rb,
lib/mcp_client/http_transport_base.rb,
lib/mcp_client/elicitation_validator.rb,
lib/mcp_client/server_sse/sse_parser.rb,
lib/mcp_client/server_streamable_http.rb,
lib/mcp_client/server_sse/reconnect_monitor.rb,
lib/mcp_client/server_sse/json_rpc_transport.rb,
lib/mcp_client/server_http/json_rpc_transport.rb,
lib/mcp_client/server_stdio/json_rpc_transport.rb,
lib/mcp_client/server_streamable_http/json_rpc_transport.rb

Overview

Model Context Protocol (MCP) Client module Provides a standardized way for agents to communicate with external tools and services through a protocol-based approach

Defined Under Namespace

Modules: Auth, ElicitationValidator, Errors, HttpTransportBase, JsonRpcCommon, SchemaValidator Classes: AudioContent, Client, ConfigParser, OAuthClient, Prompt, Resource, ResourceContent, ResourceLink, ResourceTemplate, Root, ServerBase, ServerFactory, ServerHTTP, ServerSSE, ServerStdio, ServerStreamableHTTP, Task, Tool

Constant Summary collapse

VERSION =

Current version of the MCP client gem

'2.0.0'
PROTOCOL_VERSION =

MCP protocol version (date-based) - unified across all transports

'2025-11-25'
SUPPORTED_PROTOCOL_VERSIONS =

Protocol revisions this client can speak, newest first. Used during version negotiation: if the server answers initialize with a version outside this set, the client must disconnect (MCP lifecycle).

%w[2025-11-25 2025-06-18 2025-03-26 2024-11-05].freeze

Class Method Summary collapse

Class Method Details

.connect(target) {|Faraday::Connection| ... } ⇒ MCPClient::Client

Simplified connection API - auto-detects transport and returns connected client

Accepts keyword arguments for connection options:

  • headers [Hash] HTTP headers for remote transports
  • read_timeout [Integer] Request timeout in seconds (default: 30)
  • retries [Integer] Retry attempts
  • retry_backoff [Numeric] Backoff delay (default: 1)
  • name [String] Optional server name
  • logger [Logger] Optional logger
  • env [Hash] Environment variables for stdio
  • ping [Integer] Ping interval for SSE (default: 10)
  • endpoint [String] JSON-RPC endpoint path (default: '/rpc')
  • transport [Symbol] Force transport type (:stdio, :sse, :http, :streamable_http)
  • sampling_handler [Proc] Handler for sampling requests

Examples:

Connect to SSE server

client = MCPClient.connect('http://localhost:8000/sse')

Connect to Streamable HTTP server

client = MCPClient.connect('http://localhost:8000/mcp')

Connect with options

client = MCPClient.connect('http://api.example.com/mcp',
  headers: { 'Authorization' => 'Bearer token' },
  read_timeout: 60
)

Connect to stdio server

client = MCPClient.connect('npx -y @modelcontextprotocol/server-filesystem /home')
# or with Array
client = MCPClient.connect(['npx', '-y', '@modelcontextprotocol/server-filesystem', '/home'])

Connect to multiple servers

client = MCPClient.connect(['http://server1/mcp', 'http://server2/sse'])

Force transport type

client = MCPClient.connect('http://custom-server.com', transport: :streamable_http)

With Faraday customization

client = MCPClient.connect('https://internal.server.com/mcp') do |faraday|
  faraday.ssl.cert_store = custom_cert_store
end

Parameters:

  • target (String, Array<String>)

    URL(s) or command for connection

    • URLs ending in /sse -> SSE transport
    • URLs ending in /mcp -> Streamable HTTP transport
    • stdio://command or Array commands -> stdio transport
    • Commands starting with npx, node, python, ruby, etc. -> stdio transport
    • Other HTTP URLs -> Try Streamable HTTP, fallback to SSE, then HTTP

Yields:

  • (Faraday::Connection)

    Optional block for Faraday customization

Returns:

Raises:



84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/mcp_client.rb', line 84

def self.connect(target, **, &)
  # Handle array targets: either a single stdio command or multiple server URLs
  if target.is_a?(Array)
    # Check if it's a stdio command array (elements are command parts, not URLs)
    if stdio_command_array?(target)
      connect_single(target, **, &)
    else
      # It's an array of server URLs/commands
      connect_multiple(target, **, &)
    end
  else
    connect_single(target, **, &)
  end
end

.create_client(mcp_server_configs: [], server_definition_file: nil, logger: nil) ⇒ MCPClient::Client

Create a new MCPClient client

Parameters:

  • mcp_server_configs (Array<Hash>) (defaults to: [])

    configurations for MCP servers

  • server_definition_file (String, nil) (defaults to: nil)

    optional path to a JSON file defining server configurations The JSON may be a single server object or an array of server objects.

  • logger (Logger, nil) (defaults to: nil)

    optional logger for client operations

Returns:



344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/mcp_client.rb', line 344

def self.create_client(mcp_server_configs: [], server_definition_file: nil, logger: nil)
  require 'json'
  # Start with any explicit configs provided
  configs = Array(mcp_server_configs)
  # Load additional configs from a JSON file if specified
  if server_definition_file
    # Parse JSON definitions into clean config hashes
    parser = MCPClient::ConfigParser.new(server_definition_file, logger: logger)
    parsed = parser.parse
    parsed.each_value do |cfg|
      case cfg[:type].to_s
      when 'stdio'
        cmd_list = [cfg[:command]] + Array(cfg[:args])
        configs << MCPClient.stdio_config(
          command: cmd_list,
          name: cfg[:name],
          logger: logger,
          env: cfg[:env]
        )
      when 'sse'
        configs << MCPClient.sse_config(base_url: cfg[:url], headers: cfg[:headers] || {}, name: cfg[:name],
                                        logger: logger)
      when 'http'
        configs << MCPClient.http_config(base_url: cfg[:url], endpoint: cfg[:endpoint],
                                         headers: cfg[:headers] || {}, name: cfg[:name], logger: logger)
      when 'streamable_http'
        configs << MCPClient.streamable_http_config(base_url: cfg[:url], endpoint: cfg[:endpoint],
                                                    headers: cfg[:headers] || {}, name: cfg[:name], logger: logger)
      end
    end
  end
  MCPClient::Client.new(mcp_server_configs: configs, logger: logger)
end

.http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3, retry_backoff: 1, name: nil, logger: nil) {|faraday| ... } ⇒ Hash

Create a standard server configuration for HTTP

Parameters:

  • base_url (String)

    base URL for the server

  • endpoint (String) (defaults to: '/rpc')

    JSON-RPC endpoint path (default: '/rpc')

  • headers (Hash) (defaults to: {})

    HTTP headers to include in requests

  • read_timeout (Integer) (defaults to: 30)

    read timeout in seconds (default: 30)

  • retries (Integer) (defaults to: 3)

    number of retry attempts (default: 3)

  • retry_backoff (Integer) (defaults to: 1)

    backoff delay in seconds (default: 1)

  • name (String, nil) (defaults to: nil)

    optional name for this server

  • logger (Logger, nil) (defaults to: nil)

    optional logger for server operations

Yield Parameters:

  • faraday (Faraday::Connection)

    the configured connection instance for additional customization (e.g., SSL settings, custom middleware). The block is called after default configuration is applied.

Returns:

  • (Hash)

    server configuration



430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# File 'lib/mcp_client.rb', line 430

def self.http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3, retry_backoff: 1,
                     name: nil, logger: nil, &faraday_config)
  {
    type: 'http',
    base_url: base_url,
    endpoint: endpoint,
    headers: headers,
    read_timeout: read_timeout,
    retries: retries,
    retry_backoff: retry_backoff,
    name: name,
    logger: logger,
    faraday_config: faraday_config
  }
end

.parse_content_item(item) ⇒ MCPClient::ResourceLink, Hash

Parse a single content item from a tool result into a typed object Recognizes 'resource_link' type and returns an MCPClient::ResourceLink. Unrecognized types are returned as-is (the original Hash).

Parameters:

  • item (Hash)

    a content item with a 'type' field

Returns:



480
481
482
483
484
485
486
487
# File 'lib/mcp_client.rb', line 480

def self.parse_content_item(item)
  case item['type']
  when 'resource_link'
    ResourceLink.from_json(item)
  else
    item
  end
end

.parse_tool_content(content) ⇒ Array<MCPClient::ResourceLink, Hash>

Parse the content array from a tool result into typed objects Each item with type 'resource_link' is converted to an MCPClient::ResourceLink. Other items are returned as-is.

Parameters:

  • content (Array<Hash>)

    content array from a tool result

Returns:



494
495
496
# File 'lib/mcp_client.rb', line 494

def self.parse_tool_content(content)
  Array(content).map { |item| parse_content_item(item) }
end

.sse_config(base_url:, headers: {}, read_timeout: 30, ping: 10, retries: 0, retry_backoff: 1, name: nil, logger: nil) ⇒ Hash

Create a standard server configuration for SSE

Parameters:

  • base_url (String)

    base URL for the server

  • headers (Hash) (defaults to: {})

    HTTP headers to include in requests

  • read_timeout (Integer) (defaults to: 30)

    read timeout in seconds (default: 30)

  • ping (Integer) (defaults to: 10)

    time in seconds after which to send ping if no activity (default: 10)

  • retries (Integer) (defaults to: 0)

    number of retry attempts (default: 0)

  • retry_backoff (Integer) (defaults to: 1)

    backoff delay in seconds (default: 1)

  • name (String, nil) (defaults to: nil)

    optional name for this server

  • logger (Logger, nil) (defaults to: nil)

    optional logger for server operations

Returns:

  • (Hash)

    server configuration



403
404
405
406
407
408
409
410
411
412
413
414
415
416
# File 'lib/mcp_client.rb', line 403

def self.sse_config(base_url:, headers: {}, read_timeout: 30, ping: 10, retries: 0, retry_backoff: 1,
                    name: nil, logger: nil)
  {
    type: 'sse',
    base_url: base_url,
    headers: headers,
    read_timeout: read_timeout,
    ping: ping,
    retries: retries,
    retry_backoff: retry_backoff,
    name: name,
    logger: logger
  }
end

.stdio_config(command:, name: nil, logger: nil, env: {}) ⇒ Hash

Create a standard server configuration for stdio

Parameters:

  • command (String, Array<String>)

    command to execute

  • name (String, nil) (defaults to: nil)

    optional name for this server

  • logger (Logger, nil) (defaults to: nil)

    optional logger for server operations

Returns:

  • (Hash)

    server configuration



383
384
385
386
387
388
389
390
391
# File 'lib/mcp_client.rb', line 383

def self.stdio_config(command:, name: nil, logger: nil, env: {})
  {
    type: 'stdio',
    command: command,
    name: name,
    logger: logger,
    env: env || {}
  }
end

.streamable_http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3, retry_backoff: 1, name: nil, logger: nil) {|faraday| ... } ⇒ Hash

Create configuration for Streamable HTTP transport This transport uses HTTP POST requests but expects Server-Sent Event formatted responses

Parameters:

  • base_url (String)

    Base URL of the MCP server

  • endpoint (String) (defaults to: '/rpc')

    JSON-RPC endpoint path (default: '/rpc')

  • headers (Hash) (defaults to: {})

    Additional headers to include in requests

  • read_timeout (Integer) (defaults to: 30)

    Read timeout in seconds (default: 30)

  • retries (Integer) (defaults to: 3)

    Number of retry attempts on transient errors (default: 3)

  • retry_backoff (Integer) (defaults to: 1)

    Backoff delay in seconds (default: 1)

  • name (String, nil) (defaults to: nil)

    Optional name for this server

  • logger (Logger, nil) (defaults to: nil)

    Optional logger for server operations

Yield Parameters:

  • faraday (Faraday::Connection)

    the configured connection instance for additional customization (e.g., SSL settings, custom middleware). The block is called after default configuration is applied.

Returns:

  • (Hash)

    server configuration



459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
# File 'lib/mcp_client.rb', line 459

def self.streamable_http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3,
                                retry_backoff: 1, name: nil, logger: nil, &faraday_config)
  {
    type: 'streamable_http',
    base_url: base_url,
    endpoint: endpoint,
    headers: headers,
    read_timeout: read_timeout,
    retries: retries,
    retry_backoff: retry_backoff,
    name: name,
    logger: logger,
    faraday_config: faraday_config
  }
end