diff --git a/lib/mcp/server.rb b/lib/mcp/server.rb index 2048101..122cf99 100644 --- a/lib/mcp/server.rb +++ b/lib/mcp/server.rb @@ -18,6 +18,9 @@ def initialize(duplicated_tool_names) class Server DEFAULT_VERSION = "0.1.0" + UNSUPPORTED_PROPERTIES_UNTIL_2025_06_18 = [:description, :icons].freeze + UNSUPPORTED_PROPERTIES_UNTIL_2025_03_26 = [:title, :websiteUrl].freeze + class RequestHandlerError < StandardError attr_reader :error_type attr_reader :original_error @@ -319,13 +322,32 @@ def server_info }.compact end - def init(request) - @client = request[:clientInfo] if request + def init(params) + @client = params[:clientInfo] if params + + protocol_version = params[:protocolVersion] if params + negotiated_version = if Configuration::SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(protocol_version) + protocol_version + else + configuration.protocol_version + end + + info = server_info.reject do |property| + negotiated_version <= "2025-06-18" && UNSUPPORTED_PROPERTIES_UNTIL_2025_06_18.include?(property) || + negotiated_version <= "2025-03-26" && UNSUPPORTED_PROPERTIES_UNTIL_2025_03_26.include?(property) + end + + response_instructions = instructions + + 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 9c81401..37eeb77 100644 --- a/test/mcp/server_test.rb +++ b/test/mcp/server_test.rb @@ -1274,6 +1274,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],