Merge pull request #223 from chattermill/md-protocol-negotiation

Add protocol version negotiation to server initialization
This commit is contained in:
Koichi ITO 2026-02-06 00:11:28 +09:00 • committed by GitHub
commit 15ef5ebda2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 116 additions and 5 deletions

View file

@ -18,6 +18,9 @@ module MCP
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 @@ module MCP
}.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

View file

@ -1274,6 +1274,95 @@ module MCP
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],