Merge pull request #516 from koic/counter_offer_legacy_version_on_initialize
Stop negotiating modern protocol versions through the `initialize` handshake
This commit is contained in:
commit
a62e56ef48
7 changed files with 472 additions and 207 deletions
|
|
@ -327,8 +327,9 @@ module MCP
|
|||
#
|
||||
# @param client_info [Hash, nil] `{ name:, version: }` identifying the client.
|
||||
# Defaults to `{ name: "mcp-ruby-client", version: MCP::VERSION }`.
|
||||
# @param protocol_version [String, nil] Protocol version to offer. Defaults
|
||||
# to `MCP::Configuration::LATEST_STABLE_PROTOCOL_VERSION`.
|
||||
# @param protocol_version [String, nil] Protocol version to offer on the legacy handshake.
|
||||
# Defaults to `MCP::Configuration::LATEST_HANDSHAKE_PROTOCOL_VERSION`; a modern version
|
||||
# raises `ArgumentError` here (modern versions are selected via `mode: :modern`/`:auto`).
|
||||
# @param capabilities [Hash] Capabilities advertised by the client. Defaults to `{}`.
|
||||
# @return [Hash] The server's `InitializeResult`.
|
||||
# @raise [RequestHandlerError] If the server responds with a JSON-RPC error
|
||||
|
|
@ -341,6 +342,9 @@ module MCP
|
|||
def connect(client_info: nil, protocol_version: nil, capabilities: {}, mode: :legacy)
|
||||
return @server_info if connected?
|
||||
|
||||
# Per the SEP-2575 era model, a modern version cannot ride the legacy `initialize` handshake.
|
||||
MCP::Configuration.reject_modern_handshake_version!(protocol_version) if mode == :legacy
|
||||
|
||||
client_info ||= { name: "mcp-ruby-client", version: MCP::VERSION }
|
||||
|
||||
case mode
|
||||
|
|
@ -559,7 +563,7 @@ module MCP
|
|||
attr_reader :headers
|
||||
|
||||
def connect_legacy(client_info:, protocol_version:, capabilities:)
|
||||
protocol_version ||= MCP::Configuration::LATEST_STABLE_PROTOCOL_VERSION
|
||||
protocol_version ||= MCP::Configuration::LATEST_HANDSHAKE_PROTOCOL_VERSION
|
||||
|
||||
response = send_request(request: {
|
||||
jsonrpc: JsonRpcHandler::Version::V2_0,
|
||||
|
|
@ -593,7 +597,10 @@ module MCP
|
|||
|
||||
@server_info = response["result"]
|
||||
negotiated_protocol_version = @server_info["protocolVersion"]
|
||||
unless MCP::Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(negotiated_protocol_version)
|
||||
# A modern version in an `InitializeResult` is rejected along with unknown ones: the handshake
|
||||
# settles on a legacy version by definition, and the TypeScript and Python clients refuse
|
||||
# a modern counter-offer the same way.
|
||||
unless MCP::Configuration::SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.include?(negotiated_protocol_version)
|
||||
clear_session
|
||||
raise RequestHandlerError.new(
|
||||
"Server initialization failed: unsupported protocol version #{negotiated_protocol_version.inspect}",
|
||||
|
|
@ -602,8 +609,6 @@ module MCP
|
|||
)
|
||||
end
|
||||
|
||||
MCP::ProtocolDeprecations.warn_for_client_capabilities(capabilities, protocol_version: negotiated_protocol_version, uplevel: 1)
|
||||
|
||||
begin
|
||||
send_request(request: {
|
||||
jsonrpc: JsonRpcHandler::Version::V2_0,
|
||||
|
|
@ -647,6 +652,10 @@ module MCP
|
|||
)
|
||||
end
|
||||
|
||||
# SEP-2577 deprecates roots and sampling at 2026-07-28, the revision every modern connection speaks,
|
||||
# so the warning lives here now that the handshake cannot land on one.
|
||||
MCP::ProtocolDeprecations.warn_for_client_capabilities(capabilities, protocol_version: version, uplevel: 1)
|
||||
|
||||
@server_info = result
|
||||
@connected = true
|
||||
@server_info
|
||||
|
|
@ -658,8 +667,13 @@ module MCP
|
|||
# version as well: during the 2026-07-28 rollout a server may answer discovery while
|
||||
# only serving legacy versions.
|
||||
def connect_auto(client_info:, protocol_version:, capabilities:)
|
||||
connect_modern(client_info: client_info, protocol_version: nil, capabilities: capabilities)
|
||||
modern_pin = protocol_version if protocol_version && MCP::Configuration.modern_protocol_version?(protocol_version)
|
||||
connect_modern(client_info: client_info, protocol_version: modern_pin, capabilities: capabilities)
|
||||
rescue RequestHandlerError
|
||||
# An explicitly requested modern version is never downgraded by the fallback: the legacy handshake cannot negotiate it,
|
||||
# so the probe's failure is the real answer and propagates.
|
||||
raise if modern_pin
|
||||
|
||||
connect_legacy(client_info: client_info, protocol_version: protocol_version, capabilities: capabilities)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,9 @@ module MCP
|
|||
#
|
||||
# @param client_info [Hash, nil] `{ name:, version: }` identifying the client.
|
||||
# Defaults to `{ name: "mcp-ruby-client", version: MCP::VERSION }`.
|
||||
# @param protocol_version [String, nil] Protocol version to offer. Defaults
|
||||
# to `MCP::Configuration::LATEST_STABLE_PROTOCOL_VERSION`.
|
||||
# @param protocol_version [String, nil] Protocol version to offer on the legacy handshake.
|
||||
# Defaults to `MCP::Configuration::LATEST_HANDSHAKE_PROTOCOL_VERSION`; a modern version
|
||||
# raises `ArgumentError` here (modern versions are selected via `mode: :modern`/`:auto`).
|
||||
# @param capabilities [Hash] Capabilities advertised by the client. Defaults to `{}`.
|
||||
# @return [Hash] The server's `InitializeResult`.
|
||||
# @raise [RequestHandlerError] If the server responds with a JSON-RPC error,
|
||||
|
|
@ -91,6 +92,9 @@ module MCP
|
|||
def connect(client_info: nil, protocol_version: nil, capabilities: {}, mode: :legacy)
|
||||
return @server_info if connected?
|
||||
|
||||
# Validated before `start` so a pure argument error never spawns the server process.
|
||||
MCP::Configuration.reject_modern_handshake_version!(protocol_version) if mode == :legacy
|
||||
|
||||
start unless @started
|
||||
|
||||
client_info ||= { name: "mcp-ruby-client", version: MCP::VERSION }
|
||||
|
|
@ -221,7 +225,7 @@ module MCP
|
|||
private
|
||||
|
||||
def connect_legacy(client_info:, protocol_version:, capabilities:)
|
||||
protocol_version ||= MCP::Configuration::LATEST_STABLE_PROTOCOL_VERSION
|
||||
protocol_version ||= MCP::Configuration::LATEST_HANDSHAKE_PROTOCOL_VERSION
|
||||
|
||||
init_request = {
|
||||
jsonrpc: JsonRpcHandler::Version::V2_0,
|
||||
|
|
@ -257,9 +261,11 @@ module MCP
|
|||
@server_info = response["result"]
|
||||
|
||||
negotiated_protocol_version = @server_info["protocolVersion"]
|
||||
unless MCP::Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(negotiated_protocol_version)
|
||||
unless MCP::Configuration::SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.include?(negotiated_protocol_version)
|
||||
# Per spec, if the client does not support the server's returned protocol version,
|
||||
# the client SHOULD disconnect. Roll back the cached `InitializeResult` before raising
|
||||
# the client SHOULD disconnect. A modern version is rejected along with unknown ones:
|
||||
# the handshake settles on a legacy version by definition, and the TypeScript and Python clients refuse
|
||||
# a modern counter-offer the same way. Roll back the cached `InitializeResult` before raising
|
||||
# so a retry starts without a stale `server_info`.
|
||||
# https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle#version-negotiation
|
||||
@server_info = nil
|
||||
|
|
@ -270,8 +276,6 @@ module MCP
|
|||
)
|
||||
end
|
||||
|
||||
MCP::ProtocolDeprecations.warn_for_client_capabilities(capabilities, protocol_version: negotiated_protocol_version, uplevel: 1)
|
||||
|
||||
begin
|
||||
notification = {
|
||||
jsonrpc: JsonRpcHandler::Version::V2_0,
|
||||
|
|
@ -317,6 +321,10 @@ module MCP
|
|||
)
|
||||
end
|
||||
|
||||
# SEP-2577 deprecates roots and sampling at 2026-07-28, the revision every modern connection speaks,
|
||||
# so the warning lives here now that the handshake cannot land on one.
|
||||
MCP::ProtocolDeprecations.warn_for_client_capabilities(capabilities, protocol_version: version, uplevel: 1)
|
||||
|
||||
@server_info = result
|
||||
@server_info
|
||||
end
|
||||
|
|
@ -327,8 +335,13 @@ module MCP
|
|||
# version as well: during the 2026-07-28 rollout a server may answer discovery while
|
||||
# only serving legacy versions.
|
||||
def connect_auto(client_info:, protocol_version:, capabilities:)
|
||||
connect_modern(client_info: client_info, protocol_version: nil, capabilities: capabilities)
|
||||
modern_pin = protocol_version if protocol_version && MCP::Configuration.modern_protocol_version?(protocol_version)
|
||||
connect_modern(client_info: client_info, protocol_version: modern_pin, capabilities: capabilities)
|
||||
rescue RequestHandlerError
|
||||
# An explicitly requested modern version is never downgraded by the fallback: the legacy handshake cannot negotiate it,
|
||||
# so the probe's failure is the real answer and propagates.
|
||||
raise if modern_pin
|
||||
|
||||
connect_legacy(client_info: client_info, protocol_version: protocol_version, capabilities: capabilities)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,19 +9,40 @@ module MCP
|
|||
].freeze
|
||||
DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26"
|
||||
|
||||
# Protocol versions of the stateless "modern" lifecycle introduced by the MCP 2026-07-28 spec release (SEP-2575).
|
||||
# 2026-07-28 serves both lifecycles of the dual-era model: it is negotiable through the legacy `initialize`
|
||||
# handshake (so it also appears in `SUPPORTED_STABLE_PROTOCOL_VERSIONS`), and it is the version of the modern
|
||||
# lifecycle, where each request carries its own version in `_meta` and is validated against this list
|
||||
# independently, with no handshake.
|
||||
# Protocol versions of the stateless "modern" lifecycle introduced by the MCP 2026-07-28 spec release (SEP-2575),
|
||||
# where each request carries its own version in `_meta` and is validated against this list independently,
|
||||
# with no handshake. These are reachable only through `server/discover` and the per-request envelope.
|
||||
# https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
|
||||
LATEST_MODERN_PROTOCOL_VERSION = "2026-07-28"
|
||||
SUPPORTED_MODERN_PROTOCOL_VERSIONS = [LATEST_MODERN_PROTOCOL_VERSION].freeze
|
||||
|
||||
# Protocol versions reachable through the legacy `initialize` handshake, derived so the era partition
|
||||
# (handshake = stable minus modern) cannot drift when a new revision lands.
|
||||
# Per the SEP-2575 era model, an era is a property of the protocol version itself: legacy versions establish
|
||||
# a session via `initialize` (2025-11-25 and earlier), and modern versions carry the version on every request
|
||||
# in `_meta` with no handshake at all. The handshake therefore never negotiates a modern version:
|
||||
# a client asking `initialize` for one is counter-offered
|
||||
# `LATEST_HANDSHAKE_PROTOCOL_VERSION`, matching the TypeScript and Python SDKs.
|
||||
SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS = (SUPPORTED_STABLE_PROTOCOL_VERSIONS - SUPPORTED_MODERN_PROTOCOL_VERSIONS).freeze
|
||||
LATEST_HANDSHAKE_PROTOCOL_VERSION = SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.first
|
||||
|
||||
class << self
|
||||
def modern_protocol_version?(version)
|
||||
SUPPORTED_MODERN_PROTOCOL_VERSIONS.include?(version)
|
||||
end
|
||||
|
||||
def handshake_protocol_version?(version)
|
||||
SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.include?(version)
|
||||
end
|
||||
|
||||
# The one statement of the client-side handshake contract, shared by every transport:
|
||||
# a modern version cannot ride the legacy `initialize` handshake.
|
||||
def reject_modern_handshake_version!(version)
|
||||
return unless version && modern_protocol_version?(version)
|
||||
|
||||
raise ArgumentError, "protocol version #{version.inspect} cannot be negotiated through the legacy " \
|
||||
"`initialize` handshake; use `mode: :modern` (or `:auto`) instead"
|
||||
end
|
||||
end
|
||||
|
||||
attr_writer :exception_reporter, :around_request
|
||||
|
|
@ -78,8 +99,12 @@ module MCP
|
|||
@validate_tool_call_results = validate_tool_call_results
|
||||
end
|
||||
|
||||
# The pin scopes the `initialize` handshake, so an unset pin reads as the version that handshake
|
||||
# settles on by default. Reading the newest version of any era here would hand back a value
|
||||
# the writer rejects, and no caller wants the modern revision: a modern connection carries
|
||||
# its version on every request instead of consulting configuration.
|
||||
def protocol_version
|
||||
@protocol_version || LATEST_STABLE_PROTOCOL_VERSION
|
||||
@protocol_version || LATEST_HANDSHAKE_PROTOCOL_VERSION
|
||||
end
|
||||
|
||||
def protocol_version?
|
||||
|
|
@ -174,11 +199,24 @@ module MCP
|
|||
|
||||
private
|
||||
|
||||
# A pin scopes the `initialize` handshake, so only handshake versions are accepted:
|
||||
# a modern version has no handshake to pin (its version rides every request in `_meta`),
|
||||
# and accepting one here would configure nothing. Failing at construction beats
|
||||
# a setting that silently does not apply.
|
||||
def validate_protocol_version!(protocol_version)
|
||||
unless SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(protocol_version)
|
||||
message = "protocol_version must be #{SUPPORTED_STABLE_PROTOCOL_VERSIONS[0...-1].join(", ")}, or #{SUPPORTED_STABLE_PROTOCOL_VERSIONS[-1]}"
|
||||
raise ArgumentError, message
|
||||
return if SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.include?(protocol_version)
|
||||
|
||||
# A version this SDK serves, rejected only for where it was set, deserves the reason and
|
||||
# the alternative rather than a list it is missing from: this is the error an upgrade from
|
||||
# a release that accepted the value lands on, so it doubles as the migration note.
|
||||
if self.class.modern_protocol_version?(protocol_version)
|
||||
raise ArgumentError, "protocol_version #{protocol_version.inspect} is a modern protocol version and cannot be pinned here: " \
|
||||
"the pin scopes the `initialize` handshake, which never negotiates a modern version. " \
|
||||
"Modern clients carry their version on every request and need no pin; remove the setting."
|
||||
end
|
||||
|
||||
raise ArgumentError, "protocol_version must be #{SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS[0...-1].join(", ")}, " \
|
||||
"or #{SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS[-1]}"
|
||||
end
|
||||
|
||||
def validate_value_of_validate_tool_call_arguments!(validate_tool_call_arguments)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,15 @@
|
|||
require_relative "configuration"
|
||||
|
||||
module MCP
|
||||
# Warning texts for the features SEP-2577 deprecates at 2026-07-28.
|
||||
#
|
||||
# Only the client emits these, from the modern connect, where the capabilities it declares are
|
||||
# the ones being deprecated. No server-side trigger remains: the `initialize` handshake never lands on
|
||||
# a deprecating revision and `Configuration` rejects a modern pin, so nothing on that side can reach
|
||||
# a version these apply to. `LOGGING_MESSAGE` in particular has no caller left
|
||||
# (a modern client declares no logging capability, and `notify_log_message` on that wire is
|
||||
# the SEP-2575 sanctioned delivery path rather than a deprecated call). It stays public and
|
||||
# callable for embedders, and because deleting it would be a breaking change for no gain.
|
||||
module ProtocolDeprecations
|
||||
extend self
|
||||
|
||||
|
|
|
|||
|
|
@ -403,8 +403,6 @@ module MCP
|
|||
# is deprecated as of MCP protocol version 2026-07-28 (SEP-2577).
|
||||
# Use stderr or OpenTelemetry instead.
|
||||
def notify_log_message(data:, level:, logger: nil)
|
||||
warn_if_deprecated_protocol_feature(:logging, uplevel: 1)
|
||||
|
||||
return unless @transport
|
||||
return unless logging_message_notification&.should_notify?(level)
|
||||
|
||||
|
|
@ -425,8 +423,6 @@ module MCP
|
|||
# version 2026-07-28 (SEP-2577). Use tool parameters, resource URIs,
|
||||
# server configuration, or environment variables instead.
|
||||
def roots_list_changed_handler(&block)
|
||||
warn_if_deprecated_protocol_feature(:roots, uplevel: 1)
|
||||
|
||||
@handlers[Methods::NOTIFICATIONS_ROOTS_LIST_CHANGED] = block
|
||||
end
|
||||
|
||||
|
|
@ -591,13 +587,6 @@ module MCP
|
|||
return ->(params) { handle_cancelled_notification(params, session: session) }
|
||||
end
|
||||
|
||||
case method
|
||||
when Methods::NOTIFICATIONS_ROOTS_LIST_CHANGED
|
||||
warn_if_deprecated_protocol_feature(:roots, session: session, uplevel: 2)
|
||||
when Methods::LOGGING_SET_LEVEL
|
||||
warn_if_deprecated_protocol_feature(:logging, session: session, uplevel: 2)
|
||||
end
|
||||
|
||||
handler = @handlers[method]
|
||||
unless handler
|
||||
instrument_call("unsupported_method", server_context: { request: request }) do
|
||||
|
|
@ -1045,10 +1034,19 @@ module MCP
|
|||
end
|
||||
protocol_version = params[:protocolVersion]
|
||||
|
||||
negotiated_version = if Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(protocol_version)
|
||||
# Per the SEP-2575 era model, `initialize` negotiates legacy protocol versions only: a modern version is
|
||||
# defined by carrying its own version on every request in `_meta`, with no handshake,
|
||||
# so asking `initialize` for one (or for a version this server does not know) is answered with
|
||||
# a counter-offer instead of an echo, matching the TypeScript and Python SDKs. Modern versions
|
||||
# stay reachable through `server/discover` and the per-request envelope. The counter-offer is
|
||||
# a configured `protocol_version` pin when one is set (`Configuration` only accepts handshake versions there),
|
||||
# and the latest handshake version otherwise.
|
||||
negotiated_version = if Configuration.handshake_protocol_version?(protocol_version)
|
||||
protocol_version
|
||||
else
|
||||
elsif configuration.protocol_version?
|
||||
configuration.protocol_version
|
||||
else
|
||||
Configuration::LATEST_HANDSHAKE_PROTOCOL_VERSION
|
||||
end
|
||||
|
||||
info = server_info.reject do |property|
|
||||
|
|
@ -1160,19 +1158,6 @@ module MCP
|
|||
{}
|
||||
end
|
||||
|
||||
def warn_if_deprecated_protocol_feature(feature, session: nil, uplevel: 1)
|
||||
protocol_version = effective_deprecation_protocol_version(session)
|
||||
MCP::ProtocolDeprecations.warn_for(feature, protocol_version: protocol_version, uplevel: uplevel)
|
||||
end
|
||||
|
||||
def effective_deprecation_protocol_version(session)
|
||||
session&.protocol_version || @client_protocol_version || explicit_protocol_version
|
||||
end
|
||||
|
||||
def explicit_protocol_version
|
||||
configuration.protocol_version if configuration.protocol_version?
|
||||
end
|
||||
|
||||
def list_tools(request)
|
||||
page = paginate(@tools.values, cursor: cursor_from(request), page_size: @page_size, request: request, &:to_h)
|
||||
|
||||
|
|
|
|||
|
|
@ -277,12 +277,12 @@ module MCP
|
|||
# An empty header value is malformed rather than a version claim, so it stays on the legacy path
|
||||
# and fails legacy header validation as before.
|
||||
#
|
||||
# 2026-07-28 serves both lifecycles of the dual-era model, so for that header value the version
|
||||
# alone cannot decide the era: an `Mcp-Session-Id` binds the request to an established legacy session
|
||||
# (POST requests, the GET SSE stream, and DELETE termination keep working), and a session-less POST whose
|
||||
# body is `initialize` is the legacy-distinctive handshake. Everything else under a dual-era header is
|
||||
# sessionless modern traffic (`server/discover`, envelope-carrying requests, and envelope-missing requests
|
||||
# that get the modern path's error shape).
|
||||
# A modern header value (2026-07-28) alone cannot decide the era: sessionless modern traffic carries it,
|
||||
# and requests of an established legacy session may stamp it as well (the handshake itself never negotiates it):
|
||||
# an `Mcp-Session-Id` binds the request to an established legacy session (POST requests, the GET SSE stream,
|
||||
# and DELETE termination keep working), and a session-less POST whose body is `initialize` is
|
||||
# the legacy-distinctive handshake. Everything else under a dual-era header is sessionless modern traffic
|
||||
# (`server/discover`, envelope-carrying requests, and envelope-missing requests that get the modern path's error shape).
|
||||
header_version = request.env["HTTP_MCP_PROTOCOL_VERSION"]
|
||||
if header_version && !header_version.empty? && !stable_only_version?(header_version)
|
||||
unless MCP::Configuration.modern_protocol_version?(header_version)
|
||||
|
|
@ -1414,8 +1414,9 @@ module MCP
|
|||
body.is_a?(Hash) && body[:method] == Methods::SERVER_DISCOVER
|
||||
end
|
||||
|
||||
# A version negotiable only through the legacy handshake, with no modern meaning.
|
||||
# Dual-era versions (2026-07-28) appear in both lists and need further disambiguation.
|
||||
# A version with no modern meaning, whose header can only accompany legacy traffic.
|
||||
# A modern version's header (2026-07-28) can accompany either era's traffic - the handshake never negotiates it,
|
||||
# but requests of an established legacy session may stamp it - so that value needs further disambiguation.
|
||||
def stable_only_version?(version)
|
||||
MCP::Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(version) &&
|
||||
!MCP::Configuration.modern_protocol_version?(version)
|
||||
|
|
|
|||
|
|
@ -132,7 +132,6 @@ module MCP
|
|||
# version 2026-07-28 (SEP-2577). Use tool parameters, resource URIs,
|
||||
# server configuration, or environment variables instead.
|
||||
def list_roots(related_request_id: nil, timeout: nil)
|
||||
@server.send(:warn_if_deprecated_protocol_feature, :roots, session: self, uplevel: 2)
|
||||
warn_unassociated_request(__method__, related_request_id)
|
||||
|
||||
unless client_capabilities&.dig(:roots)
|
||||
|
|
@ -159,7 +158,6 @@ module MCP
|
|||
# MCP protocol version 2026-07-28 (SEP-2577). Use direct LLM provider
|
||||
# APIs instead.
|
||||
def create_sampling_message(related_request_id: nil, timeout: nil, **kwargs)
|
||||
@server.send(:warn_if_deprecated_protocol_feature, :sampling, session: self, uplevel: 2)
|
||||
warn_unassociated_request(__method__, related_request_id)
|
||||
|
||||
params = @server.build_sampling_params(client_capabilities, **kwargs)
|
||||
|
|
@ -274,8 +272,6 @@ module MCP
|
|||
# is deprecated as of MCP protocol version 2026-07-28 (SEP-2577).
|
||||
# Use stderr or OpenTelemetry instead.
|
||||
def notify_log_message(data:, level:, logger: nil, related_request_id: nil)
|
||||
@server.send(:warn_if_deprecated_protocol_feature, :logging, session: self, uplevel: 2)
|
||||
|
||||
# In the modern lifecycle, log delivery is authorized per request through the `_meta` envelope's `logLevel` member
|
||||
# (applied via `configure_logging`); without it no `notifications/message` is sent, and the server-wide level
|
||||
# does not apply (SEP-2575).
|
||||
|
|
|
|||
Loading…
Reference in a new issue