actionmcp 0.102.0 → 0.103.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +11 -3
- data/lib/action_mcp/test_helper/session_store_assertions.rb +0 -70
- data/lib/action_mcp/version.rb +1 -1
- data/lib/action_mcp.rb +0 -1
- metadata +2 -27
- data/lib/action_mcp/client/active_record_session_store.rb +0 -57
- data/lib/action_mcp/client/base.rb +0 -225
- data/lib/action_mcp/client/blueprint.rb +0 -163
- data/lib/action_mcp/client/catalog.rb +0 -164
- data/lib/action_mcp/client/collection.rb +0 -168
- data/lib/action_mcp/client/elicitation.rb +0 -34
- data/lib/action_mcp/client/json_rpc_handler.rb +0 -202
- data/lib/action_mcp/client/logging.rb +0 -19
- data/lib/action_mcp/client/messaging.rb +0 -28
- data/lib/action_mcp/client/prompt_book.rb +0 -117
- data/lib/action_mcp/client/prompts.rb +0 -47
- data/lib/action_mcp/client/request_timeouts.rb +0 -74
- data/lib/action_mcp/client/resources.rb +0 -100
- data/lib/action_mcp/client/roots.rb +0 -13
- data/lib/action_mcp/client/server.rb +0 -60
- data/lib/action_mcp/client/session_store.rb +0 -39
- data/lib/action_mcp/client/session_store_factory.rb +0 -27
- data/lib/action_mcp/client/streamable_client.rb +0 -264
- data/lib/action_mcp/client/streamable_http_transport.rb +0 -306
- data/lib/action_mcp/client/test_session_store.rb +0 -84
- data/lib/action_mcp/client/toolbox.rb +0 -199
- data/lib/action_mcp/client/tools.rb +0 -47
- data/lib/action_mcp/client/transport.rb +0 -137
- data/lib/action_mcp/client/volatile_session_store.rb +0 -38
- data/lib/action_mcp/client.rb +0 -71
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActionMCP
|
|
4
|
-
module Client
|
|
5
|
-
# Toolbox
|
|
6
|
-
#
|
|
7
|
-
# A collection that manages and provides access to tools from the server.
|
|
8
|
-
# This class stores tool definitions along with their input schemas and
|
|
9
|
-
# provides methods for retrieving, filtering, and accessing tools.
|
|
10
|
-
#
|
|
11
|
-
# Example usage:
|
|
12
|
-
# tools_data = client.list_tools # Returns array of tool definitions
|
|
13
|
-
# toolbox = Toolbox.new(tools_data)
|
|
14
|
-
#
|
|
15
|
-
# # Access a specific tool by name
|
|
16
|
-
# weather_tool = toolbox.find("weather_forecast")
|
|
17
|
-
#
|
|
18
|
-
# # Get all tools matching a criteria
|
|
19
|
-
# calculation_tools = toolbox.filter { |t| t.name.include?("calculate") }
|
|
20
|
-
#
|
|
21
|
-
class Toolbox < Collection
|
|
22
|
-
# Initialize a new Toolbox with tool definitions
|
|
23
|
-
#
|
|
24
|
-
# @param tools [Array<Hash>] Array of tool definition hashes, each containing
|
|
25
|
-
# name, description, and inputSchema keys
|
|
26
|
-
def initialize(tools, client)
|
|
27
|
-
super(tools, client)
|
|
28
|
-
self.tools = @collection_data
|
|
29
|
-
@load_method = :list_tools
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Find a tool by name
|
|
33
|
-
#
|
|
34
|
-
# @param name [String] Name of the tool to find
|
|
35
|
-
# @return [Tool, nil] The tool with the given name, or nil if not found
|
|
36
|
-
def find(name)
|
|
37
|
-
all.find { |tool| tool.name == name }
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
# Filter tools based on a given block
|
|
41
|
-
#
|
|
42
|
-
# @yield [tool] Block that determines whether to include a tool
|
|
43
|
-
# @yieldparam tool [Tool] A tool from the collection
|
|
44
|
-
# @yieldreturn [Boolean] true to include the tool, false to exclude it
|
|
45
|
-
# @return [Array<Tool>] Tools that match the filter criteria
|
|
46
|
-
def filter(&block)
|
|
47
|
-
all.select(&block)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Get a list of all tool names
|
|
51
|
-
#
|
|
52
|
-
# @return [Array<String>] Names of all tools in the collection
|
|
53
|
-
def names
|
|
54
|
-
all.map(&:name)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Number of tools in the collection
|
|
58
|
-
#
|
|
59
|
-
# @return [Integer] The number of tools
|
|
60
|
-
def size
|
|
61
|
-
all.size
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# Check if the collection contains a tool with the given name
|
|
65
|
-
#
|
|
66
|
-
# @param name [String] The tool name to check for
|
|
67
|
-
# @return [Boolean] true if a tool with the name exists
|
|
68
|
-
def contains?(name)
|
|
69
|
-
all.any? { |tool| tool.name == name }
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
# Get tools by category or type
|
|
73
|
-
#
|
|
74
|
-
# @param keyword [String] Keyword to search for in tool names and descriptions
|
|
75
|
-
# @return [Array<Tool>] Tools containing the keyword
|
|
76
|
-
def search(keyword)
|
|
77
|
-
all.select do |tool|
|
|
78
|
-
tool.name.include?(keyword) ||
|
|
79
|
-
tool.description&.downcase&.include?(keyword.downcase)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Generate a hash representation of all tools in the collection based on provider format
|
|
84
|
-
#
|
|
85
|
-
# @param provider [Symbol] The provider format to use (:claude, :openai, or :default)
|
|
86
|
-
# @return [Hash] Hash containing all tools formatted for the specified provider
|
|
87
|
-
def to_h(provider = :default)
|
|
88
|
-
case provider
|
|
89
|
-
when :claude
|
|
90
|
-
# Claude format
|
|
91
|
-
{ "tools" => all.map(&:to_claude_h) }
|
|
92
|
-
when :openai
|
|
93
|
-
# OpenAI format
|
|
94
|
-
{ "tools" => all.map(&:to_openai_h) }
|
|
95
|
-
else
|
|
96
|
-
# Default format (same as original)
|
|
97
|
-
{ "tools" => all.map(&:to_h) }
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def tools=(tools)
|
|
102
|
-
@collection_data = tools.map { |tool_data| Tool.new(tool_data) }
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Internal Tool class to represent individual tools
|
|
106
|
-
class Tool
|
|
107
|
-
attr_reader :name, :description, :input_schema, :annotations
|
|
108
|
-
|
|
109
|
-
# Initialize a new Tool instance
|
|
110
|
-
#
|
|
111
|
-
# @param data [Hash] Tool definition hash containing name, description, and inputSchema
|
|
112
|
-
# and optionally annotations
|
|
113
|
-
def initialize(data)
|
|
114
|
-
@name = data["name"]
|
|
115
|
-
@description = data["description"]
|
|
116
|
-
@input_schema = data["inputSchema"] || {}
|
|
117
|
-
@annotations = data["annotations"] || {}
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Get all required properties for this tool
|
|
121
|
-
#
|
|
122
|
-
# @return [Array<String>] Array of required property names
|
|
123
|
-
def required_properties
|
|
124
|
-
@input_schema["required"] || []
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# Get all properties for this tool
|
|
128
|
-
#
|
|
129
|
-
# @return [Hash] Hash of property definitions
|
|
130
|
-
def properties
|
|
131
|
-
@input_schema["properties"] || {}
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Check if the tool requires a specific property
|
|
135
|
-
#
|
|
136
|
-
# @param name [String] Name of the property to check
|
|
137
|
-
# @return [Boolean] true if the property is required
|
|
138
|
-
def requires?(name)
|
|
139
|
-
required_properties.include?(name)
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
# Check if the tool has a specific property
|
|
143
|
-
#
|
|
144
|
-
# @param name [String] Name of the property to check
|
|
145
|
-
# @return [Boolean] true if the property exists
|
|
146
|
-
def has_property?(name)
|
|
147
|
-
properties.key?(name)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
# Get property details by name
|
|
151
|
-
#
|
|
152
|
-
# @param name [String] Name of the property
|
|
153
|
-
# @return [Hash, nil] Property details or nil if not found
|
|
154
|
-
def property(name)
|
|
155
|
-
properties[name]
|
|
156
|
-
end
|
|
157
|
-
|
|
158
|
-
# Generate a hash representation of the tool (default format)
|
|
159
|
-
#
|
|
160
|
-
# @return [Hash] Hash containing tool details
|
|
161
|
-
def to_h
|
|
162
|
-
{
|
|
163
|
-
"name" => @name,
|
|
164
|
-
"description" => @description,
|
|
165
|
-
"inputSchema" => @input_schema,
|
|
166
|
-
"annotations" => @annotations
|
|
167
|
-
}
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
# Generate a hash representation of the tool in Claude format
|
|
171
|
-
#
|
|
172
|
-
# @return [Hash] Hash containing tool details formatted for Claude
|
|
173
|
-
def to_claude_h
|
|
174
|
-
{
|
|
175
|
-
"name" => @name,
|
|
176
|
-
"description" => @description,
|
|
177
|
-
"input_schema" => @input_schema.transform_keys { |k| k == "inputSchema" ? "input_schema" : k },
|
|
178
|
-
"annotations" => @annotations
|
|
179
|
-
}
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
# Generate a hash representation of the tool in OpenAI format
|
|
183
|
-
#
|
|
184
|
-
# @return [Hash] Hash containing tool details formatted for OpenAI
|
|
185
|
-
def to_openai_h
|
|
186
|
-
{
|
|
187
|
-
"type" => "function",
|
|
188
|
-
"function" => {
|
|
189
|
-
"name" => @name,
|
|
190
|
-
"description" => @description,
|
|
191
|
-
"parameters" => @input_schema,
|
|
192
|
-
"annotations" => @annotations
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
end
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
end
|
|
199
|
-
end
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActionMCP
|
|
4
|
-
module Client
|
|
5
|
-
module Tools
|
|
6
|
-
# List all available tools from the server
|
|
7
|
-
# @param params [Hash] Optional parameters for pagination
|
|
8
|
-
# @option params [String] :cursor Pagination cursor for fetching next page
|
|
9
|
-
# @option params [Integer] :limit Maximum number of items to return
|
|
10
|
-
# @return [String] Request ID for tracking the request
|
|
11
|
-
def list_tools(params = {})
|
|
12
|
-
request_id = SecureRandom.uuid_v7
|
|
13
|
-
|
|
14
|
-
# Send request with pagination parameters if provided
|
|
15
|
-
request_params = {}
|
|
16
|
-
request_params[:cursor] = params[:cursor] if params[:cursor]
|
|
17
|
-
request_params[:limit] = params[:limit] if params[:limit]
|
|
18
|
-
|
|
19
|
-
send_jsonrpc_request("tools/list",
|
|
20
|
-
params: request_params.empty? ? nil : request_params,
|
|
21
|
-
id: request_id)
|
|
22
|
-
|
|
23
|
-
# Return request ID for timeout tracking
|
|
24
|
-
request_id
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Call a specific tool on the server
|
|
28
|
-
# @param name [String] Name of the tool to call
|
|
29
|
-
# @param arguments [Hash] Arguments to pass to the tool
|
|
30
|
-
# @return [String] Request ID for tracking the request
|
|
31
|
-
def call_tool(name, arguments)
|
|
32
|
-
request_id = SecureRandom.uuid_v7
|
|
33
|
-
|
|
34
|
-
# Send request
|
|
35
|
-
send_jsonrpc_request("tools/call",
|
|
36
|
-
params: {
|
|
37
|
-
name: name,
|
|
38
|
-
arguments: arguments
|
|
39
|
-
},
|
|
40
|
-
id: request_id)
|
|
41
|
-
|
|
42
|
-
# Return request ID for tracking the request
|
|
43
|
-
request_id
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActionMCP
|
|
4
|
-
module Client
|
|
5
|
-
# Base transport interface for MCP client connections
|
|
6
|
-
module Transport
|
|
7
|
-
# Called when transport should establish connection
|
|
8
|
-
def connect
|
|
9
|
-
raise NotImplementedError, "#{self.class} must implement #connect"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# Called when transport should close connection
|
|
13
|
-
def disconnect
|
|
14
|
-
raise NotImplementedError, "#{self.class} must implement #disconnect"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Send a message through the transport
|
|
18
|
-
def send_message(message)
|
|
19
|
-
raise NotImplementedError, "#{self.class} must implement #send_message"
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# Check if transport is ready to send/receive
|
|
23
|
-
def ready?
|
|
24
|
-
raise NotImplementedError, "#{self.class} must implement #ready?"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Check if transport is connected
|
|
28
|
-
def connected?
|
|
29
|
-
raise NotImplementedError, "#{self.class} must implement #connected?"
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Set callback for received messages
|
|
33
|
-
def on_message(&block)
|
|
34
|
-
@message_callback = block
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# Set callback for errors
|
|
38
|
-
def on_error(&block)
|
|
39
|
-
@error_callback = block
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# Set callback for connection events
|
|
43
|
-
def on_connect(&block)
|
|
44
|
-
@connect_callback = block
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
# Set callback for disconnection events
|
|
48
|
-
def on_disconnect(&block)
|
|
49
|
-
@disconnect_callback = block
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
protected
|
|
53
|
-
|
|
54
|
-
def handle_message(message)
|
|
55
|
-
@message_callback&.call(message)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def handle_error(error)
|
|
59
|
-
@error_callback&.call(error)
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def handle_connect
|
|
63
|
-
@connect_callback&.call
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def handle_disconnect
|
|
67
|
-
@disconnect_callback&.call
|
|
68
|
-
end
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Base class for transport implementations
|
|
72
|
-
class TransportBase
|
|
73
|
-
include Transport
|
|
74
|
-
|
|
75
|
-
attr_reader :url, :options, :session_store
|
|
76
|
-
|
|
77
|
-
def initialize(url, session_store:, logger: ActionMCP.logger, **options)
|
|
78
|
-
@url = url
|
|
79
|
-
@session_store = session_store
|
|
80
|
-
@logger = logger
|
|
81
|
-
@options = options
|
|
82
|
-
@connected = false
|
|
83
|
-
@ready = false
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def connected?
|
|
87
|
-
@connected
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def ready?
|
|
91
|
-
@ready
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
protected
|
|
95
|
-
|
|
96
|
-
def set_connected(state)
|
|
97
|
-
@connected = state
|
|
98
|
-
state ? handle_connect : handle_disconnect
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
def set_ready(state)
|
|
102
|
-
@ready = state
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Logging methods for transport classes
|
|
106
|
-
def log_debug(message)
|
|
107
|
-
@logger.debug("[ActionMCP::#{self.class.name.split('::').last}] #{message}")
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def log_info(message)
|
|
111
|
-
@logger.info("[ActionMCP::#{self.class.name.split('::').last}] #{message}")
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def log_error(message)
|
|
115
|
-
@logger.error("[ActionMCP::#{self.class.name.split('::').last}] #{message}")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
private
|
|
119
|
-
|
|
120
|
-
def handle_connect
|
|
121
|
-
@connect_callback&.call
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
def handle_disconnect
|
|
125
|
-
@disconnect_callback&.call
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
def handle_error(error)
|
|
129
|
-
@error_callback&.call(error)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def handle_message(message)
|
|
133
|
-
@message_callback&.call(message)
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ActionMCP
|
|
4
|
-
module Client
|
|
5
|
-
# Volatile session store for development (data lost on restart)
|
|
6
|
-
class VolatileSessionStore
|
|
7
|
-
include SessionStore
|
|
8
|
-
|
|
9
|
-
def initialize
|
|
10
|
-
@sessions = Concurrent::Hash.new
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def load_session(session_id)
|
|
14
|
-
@sessions[session_id]
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def save_session(session_id, session_data)
|
|
18
|
-
@sessions[session_id] = session_data.dup
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def delete_session(session_id)
|
|
22
|
-
@sessions.delete(session_id)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def session_exists?(session_id)
|
|
26
|
-
@sessions.key?(session_id)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def clear_all
|
|
30
|
-
@sessions.clear
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def session_count
|
|
34
|
-
@sessions.size
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
data/lib/action_mcp/client.rb
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative "client/transport"
|
|
4
|
-
require_relative "client/session_store"
|
|
5
|
-
require_relative "client/streamable_http_transport"
|
|
6
|
-
|
|
7
|
-
module ActionMCP
|
|
8
|
-
# Creates a client appropriate for the given endpoint.
|
|
9
|
-
#
|
|
10
|
-
# @param endpoint [String] The endpoint to connect to (URL).
|
|
11
|
-
# @param transport [Symbol] The transport type to use (:streamable_http, :sse for legacy)
|
|
12
|
-
# @param session_store [Symbol] The session store type (:memory, :active_record)
|
|
13
|
-
# @param session_id [String] Optional session ID for resuming connections
|
|
14
|
-
# @param protocol_version [String] The MCP protocol version to use (defaults to ActionMCP::DEFAULT_PROTOCOL_VERSION)
|
|
15
|
-
# @param logger [Logger] The logger to use. Default is Logger.new($stdout).
|
|
16
|
-
# @param options [Hash] Additional options to pass to the client constructor.
|
|
17
|
-
#
|
|
18
|
-
# @return [Client::Base] An instance of the appropriate client.
|
|
19
|
-
#
|
|
20
|
-
# @example Basic usage
|
|
21
|
-
# client = ActionMCP.create_client("http://127.0.0.1:3001/action_mcp")
|
|
22
|
-
# client.connect
|
|
23
|
-
#
|
|
24
|
-
# @example With specific transport and session store
|
|
25
|
-
# client = ActionMCP.create_client(
|
|
26
|
-
# "http://127.0.0.1:3001/action_mcp",
|
|
27
|
-
# transport: :streamable_http,
|
|
28
|
-
# session_store: :active_record,
|
|
29
|
-
# session_id: "existing-session-123"
|
|
30
|
-
# )
|
|
31
|
-
#
|
|
32
|
-
# @example Memory-based for development
|
|
33
|
-
# client = ActionMCP.create_client(
|
|
34
|
-
# "http://127.0.0.1:3001/action_mcp",
|
|
35
|
-
# session_store: :memory
|
|
36
|
-
# )
|
|
37
|
-
#
|
|
38
|
-
def self.create_client(endpoint, transport: :streamable_http, session_store: nil, session_id: nil,
|
|
39
|
-
protocol_version: nil, logger: Logger.new($stdout), **options)
|
|
40
|
-
unless endpoint =~ %r{\Ahttps?://}
|
|
41
|
-
raise ArgumentError, "Only HTTP(S) endpoints are supported. STDIO and other transports are not supported."
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Create session store
|
|
45
|
-
store = Client::SessionStoreFactory.create(session_store, **options)
|
|
46
|
-
|
|
47
|
-
# Create transport
|
|
48
|
-
transport_instance = create_transport(transport, endpoint, session_store: store, session_id: session_id,
|
|
49
|
-
protocol_version: protocol_version, logger: logger, **options)
|
|
50
|
-
|
|
51
|
-
logger.info("Creating #{transport} client for endpoint: #{endpoint}")
|
|
52
|
-
# Pass session_id and protocol_version to the client
|
|
53
|
-
Client::Base.new(transport: transport_instance, logger: logger, session_id: session_id,
|
|
54
|
-
protocol_version: protocol_version, **options)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private_class_method def self.create_transport(type, endpoint, **options)
|
|
58
|
-
case type.to_sym
|
|
59
|
-
when :streamable_http
|
|
60
|
-
Client::StreamableHttpTransport.new(endpoint, **options)
|
|
61
|
-
when :sse
|
|
62
|
-
# Legacy SSE transport (wrapped for compatibility)
|
|
63
|
-
Client::StreamableClient.new(endpoint, **options)
|
|
64
|
-
else
|
|
65
|
-
raise ArgumentError, "Unknown transport type: #{type}"
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
module Client
|
|
70
|
-
end
|
|
71
|
-
end
|