ruby-mcp-client 0.6.2 → 0.7.1
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 +316 -10
- data/lib/mcp_client/auth/oauth_provider.rb +514 -0
- data/lib/mcp_client/auth.rb +315 -0
- data/lib/mcp_client/client.rb +1 -1
- data/lib/mcp_client/config_parser.rb +73 -1
- data/lib/mcp_client/http_transport_base.rb +283 -0
- data/lib/mcp_client/json_rpc_common.rb +8 -10
- data/lib/mcp_client/oauth_client.rb +127 -0
- data/lib/mcp_client/server_factory.rb +42 -0
- data/lib/mcp_client/server_http/json_rpc_transport.rb +27 -0
- data/lib/mcp_client/server_http.rb +331 -0
- data/lib/mcp_client/server_sse/json_rpc_transport.rb +5 -5
- data/lib/mcp_client/server_sse.rb +16 -8
- data/lib/mcp_client/server_stdio/json_rpc_transport.rb +1 -1
- data/lib/mcp_client/server_stdio.rb +1 -1
- data/lib/mcp_client/server_streamable_http/json_rpc_transport.rb +76 -0
- data/lib/mcp_client/server_streamable_http.rb +332 -0
- data/lib/mcp_client/tool.rb +4 -3
- data/lib/mcp_client/version.rb +4 -1
- data/lib/mcp_client.rb +61 -2
- metadata +10 -2
@@ -0,0 +1,332 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'monitor'
|
6
|
+
require 'logger'
|
7
|
+
require 'faraday'
|
8
|
+
require 'faraday/retry'
|
9
|
+
|
10
|
+
module MCPClient
|
11
|
+
# Implementation of MCP server that communicates via Streamable HTTP transport
|
12
|
+
# This transport uses HTTP POST requests but expects Server-Sent Event formatted responses
|
13
|
+
# It's designed for servers that support streaming responses over HTTP
|
14
|
+
class ServerStreamableHTTP < ServerBase
|
15
|
+
require_relative 'server_streamable_http/json_rpc_transport'
|
16
|
+
|
17
|
+
include JsonRpcTransport
|
18
|
+
|
19
|
+
# Default values for connection settings
|
20
|
+
DEFAULT_READ_TIMEOUT = 30
|
21
|
+
DEFAULT_MAX_RETRIES = 3
|
22
|
+
|
23
|
+
# @!attribute [r] base_url
|
24
|
+
# @return [String] The base URL of the MCP server
|
25
|
+
# @!attribute [r] endpoint
|
26
|
+
# @return [String] The JSON-RPC endpoint path
|
27
|
+
# @!attribute [r] tools
|
28
|
+
# @return [Array<MCPClient::Tool>, nil] List of available tools (nil if not fetched yet)
|
29
|
+
attr_reader :base_url, :endpoint, :tools
|
30
|
+
|
31
|
+
# Server information from initialize response
|
32
|
+
# @return [Hash, nil] Server information
|
33
|
+
attr_reader :server_info
|
34
|
+
|
35
|
+
# Server capabilities from initialize response
|
36
|
+
# @return [Hash, nil] Server capabilities
|
37
|
+
attr_reader :capabilities
|
38
|
+
|
39
|
+
# @param base_url [String] The base URL of the MCP server
|
40
|
+
# @param options [Hash] Server configuration options (same as ServerHTTP)
|
41
|
+
def initialize(base_url:, **options)
|
42
|
+
opts = default_options.merge(options)
|
43
|
+
super(name: opts[:name])
|
44
|
+
@logger = opts[:logger] || Logger.new($stdout, level: Logger::WARN)
|
45
|
+
@logger.progname = self.class.name
|
46
|
+
@logger.formatter = proc { |severity, _datetime, progname, msg| "#{severity} [#{progname}] #{msg}\n" }
|
47
|
+
|
48
|
+
@max_retries = opts[:retries]
|
49
|
+
@retry_backoff = opts[:retry_backoff]
|
50
|
+
|
51
|
+
# Validate and normalize base_url
|
52
|
+
raise ArgumentError, "Invalid or insecure server URL: #{base_url}" unless valid_server_url?(base_url)
|
53
|
+
|
54
|
+
# Normalize base_url and handle cases where full endpoint is provided in base_url
|
55
|
+
uri = URI.parse(base_url.chomp('/'))
|
56
|
+
|
57
|
+
# Helper to build base URL without default ports
|
58
|
+
build_base_url = lambda do |parsed_uri|
|
59
|
+
port_part = if parsed_uri.port &&
|
60
|
+
!((parsed_uri.scheme == 'http' && parsed_uri.port == 80) ||
|
61
|
+
(parsed_uri.scheme == 'https' && parsed_uri.port == 443))
|
62
|
+
":#{parsed_uri.port}"
|
63
|
+
else
|
64
|
+
''
|
65
|
+
end
|
66
|
+
"#{parsed_uri.scheme}://#{parsed_uri.host}#{port_part}"
|
67
|
+
end
|
68
|
+
|
69
|
+
@base_url = build_base_url.call(uri)
|
70
|
+
@endpoint = if uri.path && !uri.path.empty? && uri.path != '/' && opts[:endpoint] == '/rpc'
|
71
|
+
# If base_url contains a path and we're using default endpoint,
|
72
|
+
# treat the path as the endpoint and use the base URL without path
|
73
|
+
uri.path
|
74
|
+
else
|
75
|
+
# Standard case: base_url is just scheme://host:port, endpoint is separate
|
76
|
+
opts[:endpoint]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Set up headers for Streamable HTTP requests
|
80
|
+
@headers = opts[:headers].merge({
|
81
|
+
'Content-Type' => 'application/json',
|
82
|
+
'Accept' => 'text/event-stream, application/json',
|
83
|
+
'Accept-Encoding' => 'gzip, deflate',
|
84
|
+
'User-Agent' => "ruby-mcp-client/#{MCPClient::VERSION}",
|
85
|
+
'Cache-Control' => 'no-cache'
|
86
|
+
})
|
87
|
+
|
88
|
+
@read_timeout = opts[:read_timeout]
|
89
|
+
@tools = nil
|
90
|
+
@tools_data = nil
|
91
|
+
@request_id = 0
|
92
|
+
@mutex = Monitor.new
|
93
|
+
@connection_established = false
|
94
|
+
@initialized = false
|
95
|
+
@http_conn = nil
|
96
|
+
@session_id = nil
|
97
|
+
@last_event_id = nil
|
98
|
+
@oauth_provider = opts[:oauth_provider]
|
99
|
+
end
|
100
|
+
|
101
|
+
# Connect to the MCP server over Streamable HTTP
|
102
|
+
# @return [Boolean] true if connection was successful
|
103
|
+
# @raise [MCPClient::Errors::ConnectionError] if connection fails
|
104
|
+
def connect
|
105
|
+
return true if @mutex.synchronize { @connection_established }
|
106
|
+
|
107
|
+
begin
|
108
|
+
@mutex.synchronize do
|
109
|
+
@connection_established = false
|
110
|
+
@initialized = false
|
111
|
+
end
|
112
|
+
|
113
|
+
# Test connectivity with a simple HTTP request
|
114
|
+
test_connection
|
115
|
+
|
116
|
+
# Perform MCP initialization handshake
|
117
|
+
perform_initialize
|
118
|
+
|
119
|
+
@mutex.synchronize do
|
120
|
+
@connection_established = true
|
121
|
+
@initialized = true
|
122
|
+
end
|
123
|
+
|
124
|
+
true
|
125
|
+
rescue MCPClient::Errors::ConnectionError => e
|
126
|
+
cleanup
|
127
|
+
raise e
|
128
|
+
rescue StandardError => e
|
129
|
+
cleanup
|
130
|
+
raise MCPClient::Errors::ConnectionError, "Failed to connect to MCP server at #{@base_url}: #{e.message}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# List all tools available from the MCP server
|
135
|
+
# @return [Array<MCPClient::Tool>] list of available tools
|
136
|
+
# @raise [MCPClient::Errors::ServerError] if server returns an error
|
137
|
+
# @raise [MCPClient::Errors::TransportError] if response isn't valid JSON
|
138
|
+
# @raise [MCPClient::Errors::ToolCallError] for other errors during tool listing
|
139
|
+
def list_tools
|
140
|
+
@mutex.synchronize do
|
141
|
+
return @tools if @tools
|
142
|
+
end
|
143
|
+
|
144
|
+
begin
|
145
|
+
ensure_connected
|
146
|
+
|
147
|
+
tools_data = request_tools_list
|
148
|
+
@mutex.synchronize do
|
149
|
+
@tools = tools_data.map do |tool_data|
|
150
|
+
MCPClient::Tool.from_json(tool_data, server: self)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
@mutex.synchronize { @tools }
|
155
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError, MCPClient::Errors::ServerError
|
156
|
+
# Re-raise these errors directly
|
157
|
+
raise
|
158
|
+
rescue StandardError => e
|
159
|
+
raise MCPClient::Errors::ToolCallError, "Error listing tools: #{e.message}"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Call a tool with the given parameters
|
164
|
+
# @param tool_name [String] the name of the tool to call
|
165
|
+
# @param parameters [Hash] the parameters to pass to the tool
|
166
|
+
# @return [Object] the result of the tool invocation (with string keys for backward compatibility)
|
167
|
+
# @raise [MCPClient::Errors::ServerError] if server returns an error
|
168
|
+
# @raise [MCPClient::Errors::TransportError] if response isn't valid JSON
|
169
|
+
# @raise [MCPClient::Errors::ToolCallError] for other errors during tool execution
|
170
|
+
# @raise [MCPClient::Errors::ConnectionError] if server is disconnected
|
171
|
+
def call_tool(tool_name, parameters)
|
172
|
+
rpc_request('tools/call', {
|
173
|
+
name: tool_name,
|
174
|
+
arguments: parameters
|
175
|
+
})
|
176
|
+
rescue MCPClient::Errors::ConnectionError, MCPClient::Errors::TransportError
|
177
|
+
# Re-raise connection/transport errors directly to match test expectations
|
178
|
+
raise
|
179
|
+
rescue StandardError => e
|
180
|
+
# For all other errors, wrap in ToolCallError
|
181
|
+
raise MCPClient::Errors::ToolCallError, "Error calling tool '#{tool_name}': #{e.message}"
|
182
|
+
end
|
183
|
+
|
184
|
+
# Stream tool call (default implementation returns single-value stream)
|
185
|
+
# @param tool_name [String] the name of the tool to call
|
186
|
+
# @param parameters [Hash] the parameters to pass to the tool
|
187
|
+
# @return [Enumerator] stream of results
|
188
|
+
def call_tool_streaming(tool_name, parameters)
|
189
|
+
Enumerator.new do |yielder|
|
190
|
+
yielder << call_tool(tool_name, parameters)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
# Override apply_request_headers to add session and SSE headers for MCP protocol
|
195
|
+
def apply_request_headers(req, request)
|
196
|
+
super
|
197
|
+
|
198
|
+
# Add session header if we have one (for non-initialize requests)
|
199
|
+
if @session_id && request['method'] != 'initialize'
|
200
|
+
req.headers['Mcp-Session-Id'] = @session_id
|
201
|
+
@logger.debug("Adding session header: Mcp-Session-Id: #{@session_id}")
|
202
|
+
end
|
203
|
+
|
204
|
+
# Add Last-Event-ID header for resumability (if available)
|
205
|
+
return unless @last_event_id
|
206
|
+
|
207
|
+
req.headers['Last-Event-ID'] = @last_event_id
|
208
|
+
@logger.debug("Adding Last-Event-ID header: #{@last_event_id}")
|
209
|
+
end
|
210
|
+
|
211
|
+
# Override handle_successful_response to capture session ID
|
212
|
+
def handle_successful_response(response, request)
|
213
|
+
super
|
214
|
+
|
215
|
+
# Capture session ID from initialize response with validation
|
216
|
+
return unless request['method'] == 'initialize' && response.success?
|
217
|
+
|
218
|
+
session_id = response.headers['mcp-session-id'] || response.headers['Mcp-Session-Id']
|
219
|
+
if session_id
|
220
|
+
if valid_session_id?(session_id)
|
221
|
+
@session_id = session_id
|
222
|
+
@logger.debug("Captured session ID: #{@session_id}")
|
223
|
+
else
|
224
|
+
@logger.warn("Invalid session ID format received: #{session_id.inspect}")
|
225
|
+
end
|
226
|
+
else
|
227
|
+
@logger.warn('No session ID found in initialize response headers')
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
# Terminate the current session (if any)
|
232
|
+
# @return [Boolean] true if termination was successful or no session exists
|
233
|
+
def terminate_session
|
234
|
+
@mutex.synchronize do
|
235
|
+
return true unless @session_id
|
236
|
+
|
237
|
+
super
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Clean up the server connection
|
242
|
+
# Properly closes HTTP connections and clears cached state
|
243
|
+
def cleanup
|
244
|
+
@mutex.synchronize do
|
245
|
+
# Attempt to terminate session before cleanup
|
246
|
+
terminate_session if @session_id
|
247
|
+
|
248
|
+
@connection_established = false
|
249
|
+
@initialized = false
|
250
|
+
|
251
|
+
@logger.debug('Cleaning up Streamable HTTP connection')
|
252
|
+
|
253
|
+
# Close HTTP connection if it exists
|
254
|
+
@http_conn = nil
|
255
|
+
@session_id = nil
|
256
|
+
|
257
|
+
@tools = nil
|
258
|
+
@tools_data = nil
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
private
|
263
|
+
|
264
|
+
# Default options for server initialization
|
265
|
+
# @return [Hash] Default options
|
266
|
+
def default_options
|
267
|
+
{
|
268
|
+
endpoint: '/rpc',
|
269
|
+
headers: {},
|
270
|
+
read_timeout: DEFAULT_READ_TIMEOUT,
|
271
|
+
retries: DEFAULT_MAX_RETRIES,
|
272
|
+
retry_backoff: 1,
|
273
|
+
name: nil,
|
274
|
+
logger: nil,
|
275
|
+
oauth_provider: nil
|
276
|
+
}
|
277
|
+
end
|
278
|
+
|
279
|
+
# Test basic connectivity to the HTTP endpoint
|
280
|
+
# @return [void]
|
281
|
+
# @raise [MCPClient::Errors::ConnectionError] if connection test fails
|
282
|
+
def test_connection
|
283
|
+
create_http_connection
|
284
|
+
|
285
|
+
# Simple connectivity test - we'll use the actual initialize call
|
286
|
+
# since there's no standard HTTP health check endpoint
|
287
|
+
rescue Faraday::ConnectionFailed => e
|
288
|
+
raise MCPClient::Errors::ConnectionError, "Cannot connect to server at #{@base_url}: #{e.message}"
|
289
|
+
rescue Faraday::UnauthorizedError, Faraday::ForbiddenError => e
|
290
|
+
error_status = e.response ? e.response[:status] : 'unknown'
|
291
|
+
raise MCPClient::Errors::ConnectionError, "Authorization failed: HTTP #{error_status}"
|
292
|
+
rescue Faraday::Error => e
|
293
|
+
raise MCPClient::Errors::ConnectionError, "HTTP connection error: #{e.message}"
|
294
|
+
end
|
295
|
+
|
296
|
+
# Ensure connection is established
|
297
|
+
# @return [void]
|
298
|
+
# @raise [MCPClient::Errors::ConnectionError] if connection is not established
|
299
|
+
def ensure_connected
|
300
|
+
return if @mutex.synchronize { @connection_established && @initialized }
|
301
|
+
|
302
|
+
@logger.debug('Connection not active, attempting to reconnect before request')
|
303
|
+
cleanup
|
304
|
+
connect
|
305
|
+
end
|
306
|
+
|
307
|
+
# Request the tools list using JSON-RPC
|
308
|
+
# @return [Array<Hash>] the tools data
|
309
|
+
# @raise [MCPClient::Errors::ToolCallError] if tools list retrieval fails
|
310
|
+
def request_tools_list
|
311
|
+
@mutex.synchronize do
|
312
|
+
return @tools_data if @tools_data
|
313
|
+
end
|
314
|
+
|
315
|
+
result = rpc_request('tools/list')
|
316
|
+
|
317
|
+
if result.is_a?(Hash) && result['tools']
|
318
|
+
@mutex.synchronize do
|
319
|
+
@tools_data = result['tools']
|
320
|
+
end
|
321
|
+
return @mutex.synchronize { @tools_data.dup }
|
322
|
+
elsif result.is_a?(Array) || result
|
323
|
+
@mutex.synchronize do
|
324
|
+
@tools_data = result
|
325
|
+
end
|
326
|
+
return @mutex.synchronize { @tools_data.dup }
|
327
|
+
end
|
328
|
+
|
329
|
+
raise MCPClient::Errors::ToolCallError, 'Failed to get tools list from JSON-RPC request'
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
data/lib/mcp_client/tool.rb
CHANGED
@@ -31,10 +31,11 @@ module MCPClient
|
|
31
31
|
# @return [MCPClient::Tool] tool instance
|
32
32
|
def self.from_json(data, server: nil)
|
33
33
|
# Some servers (Playwright MCP CLI) use 'inputSchema' instead of 'schema'
|
34
|
-
|
34
|
+
# Handle both string and symbol keys
|
35
|
+
schema = data['inputSchema'] || data[:inputSchema] || data['schema'] || data[:schema]
|
35
36
|
new(
|
36
|
-
name: data['name'],
|
37
|
-
description: data['description'],
|
37
|
+
name: data['name'] || data[:name],
|
38
|
+
description: data['description'] || data[:description],
|
38
39
|
schema: schema,
|
39
40
|
server: server
|
40
41
|
)
|
data/lib/mcp_client/version.rb
CHANGED
@@ -2,8 +2,11 @@
|
|
2
2
|
|
3
3
|
module MCPClient
|
4
4
|
# Current version of the MCP client gem
|
5
|
-
VERSION = '0.
|
5
|
+
VERSION = '0.7.1'
|
6
6
|
|
7
7
|
# JSON-RPC handshake protocol version (date-based)
|
8
8
|
PROTOCOL_VERSION = '2024-11-05'
|
9
|
+
|
10
|
+
# Protocol version for HTTP and Streamable HTTP transports
|
11
|
+
HTTP_PROTOCOL_VERSION = '2025-03-26'
|
9
12
|
end
|
data/lib/mcp_client.rb
CHANGED
@@ -6,10 +6,14 @@ require_relative 'mcp_client/tool'
|
|
6
6
|
require_relative 'mcp_client/server_base'
|
7
7
|
require_relative 'mcp_client/server_stdio'
|
8
8
|
require_relative 'mcp_client/server_sse'
|
9
|
+
require_relative 'mcp_client/server_http'
|
10
|
+
require_relative 'mcp_client/server_streamable_http'
|
9
11
|
require_relative 'mcp_client/server_factory'
|
10
12
|
require_relative 'mcp_client/client'
|
11
13
|
require_relative 'mcp_client/version'
|
12
14
|
require_relative 'mcp_client/config_parser'
|
15
|
+
require_relative 'mcp_client/auth'
|
16
|
+
require_relative 'mcp_client/oauth_client'
|
13
17
|
|
14
18
|
# Model Context Protocol (MCP) Client module
|
15
19
|
# Provides a standardized way for agents to communicate with external tools and services
|
@@ -33,7 +37,6 @@ module MCPClient
|
|
33
37
|
parsed.each_value do |cfg|
|
34
38
|
case cfg[:type].to_s
|
35
39
|
when 'stdio'
|
36
|
-
# Build command list with args and propagate environment
|
37
40
|
cmd_list = [cfg[:command]] + Array(cfg[:args])
|
38
41
|
configs << MCPClient.stdio_config(
|
39
42
|
command: cmd_list,
|
@@ -42,9 +45,14 @@ module MCPClient
|
|
42
45
|
env: cfg[:env]
|
43
46
|
)
|
44
47
|
when 'sse'
|
45
|
-
# Use 'url' from parsed config as 'base_url' for SSE config
|
46
48
|
configs << MCPClient.sse_config(base_url: cfg[:url], headers: cfg[:headers] || {}, name: cfg[:name],
|
47
49
|
logger: logger)
|
50
|
+
when 'http'
|
51
|
+
configs << MCPClient.http_config(base_url: cfg[:url], endpoint: cfg[:endpoint],
|
52
|
+
headers: cfg[:headers] || {}, name: cfg[:name], logger: logger)
|
53
|
+
when 'streamable_http'
|
54
|
+
configs << MCPClient.streamable_http_config(base_url: cfg[:url], endpoint: cfg[:endpoint],
|
55
|
+
headers: cfg[:headers] || {}, name: cfg[:name], logger: logger)
|
48
56
|
end
|
49
57
|
end
|
50
58
|
end
|
@@ -90,4 +98,55 @@ module MCPClient
|
|
90
98
|
logger: logger
|
91
99
|
}
|
92
100
|
end
|
101
|
+
|
102
|
+
# Create a standard server configuration for HTTP
|
103
|
+
# @param base_url [String] base URL for the server
|
104
|
+
# @param endpoint [String] JSON-RPC endpoint path (default: '/rpc')
|
105
|
+
# @param headers [Hash] HTTP headers to include in requests
|
106
|
+
# @param read_timeout [Integer] read timeout in seconds (default: 30)
|
107
|
+
# @param retries [Integer] number of retry attempts (default: 3)
|
108
|
+
# @param retry_backoff [Integer] backoff delay in seconds (default: 1)
|
109
|
+
# @param name [String, nil] optional name for this server
|
110
|
+
# @param logger [Logger, nil] optional logger for server operations
|
111
|
+
# @return [Hash] server configuration
|
112
|
+
def self.http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3, retry_backoff: 1,
|
113
|
+
name: nil, logger: nil)
|
114
|
+
{
|
115
|
+
type: 'http',
|
116
|
+
base_url: base_url,
|
117
|
+
endpoint: endpoint,
|
118
|
+
headers: headers,
|
119
|
+
read_timeout: read_timeout,
|
120
|
+
retries: retries,
|
121
|
+
retry_backoff: retry_backoff,
|
122
|
+
name: name,
|
123
|
+
logger: logger
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
# Create configuration for Streamable HTTP transport
|
128
|
+
# This transport uses HTTP POST requests but expects Server-Sent Event formatted responses
|
129
|
+
# @param base_url [String] Base URL of the MCP server
|
130
|
+
# @param endpoint [String] JSON-RPC endpoint path (default: '/rpc')
|
131
|
+
# @param headers [Hash] Additional headers to include in requests
|
132
|
+
# @param read_timeout [Integer] Read timeout in seconds (default: 30)
|
133
|
+
# @param retries [Integer] Number of retry attempts on transient errors (default: 3)
|
134
|
+
# @param retry_backoff [Integer] Backoff delay in seconds (default: 1)
|
135
|
+
# @param name [String, nil] Optional name for this server
|
136
|
+
# @param logger [Logger, nil] Optional logger for server operations
|
137
|
+
# @return [Hash] server configuration
|
138
|
+
def self.streamable_http_config(base_url:, endpoint: '/rpc', headers: {}, read_timeout: 30, retries: 3,
|
139
|
+
retry_backoff: 1, name: nil, logger: nil)
|
140
|
+
{
|
141
|
+
type: 'streamable_http',
|
142
|
+
base_url: base_url,
|
143
|
+
endpoint: endpoint,
|
144
|
+
headers: headers,
|
145
|
+
read_timeout: read_timeout,
|
146
|
+
retries: retries,
|
147
|
+
retry_backoff: retry_backoff,
|
148
|
+
name: name,
|
149
|
+
logger: logger
|
150
|
+
}
|
151
|
+
end
|
93
152
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-mcp-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Szymon Kurcab
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -105,18 +105,26 @@ files:
|
|
105
105
|
- LICENSE
|
106
106
|
- README.md
|
107
107
|
- lib/mcp_client.rb
|
108
|
+
- lib/mcp_client/auth.rb
|
109
|
+
- lib/mcp_client/auth/oauth_provider.rb
|
108
110
|
- lib/mcp_client/client.rb
|
109
111
|
- lib/mcp_client/config_parser.rb
|
110
112
|
- lib/mcp_client/errors.rb
|
113
|
+
- lib/mcp_client/http_transport_base.rb
|
111
114
|
- lib/mcp_client/json_rpc_common.rb
|
115
|
+
- lib/mcp_client/oauth_client.rb
|
112
116
|
- lib/mcp_client/server_base.rb
|
113
117
|
- lib/mcp_client/server_factory.rb
|
118
|
+
- lib/mcp_client/server_http.rb
|
119
|
+
- lib/mcp_client/server_http/json_rpc_transport.rb
|
114
120
|
- lib/mcp_client/server_sse.rb
|
115
121
|
- lib/mcp_client/server_sse/json_rpc_transport.rb
|
116
122
|
- lib/mcp_client/server_sse/reconnect_monitor.rb
|
117
123
|
- lib/mcp_client/server_sse/sse_parser.rb
|
118
124
|
- lib/mcp_client/server_stdio.rb
|
119
125
|
- lib/mcp_client/server_stdio/json_rpc_transport.rb
|
126
|
+
- lib/mcp_client/server_streamable_http.rb
|
127
|
+
- lib/mcp_client/server_streamable_http/json_rpc_transport.rb
|
120
128
|
- lib/mcp_client/tool.rb
|
121
129
|
- lib/mcp_client/version.rb
|
122
130
|
homepage: https://github.com/simonx1/ruby-mcp-client
|