Skip to content

Commit d20eac0

Browse files
authored
Merge pull request modelcontextprotocol#476 from koic/support_2026_07_28_as_latest_protocol_version
Support 2026-07-28 as the Latest Protocol Version
2 parents ba88d9f + dc25610 commit d20eac0

6 files changed

Lines changed: 60 additions & 16 deletions

File tree

conformance/expected_failures.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
server: []
2-
client: []
2+
client:
3+
# TODO: The conformance framework's client-initialization check pins the expected requested version to 2025-11-25,
4+
# while this SDK's latest protocol version is 2026-07-28. Remove once the @modelcontextprotocol/conformance package
5+
# accepts 2026-07-28.
6+
- initialize

docs/building-clients.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Call `MCP::Client#connect` to perform the MCP [initialization handshake](https:/
2222

2323
```ruby
2424
client.connect
25-
# => { "protocolVersion" => "2025-11-25", "capabilities" => {...}, "serverInfo" => {...} }
25+
# => { "protocolVersion" => "2026-07-28", "capabilities" => {...}, "serverInfo" => {...} }
2626

2727
client.connected? # => true
2828
client.server_info # => cached InitializeResult
@@ -99,7 +99,7 @@ After `connect` succeeds, the HTTP transport captures the `Mcp-Session-Id` heade
9999

100100
```ruby
101101
http_transport.session_id # => "abc123..."
102-
http_transport.protocol_version # => "2025-11-25"
102+
http_transport.protocol_version # => "2026-07-28"
103103
```
104104

105105
If the server terminates the session, subsequent requests return HTTP 404 and the transport raises `MCP::Client::SessionExpiredError` (a subclass of `RequestHandlerError`). Session state is cleared automatically; callers should start a new session by calling `connect` again.

lib/mcp/configuration.rb

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
module MCP
44
class Configuration
5-
LATEST_STABLE_PROTOCOL_VERSION = "2025-11-25"
5+
LATEST_STABLE_PROTOCOL_VERSION = "2026-07-28"
66
SUPPORTED_STABLE_PROTOCOL_VERSIONS = [
7-
LATEST_STABLE_PROTOCOL_VERSION, "2025-06-18", "2025-03-26", "2024-11-05",
7+
LATEST_STABLE_PROTOCOL_VERSION, "2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05",
88
].freeze
99
DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26"
1010

1111
# Protocol versions of the stateless "modern" lifecycle introduced by the MCP 2026-07-28 spec release (SEP-2575).
12-
# Modern versions are deliberately kept out of `SUPPORTED_STABLE_PROTOCOL_VERSIONS`: the modern lifecycle has
13-
# no `initialize` handshake, so these versions are never negotiated (each request carries its own version in `_meta`
14-
# and is validated against this list independently), and `protocol_version=` keeps rejecting them for the same reason.
12+
# 2026-07-28 serves both lifecycles of the dual-era model: it is negotiable through the legacy `initialize`
13+
# handshake (so it also appears in `SUPPORTED_STABLE_PROTOCOL_VERSIONS`), and it is the version of the modern
14+
# lifecycle, where each request carries its own version in `_meta` and is validated against this list
15+
# independently, with no handshake.
1516
# https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
1617
LATEST_MODERN_PROTOCOL_VERSION = "2026-07-28"
1718
SUPPORTED_MODERN_PROTOCOL_VERSIONS = [LATEST_MODERN_PROTOCOL_VERSION].freeze

test/mcp/configuration_test.rb

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class ConfigurationTest < ActiveSupport::TestCase
5454
Configuration.new(protocol_version: "DRAFT-2025-v3")
5555
end
5656

57-
assert_equal("protocol_version must be 2025-11-25, 2025-06-18, 2025-03-26, or 2024-11-05", exception.message)
57+
assert_equal("protocol_version must be 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26, or 2024-11-05", exception.message)
5858
end
5959

6060
test "raises ArgumentError when protocol_version is not a supported protocol version" do
@@ -63,7 +63,7 @@ class ConfigurationTest < ActiveSupport::TestCase
6363
custom_version = "2025-03-27"
6464
config.protocol_version = custom_version
6565
end
66-
assert_equal("protocol_version must be 2025-11-25, 2025-06-18, 2025-03-26, or 2024-11-05", exception.message)
66+
assert_equal("protocol_version must be 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26, or 2024-11-05", exception.message)
6767
end
6868

6969
test "exposes the SEP-2575 modern protocol versions" do
@@ -73,12 +73,11 @@ class ConfigurationTest < ActiveSupport::TestCase
7373
refute Configuration.modern_protocol_version?("2025-11-25")
7474
end
7575

76-
test "raises ArgumentError when setting a modern protocol version" do
77-
# Modern versions (SEP-2575) are never negotiated via `initialize`, so they are deliberately not settable as
78-
# the legacy fallback version.
79-
assert_raises(ArgumentError) do
80-
Configuration.new(protocol_version: Configuration::LATEST_MODERN_PROTOCOL_VERSION)
81-
end
76+
test "accepts 2026-07-28 as the protocol version" do
77+
# 2026-07-28 serves both lifecycles of the dual-era model (SEP-2575), so it is negotiable through
78+
# the legacy `initialize` handshake and settable as the fallback version.
79+
config = Configuration.new(protocol_version: Configuration::LATEST_MODERN_PROTOCOL_VERSION)
80+
assert_equal "2026-07-28", config.protocol_version
8281
end
8382

8483
test "raises ArgumentError when protocol_version is not a boolean value" do

test/mcp/server/transports/streamable_http_transport_test.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,6 +1993,32 @@ def string
19931993
assert_equal 200, response[0]
19941994
end
19951995

1996+
test "POST request with the 2026-07-28 MCP-Protocol-Version header succeeds" do
1997+
init_request = create_rack_request(
1998+
"POST",
1999+
"/",
2000+
{ "CONTENT_TYPE" => "application/json" },
2001+
{ jsonrpc: "2.0", method: "initialize", id: "init", params: initialize_params(protocolVersion: "2026-07-28") }.to_json,
2002+
)
2003+
init_response = @transport.handle_request(init_request)
2004+
assert_equal "2026-07-28", JSON.parse(init_response[2][0])["result"]["protocolVersion"]
2005+
session_id = init_response[1]["mcp-session-id"]
2006+
2007+
request = create_rack_request(
2008+
"POST",
2009+
"/",
2010+
{
2011+
"CONTENT_TYPE" => "application/json",
2012+
"HTTP_MCP_SESSION_ID" => session_id,
2013+
"HTTP_MCP_PROTOCOL_VERSION" => "2026-07-28",
2014+
},
2015+
{ jsonrpc: "2.0", method: "tools/list", id: "list" }.to_json,
2016+
)
2017+
2018+
response = @transport.handle_request(request)
2019+
assert_equal 200, response[0]
2020+
end
2021+
19962022
test "POST request without MCP-Protocol-Version header succeeds" do
19972023
init_request = create_rack_request(
19982024
"POST",

test/mcp/server_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2036,6 +2036,20 @@ def read_resource_request(uri)
20362036
assert_equal Configuration::LATEST_STABLE_PROTOCOL_VERSION, response[:result][:protocolVersion]
20372037
end
20382038

2039+
test "server negotiates 2026-07-28 when the client requests it via initialize" do
2040+
server = Server.new(name: "test_server")
2041+
2042+
request = {
2043+
jsonrpc: "2.0",
2044+
method: "initialize",
2045+
id: 1,
2046+
params: initialize_params(protocolVersion: "2026-07-28"),
2047+
}
2048+
2049+
response = server.handle(request)
2050+
assert_equal "2026-07-28", response[:result][:protocolVersion]
2051+
end
2052+
20392053
test "server removes description and icons from server_info when negotiating to 2025-06-18" do
20402054
server = Server.new(
20412055
name: "test_server",

0 commit comments

Comments
 (0)