ruby-mcp-client 1.0.1 → 2.0.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 +234 -7
- data/lib/mcp_client/auth/oauth_provider.rb +553 -50
- data/lib/mcp_client/auth.rb +47 -9
- data/lib/mcp_client/client.rb +613 -172
- data/lib/mcp_client/elicitation_validator.rb +43 -0
- data/lib/mcp_client/errors.rb +44 -1
- data/lib/mcp_client/http_transport_base.rb +232 -38
- data/lib/mcp_client/json_rpc_common.rb +140 -12
- data/lib/mcp_client/oauth_client.rb +8 -3
- data/lib/mcp_client/prompt.rb +17 -2
- data/lib/mcp_client/resource.rb +15 -2
- data/lib/mcp_client/resource_content.rb +8 -3
- data/lib/mcp_client/resource_link.rb +16 -3
- data/lib/mcp_client/resource_template.rb +15 -2
- data/lib/mcp_client/root.rb +61 -7
- data/lib/mcp_client/schema_validator.rb +285 -0
- data/lib/mcp_client/server_base.rb +139 -0
- data/lib/mcp_client/server_http/json_rpc_transport.rb +2 -1
- data/lib/mcp_client/server_http.rb +45 -29
- data/lib/mcp_client/server_sse/json_rpc_transport.rb +67 -9
- data/lib/mcp_client/server_sse/reconnect_monitor.rb +11 -0
- data/lib/mcp_client/server_sse/sse_parser.rb +51 -11
- data/lib/mcp_client/server_sse.rb +98 -57
- data/lib/mcp_client/server_stdio/json_rpc_transport.rb +42 -9
- data/lib/mcp_client/server_stdio.rb +216 -37
- data/lib/mcp_client/server_streamable_http/json_rpc_transport.rb +149 -23
- data/lib/mcp_client/server_streamable_http.rb +249 -107
- data/lib/mcp_client/task.rb +93 -61
- data/lib/mcp_client/tool.rb +63 -10
- data/lib/mcp_client/version.rb +6 -1
- data/lib/mcp_client.rb +1 -0
- metadata +19 -4
data/lib/mcp_client/auth.rb
CHANGED
|
@@ -225,7 +225,8 @@ module MCPClient
|
|
|
225
225
|
# OAuth authorization server metadata
|
|
226
226
|
class ServerMetadata
|
|
227
227
|
attr_reader :issuer, :authorization_endpoint, :token_endpoint, :registration_endpoint,
|
|
228
|
-
:scopes_supported, :response_types_supported, :grant_types_supported
|
|
228
|
+
:scopes_supported, :response_types_supported, :grant_types_supported,
|
|
229
|
+
:code_challenge_methods_supported, :client_id_metadata_document_supported
|
|
229
230
|
|
|
230
231
|
# @param issuer [String] Issuer identifier URL
|
|
231
232
|
# @param authorization_endpoint [String] Authorization endpoint URL
|
|
@@ -234,8 +235,14 @@ module MCPClient
|
|
|
234
235
|
# @param scopes_supported [Array<String>, nil] Supported OAuth scopes
|
|
235
236
|
# @param response_types_supported [Array<String>, nil] Supported response types
|
|
236
237
|
# @param grant_types_supported [Array<String>, nil] Supported grant types
|
|
238
|
+
# @param code_challenge_methods_supported [Array<String>, nil] Supported PKCE code challenge methods (RFC 8414)
|
|
239
|
+
# @param client_id_metadata_document_supported [Boolean, nil] Whether the server accepts
|
|
240
|
+
# Client ID Metadata Document client IDs (MCP 2025-11-25 / SEP-991)
|
|
241
|
+
# rubocop:disable Metrics/ParameterLists
|
|
237
242
|
def initialize(issuer:, authorization_endpoint:, token_endpoint:, registration_endpoint: nil,
|
|
238
|
-
scopes_supported: nil, response_types_supported: nil, grant_types_supported: nil
|
|
243
|
+
scopes_supported: nil, response_types_supported: nil, grant_types_supported: nil,
|
|
244
|
+
code_challenge_methods_supported: nil, client_id_metadata_document_supported: nil)
|
|
245
|
+
# rubocop:enable Metrics/ParameterLists
|
|
239
246
|
@issuer = issuer
|
|
240
247
|
@authorization_endpoint = authorization_endpoint
|
|
241
248
|
@token_endpoint = token_endpoint
|
|
@@ -243,6 +250,8 @@ module MCPClient
|
|
|
243
250
|
@scopes_supported = scopes_supported
|
|
244
251
|
@response_types_supported = response_types_supported
|
|
245
252
|
@grant_types_supported = grant_types_supported
|
|
253
|
+
@code_challenge_methods_supported = code_challenge_methods_supported
|
|
254
|
+
@client_id_metadata_document_supported = client_id_metadata_document_supported
|
|
246
255
|
end
|
|
247
256
|
|
|
248
257
|
# Check if dynamic client registration is supported
|
|
@@ -251,6 +260,13 @@ module MCPClient
|
|
|
251
260
|
!@registration_endpoint.nil?
|
|
252
261
|
end
|
|
253
262
|
|
|
263
|
+
# Check if the server accepts clients using Client ID Metadata Documents
|
|
264
|
+
# (MCP 2025-11-25 / SEP-991), i.e. HTTPS URLs as client identifiers
|
|
265
|
+
# @return [Boolean] true if client_id_metadata_document_supported is true
|
|
266
|
+
def supports_client_id_metadata_documents?
|
|
267
|
+
@client_id_metadata_document_supported == true
|
|
268
|
+
end
|
|
269
|
+
|
|
254
270
|
# Convert to hash
|
|
255
271
|
# @return [Hash] Hash representation
|
|
256
272
|
def to_h
|
|
@@ -261,7 +277,9 @@ module MCPClient
|
|
|
261
277
|
registration_endpoint: @registration_endpoint,
|
|
262
278
|
scopes_supported: @scopes_supported,
|
|
263
279
|
response_types_supported: @response_types_supported,
|
|
264
|
-
grant_types_supported: @grant_types_supported
|
|
280
|
+
grant_types_supported: @grant_types_supported,
|
|
281
|
+
code_challenge_methods_supported: @code_challenge_methods_supported,
|
|
282
|
+
client_id_metadata_document_supported: @client_id_metadata_document_supported
|
|
265
283
|
}.compact
|
|
266
284
|
end
|
|
267
285
|
|
|
@@ -276,20 +294,38 @@ module MCPClient
|
|
|
276
294
|
registration_endpoint: data[:registration_endpoint] || data['registration_endpoint'],
|
|
277
295
|
scopes_supported: data[:scopes_supported] || data['scopes_supported'],
|
|
278
296
|
response_types_supported: data[:response_types_supported] || data['response_types_supported'],
|
|
279
|
-
grant_types_supported: data[:grant_types_supported] || data['grant_types_supported']
|
|
297
|
+
grant_types_supported: data[:grant_types_supported] || data['grant_types_supported'],
|
|
298
|
+
code_challenge_methods_supported: data[:code_challenge_methods_supported] ||
|
|
299
|
+
data['code_challenge_methods_supported'],
|
|
300
|
+
client_id_metadata_document_supported: fetch_boolean(data, :client_id_metadata_document_supported)
|
|
280
301
|
)
|
|
281
302
|
end
|
|
303
|
+
|
|
304
|
+
# Fetch a possibly-false value from a hash by symbol or string key.
|
|
305
|
+
# Unlike the `||` chains above, this preserves an explicit false.
|
|
306
|
+
# @param data [Hash] Source hash
|
|
307
|
+
# @param key [Symbol] Key to fetch
|
|
308
|
+
# @return [Object, nil] The value, or nil when absent under both keys
|
|
309
|
+
def self.fetch_boolean(data, key)
|
|
310
|
+
return data[key] if data.key?(key)
|
|
311
|
+
|
|
312
|
+
data[key.to_s]
|
|
313
|
+
end
|
|
314
|
+
private_class_method :fetch_boolean
|
|
282
315
|
end
|
|
283
316
|
|
|
284
317
|
# Protected resource metadata for authorization server discovery
|
|
285
318
|
class ResourceMetadata
|
|
286
|
-
attr_reader :resource, :authorization_servers
|
|
319
|
+
attr_reader :resource, :authorization_servers, :scopes_supported
|
|
287
320
|
|
|
288
321
|
# @param resource [String] Resource server identifier
|
|
289
322
|
# @param authorization_servers [Array<String>] List of authorization server URLs
|
|
290
|
-
|
|
323
|
+
# @param scopes_supported [Array<String>, nil] Scopes the resource supports (RFC 9728);
|
|
324
|
+
# per MCP, the default scope set when a challenge provides none
|
|
325
|
+
def initialize(resource:, authorization_servers:, scopes_supported: nil)
|
|
291
326
|
@resource = resource
|
|
292
327
|
@authorization_servers = authorization_servers
|
|
328
|
+
@scopes_supported = scopes_supported
|
|
293
329
|
end
|
|
294
330
|
|
|
295
331
|
# Convert to hash
|
|
@@ -297,8 +333,9 @@ module MCPClient
|
|
|
297
333
|
def to_h
|
|
298
334
|
{
|
|
299
335
|
resource: @resource,
|
|
300
|
-
authorization_servers: @authorization_servers
|
|
301
|
-
|
|
336
|
+
authorization_servers: @authorization_servers,
|
|
337
|
+
scopes_supported: @scopes_supported
|
|
338
|
+
}.compact
|
|
302
339
|
end
|
|
303
340
|
|
|
304
341
|
# Create resource metadata from hash
|
|
@@ -307,7 +344,8 @@ module MCPClient
|
|
|
307
344
|
def self.from_h(data)
|
|
308
345
|
new(
|
|
309
346
|
resource: data[:resource] || data['resource'],
|
|
310
|
-
authorization_servers: data[:authorization_servers] || data['authorization_servers']
|
|
347
|
+
authorization_servers: data[:authorization_servers] || data['authorization_servers'],
|
|
348
|
+
scopes_supported: data[:scopes_supported] || data['scopes_supported']
|
|
311
349
|
)
|
|
312
350
|
end
|
|
313
351
|
end
|