ruby-mcp-client 1.1.0 → 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 +121 -3
- data/lib/mcp_client/auth/oauth_provider.rb +236 -26
- data/lib/mcp_client/auth.rb +40 -9
- data/lib/mcp_client/client.rb +417 -139
- data/lib/mcp_client/elicitation_validator.rb +43 -0
- data/lib/mcp_client/errors.rb +35 -1
- data/lib/mcp_client/http_transport_base.rb +227 -37
- data/lib/mcp_client/json_rpc_common.rb +126 -13
- 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 +66 -0
- data/lib/mcp_client/server_http/json_rpc_transport.rb +2 -1
- data/lib/mcp_client/server_http.rb +18 -12
- data/lib/mcp_client/server_sse/json_rpc_transport.rb +63 -8
- data/lib/mcp_client/server_sse/reconnect_monitor.rb +10 -3
- data/lib/mcp_client/server_sse/sse_parser.rb +46 -9
- data/lib/mcp_client/server_sse.rb +49 -21
- data/lib/mcp_client/server_stdio/json_rpc_transport.rb +29 -6
- data/lib/mcp_client/server_stdio.rb +92 -17
- data/lib/mcp_client/server_streamable_http/json_rpc_transport.rb +149 -23
- data/lib/mcp_client/server_streamable_http.rb +238 -77
- data/lib/mcp_client/tool.rb +18 -3
- data/lib/mcp_client/version.rb +6 -1
- data/lib/mcp_client.rb +1 -0
- metadata +3 -2
data/lib/mcp_client/auth.rb
CHANGED
|
@@ -226,7 +226,7 @@ module MCPClient
|
|
|
226
226
|
class ServerMetadata
|
|
227
227
|
attr_reader :issuer, :authorization_endpoint, :token_endpoint, :registration_endpoint,
|
|
228
228
|
:scopes_supported, :response_types_supported, :grant_types_supported,
|
|
229
|
-
:code_challenge_methods_supported
|
|
229
|
+
:code_challenge_methods_supported, :client_id_metadata_document_supported
|
|
230
230
|
|
|
231
231
|
# @param issuer [String] Issuer identifier URL
|
|
232
232
|
# @param authorization_endpoint [String] Authorization endpoint URL
|
|
@@ -236,9 +236,13 @@ module MCPClient
|
|
|
236
236
|
# @param response_types_supported [Array<String>, nil] Supported response types
|
|
237
237
|
# @param grant_types_supported [Array<String>, nil] Supported grant types
|
|
238
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
|
|
239
242
|
def initialize(issuer:, authorization_endpoint:, token_endpoint:, registration_endpoint: nil,
|
|
240
243
|
scopes_supported: nil, response_types_supported: nil, grant_types_supported: nil,
|
|
241
|
-
code_challenge_methods_supported: nil)
|
|
244
|
+
code_challenge_methods_supported: nil, client_id_metadata_document_supported: nil)
|
|
245
|
+
# rubocop:enable Metrics/ParameterLists
|
|
242
246
|
@issuer = issuer
|
|
243
247
|
@authorization_endpoint = authorization_endpoint
|
|
244
248
|
@token_endpoint = token_endpoint
|
|
@@ -247,6 +251,7 @@ module MCPClient
|
|
|
247
251
|
@response_types_supported = response_types_supported
|
|
248
252
|
@grant_types_supported = grant_types_supported
|
|
249
253
|
@code_challenge_methods_supported = code_challenge_methods_supported
|
|
254
|
+
@client_id_metadata_document_supported = client_id_metadata_document_supported
|
|
250
255
|
end
|
|
251
256
|
|
|
252
257
|
# Check if dynamic client registration is supported
|
|
@@ -255,6 +260,13 @@ module MCPClient
|
|
|
255
260
|
!@registration_endpoint.nil?
|
|
256
261
|
end
|
|
257
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
|
+
|
|
258
270
|
# Convert to hash
|
|
259
271
|
# @return [Hash] Hash representation
|
|
260
272
|
def to_h
|
|
@@ -266,7 +278,8 @@ module MCPClient
|
|
|
266
278
|
scopes_supported: @scopes_supported,
|
|
267
279
|
response_types_supported: @response_types_supported,
|
|
268
280
|
grant_types_supported: @grant_types_supported,
|
|
269
|
-
code_challenge_methods_supported: @code_challenge_methods_supported
|
|
281
|
+
code_challenge_methods_supported: @code_challenge_methods_supported,
|
|
282
|
+
client_id_metadata_document_supported: @client_id_metadata_document_supported
|
|
270
283
|
}.compact
|
|
271
284
|
end
|
|
272
285
|
|
|
@@ -283,20 +296,36 @@ module MCPClient
|
|
|
283
296
|
response_types_supported: data[:response_types_supported] || data['response_types_supported'],
|
|
284
297
|
grant_types_supported: data[:grant_types_supported] || data['grant_types_supported'],
|
|
285
298
|
code_challenge_methods_supported: data[:code_challenge_methods_supported] ||
|
|
286
|
-
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)
|
|
287
301
|
)
|
|
288
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
|
|
289
315
|
end
|
|
290
316
|
|
|
291
317
|
# Protected resource metadata for authorization server discovery
|
|
292
318
|
class ResourceMetadata
|
|
293
|
-
attr_reader :resource, :authorization_servers
|
|
319
|
+
attr_reader :resource, :authorization_servers, :scopes_supported
|
|
294
320
|
|
|
295
321
|
# @param resource [String] Resource server identifier
|
|
296
322
|
# @param authorization_servers [Array<String>] List of authorization server URLs
|
|
297
|
-
|
|
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)
|
|
298
326
|
@resource = resource
|
|
299
327
|
@authorization_servers = authorization_servers
|
|
328
|
+
@scopes_supported = scopes_supported
|
|
300
329
|
end
|
|
301
330
|
|
|
302
331
|
# Convert to hash
|
|
@@ -304,8 +333,9 @@ module MCPClient
|
|
|
304
333
|
def to_h
|
|
305
334
|
{
|
|
306
335
|
resource: @resource,
|
|
307
|
-
authorization_servers: @authorization_servers
|
|
308
|
-
|
|
336
|
+
authorization_servers: @authorization_servers,
|
|
337
|
+
scopes_supported: @scopes_supported
|
|
338
|
+
}.compact
|
|
309
339
|
end
|
|
310
340
|
|
|
311
341
|
# Create resource metadata from hash
|
|
@@ -314,7 +344,8 @@ module MCPClient
|
|
|
314
344
|
def self.from_h(data)
|
|
315
345
|
new(
|
|
316
346
|
resource: data[:resource] || data['resource'],
|
|
317
|
-
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']
|
|
318
349
|
)
|
|
319
350
|
end
|
|
320
351
|
end
|