mcp 1.0.0 → 1.2.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 +428 -9
- data/lib/json_rpc_handler.rb +3 -2
- data/lib/mcp/client/http.rb +338 -63
- data/lib/mcp/client/mcp_param_headers.rb +242 -0
- data/lib/mcp/client/modern_envelope.rb +32 -0
- data/lib/mcp/client/oauth/discovery.rb +108 -14
- data/lib/mcp/client/oauth/flow.rb +95 -7
- data/lib/mcp/client/stdio.rb +243 -66
- data/lib/mcp/client/tool.rb +3 -2
- data/lib/mcp/client.rb +364 -41
- data/lib/mcp/configuration.rb +84 -7
- data/lib/mcp/elicitation/enum_schema.rb +121 -0
- data/lib/mcp/elicitation.rb +10 -0
- data/lib/mcp/error_codes.rb +14 -8
- data/lib/mcp/instrumentation.rb +6 -0
- data/lib/mcp/methods.rb +21 -0
- data/lib/mcp/prompt.rb +8 -1
- data/lib/mcp/protocol_deprecations.rb +61 -0
- data/lib/mcp/request_envelope.rb +117 -0
- data/lib/mcp/server/input_required_result.rb +163 -0
- data/lib/mcp/server/pending_response.rb +62 -0
- data/lib/mcp/server/request_state_security.rb +131 -0
- data/lib/mcp/server/transports/stdio_transport.rb +39 -2
- data/lib/mcp/server/transports/streamable_http_transport.rb +710 -20
- data/lib/mcp/server.rb +541 -43
- data/lib/mcp/server_context.rb +92 -5
- data/lib/mcp/server_session.rb +77 -15
- data/lib/mcp/tool/response.rb +8 -2
- data/lib/mcp/transport.rb +7 -0
- data/lib/mcp/version.rb +1 -1
- data/lib/mcp.rb +3 -0
- metadata +11 -2
data/lib/mcp/server_context.rb
CHANGED
|
@@ -4,12 +4,35 @@ module MCP
|
|
|
4
4
|
class ServerContext
|
|
5
5
|
attr_reader :cancellation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# The SEP-2575 per-request envelope (`MCP::RequestEnvelope`) when the request was classified as modern;
|
|
8
|
+
# `nil` on legacy requests.
|
|
9
|
+
attr_reader :envelope
|
|
10
|
+
|
|
11
|
+
# SEP-2322 multi round-trip retry fields, present when the client re-issued the request after
|
|
12
|
+
# an `input_required` result: `input_responses` maps the keys of the earlier `inputRequests` to
|
|
13
|
+
# the client's answers, and `request_state` is the opaque continuation string echoed back byte-exactly.
|
|
14
|
+
# Both are `nil` on a first-round request. Only handlers that opt in to `server_context:` can read them
|
|
15
|
+
# (the same access model as the envelope readers).
|
|
16
|
+
attr_reader :input_responses, :request_state
|
|
17
|
+
|
|
18
|
+
def initialize(context, progress:, notification_target:, related_request_id: nil, cancellation: nil, envelope: nil,
|
|
19
|
+
input_responses: nil, request_state: nil)
|
|
8
20
|
@context = context
|
|
9
21
|
@progress = progress
|
|
10
22
|
@notification_target = notification_target
|
|
11
23
|
@related_request_id = related_request_id
|
|
12
24
|
@cancellation = cancellation
|
|
25
|
+
@envelope = envelope
|
|
26
|
+
@input_responses = input_responses
|
|
27
|
+
@request_state = request_state
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Reads one entry of {#input_responses} by its `inputRequests` key, tolerating symbol or string keys.
|
|
31
|
+
def input_response(key)
|
|
32
|
+
return unless @input_responses.is_a?(Hash)
|
|
33
|
+
|
|
34
|
+
value = @input_responses[key.to_sym]
|
|
35
|
+
value.nil? ? @input_responses[key.to_s] : value
|
|
13
36
|
end
|
|
14
37
|
|
|
15
38
|
def cancelled?
|
|
@@ -20,6 +43,52 @@ module MCP
|
|
|
20
43
|
@cancellation&.raise_if_cancelled!
|
|
21
44
|
end
|
|
22
45
|
|
|
46
|
+
# Whether the current request follows the stateless modern lifecycle (SEP-2575).
|
|
47
|
+
def modern?
|
|
48
|
+
!@envelope.nil?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Client identity for the current request. Modern requests carry it in the `_meta` envelope;
|
|
52
|
+
# legacy sessions fall back to the state stored by `initialize`. The envelope always wins
|
|
53
|
+
# because servers MUST NOT infer identity from prior requests.
|
|
54
|
+
def client_info
|
|
55
|
+
return @envelope.client_info if @envelope
|
|
56
|
+
|
|
57
|
+
@notification_target.client if @notification_target.respond_to?(:client)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Client capabilities for the current request, with the same envelope-first resolution as {#client_info}.
|
|
61
|
+
def client_capabilities
|
|
62
|
+
return @envelope.client_capabilities if @envelope
|
|
63
|
+
|
|
64
|
+
@notification_target.client_capabilities if @notification_target.respond_to?(:client_capabilities)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# The protocol version the current request was made with. `nil` on legacy requests,
|
|
68
|
+
# where the version is a session-level negotiation result rather than per-request data.
|
|
69
|
+
def protocol_version
|
|
70
|
+
@envelope&.protocol_version
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Guards the current request on a declared client capability (SEP-2575). `path` names nested capability keys,
|
|
74
|
+
# e.g. `require_client_capability!(:elicitation, :form)`. Raises `Server::MissingRequiredClientCapabilityError`
|
|
75
|
+
# (JSON-RPC error `-32021` with `data: { requiredCapabilities: ... }`) when the capability was not declared.
|
|
76
|
+
def require_client_capability!(*path)
|
|
77
|
+
raise ArgumentError, "at least one capability key is required" if path.empty?
|
|
78
|
+
|
|
79
|
+
declared = client_capabilities
|
|
80
|
+
value = path.reduce(declared) do |acc, key|
|
|
81
|
+
break unless acc.is_a?(Hash)
|
|
82
|
+
|
|
83
|
+
symbol_value = acc[key.to_sym]
|
|
84
|
+
symbol_value.nil? ? acc[key.to_s] : symbol_value
|
|
85
|
+
end
|
|
86
|
+
return unless value.nil?
|
|
87
|
+
|
|
88
|
+
required = path.reverse.inject({}) { |acc, key| { key.to_sym => acc } }
|
|
89
|
+
raise Server::MissingRequiredClientCapabilityError, required
|
|
90
|
+
end
|
|
91
|
+
|
|
23
92
|
# Reports progress for the current tool operation.
|
|
24
93
|
# The notification is automatically scoped to the originating session.
|
|
25
94
|
#
|
|
@@ -41,6 +110,14 @@ module MCP
|
|
|
41
110
|
def notify_log_message(data:, level:, logger: nil)
|
|
42
111
|
return unless @notification_target
|
|
43
112
|
|
|
113
|
+
# Modern requests opt in to logging per request (SEP-2575): without `io.modelcontextprotocol/logLevel` in `_meta`,
|
|
114
|
+
# the server MUST NOT send any `notifications/message` for the request, and an insufficient level drops
|
|
115
|
+
# the message the same way. Session- or server-level gating still applies downstream on delegation.
|
|
116
|
+
if @envelope
|
|
117
|
+
threshold = @envelope.log_level && LoggingMessageNotification.new(level: @envelope.log_level)
|
|
118
|
+
return unless threshold&.valid_level? && threshold.should_notify?(level)
|
|
119
|
+
end
|
|
120
|
+
|
|
44
121
|
@notification_target.notify_log_message(data: data, level: level, logger: logger, related_request_id: @related_request_id)
|
|
45
122
|
end
|
|
46
123
|
|
|
@@ -61,9 +138,9 @@ module MCP
|
|
|
61
138
|
# `notifications/roots/list_changed`) is deprecated as of MCP protocol
|
|
62
139
|
# version 2026-07-28 (SEP-2577). Use tool parameters, resource URIs,
|
|
63
140
|
# server configuration, or environment variables instead.
|
|
64
|
-
def list_roots
|
|
141
|
+
def list_roots(timeout: nil)
|
|
65
142
|
if @notification_target.respond_to?(:list_roots)
|
|
66
|
-
@notification_target.list_roots(related_request_id: @related_request_id)
|
|
143
|
+
@notification_target.list_roots(related_request_id: @related_request_id, **timeout_kwarg(timeout))
|
|
67
144
|
else
|
|
68
145
|
raise NoMethodError, "undefined method 'list_roots' for #{self}"
|
|
69
146
|
end
|
|
@@ -83,9 +160,9 @@ module MCP
|
|
|
83
160
|
# end
|
|
84
161
|
#
|
|
85
162
|
# @see https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/ping
|
|
86
|
-
def ping
|
|
163
|
+
def ping(timeout: nil)
|
|
87
164
|
if @notification_target.respond_to?(:ping)
|
|
88
|
-
@notification_target.ping(related_request_id: @related_request_id)
|
|
165
|
+
@notification_target.ping(related_request_id: @related_request_id, **timeout_kwarg(timeout))
|
|
89
166
|
else
|
|
90
167
|
raise NoMethodError, "undefined method 'ping' for #{self}"
|
|
91
168
|
end
|
|
@@ -168,5 +245,15 @@ module MCP
|
|
|
168
245
|
def respond_to_missing?(name, include_private = false)
|
|
169
246
|
@context.respond_to?(name) || super
|
|
170
247
|
end
|
|
248
|
+
|
|
249
|
+
private
|
|
250
|
+
|
|
251
|
+
# An omitted `timeout:` is not forwarded at all, so the delegated call keeps the shape it had
|
|
252
|
+
# before per-request timeouts existed. A notification target that predates the keyword
|
|
253
|
+
# (a custom object standing in for a session) keeps working until a caller actually asks for a timeout,
|
|
254
|
+
# and the transport applies its own default in that case.
|
|
255
|
+
def timeout_kwarg(timeout)
|
|
256
|
+
timeout.nil? ? {} : { timeout: timeout }
|
|
257
|
+
end
|
|
171
258
|
end
|
|
172
259
|
end
|
data/lib/mcp/server_session.rb
CHANGED
|
@@ -7,15 +7,26 @@ module MCP
|
|
|
7
7
|
# Holds per-connection state for a single client session.
|
|
8
8
|
# Created by the transport layer; delegates request handling to the shared `Server`.
|
|
9
9
|
class ServerSession
|
|
10
|
-
|
|
10
|
+
ERAS = [:legacy, :modern].freeze
|
|
11
|
+
|
|
12
|
+
attr_reader :session_id, :client, :logging_message_notification, :protocol_version
|
|
13
|
+
|
|
14
|
+
# Connection-era lock of the dual-era serving model (SEP-2575): `nil` until the first era-distinctive message succeeds,
|
|
15
|
+
# then `:legacy` or `:modern` for the connection's lifetime. Modern-era transports construct their per-request sessions
|
|
16
|
+
# with `era: :modern` up front.
|
|
17
|
+
attr_reader :era
|
|
18
|
+
|
|
19
|
+
def initialize(server:, transport:, session_id: nil, era: nil)
|
|
20
|
+
validate_era!(era) if era
|
|
11
21
|
|
|
12
|
-
def initialize(server:, transport:, session_id: nil)
|
|
13
22
|
@server = server
|
|
14
23
|
@transport = transport
|
|
15
24
|
@session_id = session_id
|
|
25
|
+
@era = era
|
|
16
26
|
@client = nil
|
|
17
27
|
@client_capabilities = nil
|
|
18
28
|
@logging_message_notification = nil
|
|
29
|
+
@protocol_version = nil
|
|
19
30
|
@in_flight = {}
|
|
20
31
|
@in_flight_mutex = Mutex.new
|
|
21
32
|
@initialized = false
|
|
@@ -29,8 +40,22 @@ module MCP
|
|
|
29
40
|
# Called by `Server#init` after a successful `initialize` response, so subsequent
|
|
30
41
|
# `initialize` requests on the same session can be rejected per MCP spec
|
|
31
42
|
# (the initialization phase MUST be the first interaction).
|
|
32
|
-
def mark_initialized!
|
|
43
|
+
def mark_initialized!(protocol_version: nil)
|
|
33
44
|
@initialized = true
|
|
45
|
+
@protocol_version = protocol_version
|
|
46
|
+
# A successful `initialize` is the legacy-distinctive message of the dual-era serving model (SEP-2575),
|
|
47
|
+
# so it also locks the connection era.
|
|
48
|
+
@era ||= :legacy
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# One-shot era lock. Locking the already-locked era is a no-op; flipping an established era raises,
|
|
52
|
+
# because a connection can never change eras.
|
|
53
|
+
def lock_era!(era)
|
|
54
|
+
validate_era!(era)
|
|
55
|
+
return if @era == era
|
|
56
|
+
raise "Session era already locked to #{@era}" if @era
|
|
57
|
+
|
|
58
|
+
@era = era
|
|
34
59
|
end
|
|
35
60
|
|
|
36
61
|
# Registers a `Cancellation` token for an in-flight request.
|
|
@@ -106,19 +131,19 @@ module MCP
|
|
|
106
131
|
# `notifications/roots/list_changed`) is deprecated as of MCP protocol
|
|
107
132
|
# version 2026-07-28 (SEP-2577). Use tool parameters, resource URIs,
|
|
108
133
|
# server configuration, or environment variables instead.
|
|
109
|
-
def list_roots(related_request_id: nil)
|
|
134
|
+
def list_roots(related_request_id: nil, timeout: nil)
|
|
110
135
|
warn_unassociated_request(__method__, related_request_id)
|
|
111
136
|
|
|
112
137
|
unless client_capabilities&.dig(:roots)
|
|
113
138
|
raise "Client does not support roots."
|
|
114
139
|
end
|
|
115
140
|
|
|
116
|
-
send_to_transport_request(Methods::ROOTS_LIST, nil, related_request_id: related_request_id)
|
|
141
|
+
send_to_transport_request(Methods::ROOTS_LIST, nil, related_request_id: related_request_id, timeout: timeout)
|
|
117
142
|
end
|
|
118
143
|
|
|
119
144
|
# Sends a `ping` request scoped to this session.
|
|
120
|
-
def ping(related_request_id: nil)
|
|
121
|
-
result = send_to_transport_request(Methods::PING, nil, related_request_id: related_request_id)
|
|
145
|
+
def ping(related_request_id: nil, timeout: nil)
|
|
146
|
+
result = send_to_transport_request(Methods::PING, nil, related_request_id: related_request_id, timeout: timeout)
|
|
122
147
|
raise Server::ValidationError, "Response validation failed: invalid `result`" unless result.is_a?(Hash)
|
|
123
148
|
|
|
124
149
|
result
|
|
@@ -132,11 +157,16 @@ module MCP
|
|
|
132
157
|
# @deprecated MCP Sampling (`sampling/createMessage`) is deprecated as of
|
|
133
158
|
# MCP protocol version 2026-07-28 (SEP-2577). Use direct LLM provider
|
|
134
159
|
# APIs instead.
|
|
135
|
-
def create_sampling_message(related_request_id: nil, **kwargs)
|
|
160
|
+
def create_sampling_message(related_request_id: nil, timeout: nil, **kwargs)
|
|
136
161
|
warn_unassociated_request(__method__, related_request_id)
|
|
137
162
|
|
|
138
163
|
params = @server.build_sampling_params(client_capabilities, **kwargs)
|
|
139
|
-
send_to_transport_request(
|
|
164
|
+
send_to_transport_request(
|
|
165
|
+
Methods::SAMPLING_CREATE_MESSAGE,
|
|
166
|
+
params,
|
|
167
|
+
related_request_id: related_request_id,
|
|
168
|
+
timeout: timeout,
|
|
169
|
+
)
|
|
140
170
|
end
|
|
141
171
|
|
|
142
172
|
# Sends an `elicitation/create` request (form mode) scoped to this session.
|
|
@@ -144,7 +174,7 @@ module MCP
|
|
|
144
174
|
# Per SEP-2260, the request must be associated with an originating client
|
|
145
175
|
# request; prefer `server_context.create_form_elicitation` inside a handler,
|
|
146
176
|
# which stamps the association automatically.
|
|
147
|
-
def create_form_elicitation(message:, requested_schema:, related_request_id: nil)
|
|
177
|
+
def create_form_elicitation(message:, requested_schema:, related_request_id: nil, timeout: nil)
|
|
148
178
|
warn_unassociated_request(__method__, related_request_id)
|
|
149
179
|
|
|
150
180
|
unless client_capabilities&.dig(:elicitation)
|
|
@@ -153,7 +183,12 @@ module MCP
|
|
|
153
183
|
end
|
|
154
184
|
|
|
155
185
|
params = { mode: "form", message: message, requestedSchema: requested_schema }
|
|
156
|
-
send_to_transport_request(
|
|
186
|
+
send_to_transport_request(
|
|
187
|
+
Methods::ELICITATION_CREATE,
|
|
188
|
+
params,
|
|
189
|
+
related_request_id: related_request_id,
|
|
190
|
+
timeout: timeout,
|
|
191
|
+
)
|
|
157
192
|
end
|
|
158
193
|
|
|
159
194
|
# Sends an `elicitation/create` request (URL mode) scoped to this session.
|
|
@@ -161,7 +196,7 @@ module MCP
|
|
|
161
196
|
# Per SEP-2260, the request must be associated with an originating client
|
|
162
197
|
# request; prefer `server_context.create_url_elicitation` inside a handler,
|
|
163
198
|
# which stamps the association automatically.
|
|
164
|
-
def create_url_elicitation(message:, url:, elicitation_id:, related_request_id: nil)
|
|
199
|
+
def create_url_elicitation(message:, url:, elicitation_id:, related_request_id: nil, timeout: nil)
|
|
165
200
|
warn_unassociated_request(__method__, related_request_id)
|
|
166
201
|
|
|
167
202
|
unless client_capabilities&.dig(:elicitation, :url)
|
|
@@ -170,7 +205,21 @@ module MCP
|
|
|
170
205
|
end
|
|
171
206
|
|
|
172
207
|
params = { mode: "url", message: message, url: url, elicitationId: elicitation_id }
|
|
173
|
-
send_to_transport_request(
|
|
208
|
+
send_to_transport_request(
|
|
209
|
+
Methods::ELICITATION_CREATE,
|
|
210
|
+
params,
|
|
211
|
+
related_request_id: related_request_id,
|
|
212
|
+
timeout: timeout,
|
|
213
|
+
)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
# Sends an embedded SEP-2322 `inputRequests` entry as a real server-to-client request on the legacy wire,
|
|
217
|
+
# for the server's dual-era fulfilment shim.
|
|
218
|
+
# The entry is forwarded verbatim - per the spec, clients treat each entry exactly like the equivalent
|
|
219
|
+
# standalone request - and stays associated with the originating client request per SEP-2260.
|
|
220
|
+
# Returns the client's result.
|
|
221
|
+
def fulfill_input_request(method, params, related_request_id:)
|
|
222
|
+
send_to_transport_request(method, params, related_request_id: related_request_id)
|
|
174
223
|
end
|
|
175
224
|
|
|
176
225
|
# Sends `notifications/cancelled` to the peer for a nested server-to-client request
|
|
@@ -223,7 +272,15 @@ module MCP
|
|
|
223
272
|
# is deprecated as of MCP protocol version 2026-07-28 (SEP-2577).
|
|
224
273
|
# Use stderr or OpenTelemetry instead.
|
|
225
274
|
def notify_log_message(data:, level:, logger: nil, related_request_id: nil)
|
|
226
|
-
|
|
275
|
+
# In the modern lifecycle, log delivery is authorized per request through the `_meta` envelope's `logLevel` member
|
|
276
|
+
# (applied via `configure_logging`); without it no `notifications/message` is sent, and the server-wide level
|
|
277
|
+
# does not apply (SEP-2575).
|
|
278
|
+
effective_logging = if @era == :modern
|
|
279
|
+
@logging_message_notification
|
|
280
|
+
else
|
|
281
|
+
@logging_message_notification || @server.logging_message_notification
|
|
282
|
+
end
|
|
283
|
+
|
|
227
284
|
return unless effective_logging&.should_notify?(level)
|
|
228
285
|
|
|
229
286
|
params = { "data" => data, "level" => level }
|
|
@@ -236,6 +293,10 @@ module MCP
|
|
|
236
293
|
|
|
237
294
|
private
|
|
238
295
|
|
|
296
|
+
def validate_era!(era)
|
|
297
|
+
raise ArgumentError, "era must be one of #{ERAS.inspect}" unless ERAS.include?(era)
|
|
298
|
+
end
|
|
299
|
+
|
|
239
300
|
# Forwards `send_notification` to the transport with only the kwargs the transport's method signature
|
|
240
301
|
# actually accepts. Custom transports that implement the abstract `send_notification(method, params = nil)`
|
|
241
302
|
# contract continue to work unchanged; bundled transports that declare `session_id:` / `related_request_id:`
|
|
@@ -255,7 +316,7 @@ module MCP
|
|
|
255
316
|
# `parent_cancellation:` / `server_session:` receive the nested-cancellation plumbing.
|
|
256
317
|
# When `related_request_id` names an in-flight request, its `Cancellation` token is looked up
|
|
257
318
|
# so that cancelling the parent also cancels this nested server-to-client request.
|
|
258
|
-
def send_to_transport_request(method, params, related_request_id: nil)
|
|
319
|
+
def send_to_transport_request(method, params, related_request_id: nil, timeout: nil)
|
|
259
320
|
parent_cancellation = related_request_id ? lookup_in_flight(related_request_id) : nil
|
|
260
321
|
|
|
261
322
|
kwargs = {
|
|
@@ -263,6 +324,7 @@ module MCP
|
|
|
263
324
|
related_request_id: related_request_id,
|
|
264
325
|
parent_cancellation: parent_cancellation,
|
|
265
326
|
server_session: self,
|
|
327
|
+
timeout: timeout,
|
|
266
328
|
}.compact
|
|
267
329
|
|
|
268
330
|
forward_to_transport(@transport.method(:send_request), method, params, kwargs)
|
data/lib/mcp/tool/response.rb
CHANGED
|
@@ -7,18 +7,24 @@ module MCP
|
|
|
7
7
|
|
|
8
8
|
attr_reader :content, :structured_content, :meta
|
|
9
9
|
|
|
10
|
-
def initialize(content =
|
|
10
|
+
def initialize(content = NOT_GIVEN, deprecated_error = NOT_GIVEN, error: false, structured_content: nil, meta: nil)
|
|
11
11
|
if deprecated_error != NOT_GIVEN
|
|
12
12
|
warn("Passing `error` with the 2nd argument of `Response.new` is deprecated. Use keyword argument like `Response.new(content, error: error)` instead.", uplevel: 1)
|
|
13
13
|
error = deprecated_error
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
content_given = !content.equal?(NOT_GIVEN)
|
|
17
|
+
@content_provided = content_given && !content.nil?
|
|
18
|
+
@content = content_given ? (content || []) : []
|
|
17
19
|
@error = error
|
|
18
20
|
@structured_content = structured_content
|
|
19
21
|
@meta = meta
|
|
20
22
|
end
|
|
21
23
|
|
|
24
|
+
def content_provided?
|
|
25
|
+
@content_provided
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
def error?
|
|
23
29
|
!!@error
|
|
24
30
|
end
|
data/lib/mcp/transport.rb
CHANGED
|
@@ -50,6 +50,13 @@ module MCP
|
|
|
50
50
|
raise NotImplementedError, "Subclasses must implement send_request"
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
+
# Whether the transport serves the `subscriptions/listen` notification stream (MCP 2026-07-28, SEP-2575).
|
|
54
|
+
# `Server#discover` strips the `listChanged`/`subscribe` capability flags when the transport cannot deliver
|
|
55
|
+
# those notifications in the modern lifecycle.
|
|
56
|
+
def serves_subscriptions_listen?
|
|
57
|
+
false
|
|
58
|
+
end
|
|
59
|
+
|
|
53
60
|
private
|
|
54
61
|
|
|
55
62
|
def generate_request_id
|
data/lib/mcp/version.rb
CHANGED
data/lib/mcp.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "json_rpc_handler"
|
|
4
4
|
require_relative "mcp/configuration"
|
|
5
|
+
require_relative "mcp/protocol_deprecations"
|
|
5
6
|
require_relative "mcp/string_utils"
|
|
6
7
|
require_relative "mcp/transport"
|
|
7
8
|
require_relative "mcp/version"
|
|
@@ -13,9 +14,11 @@ module MCP
|
|
|
13
14
|
autoload :CancelledError, "mcp/cancelled_error"
|
|
14
15
|
autoload :Client, "mcp/client"
|
|
15
16
|
autoload :Content, "mcp/content"
|
|
17
|
+
autoload :Elicitation, "mcp/elicitation"
|
|
16
18
|
autoload :ErrorCodes, "mcp/error_codes"
|
|
17
19
|
autoload :Icon, "mcp/icon"
|
|
18
20
|
autoload :Prompt, "mcp/prompt"
|
|
21
|
+
autoload :RequestEnvelope, "mcp/request_envelope"
|
|
19
22
|
autoload :Resource, "mcp/resource"
|
|
20
23
|
autoload :ResourceTemplate, "mcp/resource_template"
|
|
21
24
|
autoload :ResultType, "mcp/result_type"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Model Context Protocol
|
|
@@ -43,6 +43,8 @@ files:
|
|
|
43
43
|
- lib/mcp/client.rb
|
|
44
44
|
- lib/mcp/client/elicitation.rb
|
|
45
45
|
- lib/mcp/client/http.rb
|
|
46
|
+
- lib/mcp/client/mcp_param_headers.rb
|
|
47
|
+
- lib/mcp/client/modern_envelope.rb
|
|
46
48
|
- lib/mcp/client/oauth.rb
|
|
47
49
|
- lib/mcp/client/oauth/client_credentials_provider.rb
|
|
48
50
|
- lib/mcp/client/oauth/cross_app_access_provider.rb
|
|
@@ -59,6 +61,8 @@ files:
|
|
|
59
61
|
- lib/mcp/client/tool.rb
|
|
60
62
|
- lib/mcp/configuration.rb
|
|
61
63
|
- lib/mcp/content.rb
|
|
64
|
+
- lib/mcp/elicitation.rb
|
|
65
|
+
- lib/mcp/elicitation/enum_schema.rb
|
|
62
66
|
- lib/mcp/error_codes.rb
|
|
63
67
|
- lib/mcp/icon.rb
|
|
64
68
|
- lib/mcp/instrumentation.rb
|
|
@@ -69,6 +73,8 @@ files:
|
|
|
69
73
|
- lib/mcp/prompt/argument.rb
|
|
70
74
|
- lib/mcp/prompt/message.rb
|
|
71
75
|
- lib/mcp/prompt/result.rb
|
|
76
|
+
- lib/mcp/protocol_deprecations.rb
|
|
77
|
+
- lib/mcp/request_envelope.rb
|
|
72
78
|
- lib/mcp/resource.rb
|
|
73
79
|
- lib/mcp/resource/contents.rb
|
|
74
80
|
- lib/mcp/resource/embedded.rb
|
|
@@ -76,7 +82,10 @@ files:
|
|
|
76
82
|
- lib/mcp/result_type.rb
|
|
77
83
|
- lib/mcp/server.rb
|
|
78
84
|
- lib/mcp/server/capabilities.rb
|
|
85
|
+
- lib/mcp/server/input_required_result.rb
|
|
79
86
|
- lib/mcp/server/pagination.rb
|
|
87
|
+
- lib/mcp/server/pending_response.rb
|
|
88
|
+
- lib/mcp/server/request_state_security.rb
|
|
80
89
|
- lib/mcp/server/transports.rb
|
|
81
90
|
- lib/mcp/server/transports/stdio_transport.rb
|
|
82
91
|
- lib/mcp/server/transports/streamable_http_transport.rb
|
|
@@ -97,7 +106,7 @@ licenses:
|
|
|
97
106
|
- Apache-2.0
|
|
98
107
|
metadata:
|
|
99
108
|
allowed_push_host: https://rubygems.org
|
|
100
|
-
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v1.
|
|
109
|
+
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v1.2.0
|
|
101
110
|
homepage_uri: https://ruby.sdk.modelcontextprotocol.io
|
|
102
111
|
source_code_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
103
112
|
bug_tracker_uri: https://github.com/modelcontextprotocol/ruby-sdk/issues
|