From 1c14f65d2ffc3919762a3cbbeb280d5fb00ec472 Mon Sep 17 00:00:00 2001 From: Mikhail Dubov Date: Sun, 1 Feb 2026 14:27:21 +0000 Subject: [PATCH] Add protocol version negotiation to server initialization --- lib/mcp/server.rb | 32 +++++++++++++-- test/mcp/server_test.rb | 89 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 4 deletions(-) diff --git a/lib/mcp/server.rb b/lib/mcp/server.rb index e100516..155be8d 100644 --- a/lib/mcp/server.rb +++ b/lib/mcp/server.rb @@ -313,12 +313,36 @@ def server_info }.compact end - def init(request) + def init(params) + client_version = params&.dig(:protocolVersion) || params&.dig("protocolVersion") + negotiated_version = if client_version && Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(client_version) + client_version + else + configuration.protocol_version + end + + info = server_info.dup + response_instructions = instructions + + if negotiated_version <= "2025-06-18" + info.delete(:description) + info.delete(:icons) + end + + if negotiated_version <= "2025-03-26" + info.delete(:title) + info.delete(:websiteUrl) + end + + if negotiated_version == "2024-11-05" + response_instructions = nil + end + { - protocolVersion: configuration.protocol_version, + protocolVersion: negotiated_version, capabilities: capabilities, - serverInfo: server_info, - instructions: instructions, + serverInfo: info, + instructions: response_instructions, }.compact end diff --git a/test/mcp/server_test.rb b/test/mcp/server_test.rb index 061987c..1f3db2b 100644 --- a/test/mcp/server_test.rb +++ b/test/mcp/server_test.rb @@ -1227,6 +1227,95 @@ class Example < Tool assert_equal custom_version, response[:result][:protocolVersion] end + test "server negotiates protocol version when client requests a supported version" do + server = Server.new(name: "test_server") + + request = { + jsonrpc: "2.0", + method: "initialize", + id: 1, + params: { + protocolVersion: "2025-06-18", + }, + } + + response = server.handle(request) + assert_equal "2025-06-18", response[:result][:protocolVersion] + end + + test "server falls back to default version when client requests unsupported version" do + server = Server.new(name: "test_server") + + request = { + jsonrpc: "2.0", + method: "initialize", + id: 1, + params: { + protocolVersion: "1999-01-01", + }, + } + + response = server.handle(request) + assert_equal Configuration::LATEST_STABLE_PROTOCOL_VERSION, response[:result][:protocolVersion] + end + + test "server removes description and icons from server_info when negotiating to 2025-06-18" do + server = Server.new( + name: "test_server", + description: "A test server", + icons: [Icon.new(src: "https://example.com/icon.png")], + ) + + request = { + jsonrpc: "2.0", + method: "initialize", + id: 1, + params: { + protocolVersion: "2025-06-18", + }, + } + + response = server.handle(request) + assert_equal "2025-06-18", response[:result][:protocolVersion] + refute response[:result][:serverInfo].key?(:description) + refute response[:result][:serverInfo].key?(:icons) + end + + test "server removes title and websiteUrl when negotiating to 2025-03-26" do + server = Server.new(name: "test_server", title: "Test Server", website_url: "https://example.com") + + request = { + jsonrpc: "2.0", + method: "initialize", + id: 1, + params: { + protocolVersion: "2025-03-26", + }, + } + + response = server.handle(request) + assert_equal "2025-03-26", response[:result][:protocolVersion] + refute response[:result][:serverInfo].key?(:title) + refute response[:result][:serverInfo].key?(:websiteUrl) + end + + test "server removes instructions when negotiating to 2024-11-05" do + server = Server.new(name: "test_server", instructions: "Some instructions") + + request = { + jsonrpc: "2.0", + method: "initialize", + id: 1, + params: { + protocolVersion: "2024-11-05", + }, + } + + response = server.handle(request) + assert_equal "2024-11-05", response[:result][:protocolVersion] + refute response[:result].key?(:instructions) + end + test "tools/call handles missing arguments field" do server = Server.new( tools: [TestTool],