Skip to content

Commit 11aea51

Browse files
authored
Merge pull request #179 from koic/add_draft_version
Add "Draft" protocol version to supported protocol versions
2 parents 26bbdfc + bf729ba commit 11aea51

File tree

6 files changed

+106
-9
lines changed

6 files changed

+106
-9
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ configuration = MCP::Configuration.new(protocol_version: "2024-11-05")
348348
MCP::Server.new(name: "test_server", configuration: configuration)
349349
```
350350

351+
If no protocol version is specified, the [Draft version](https://modelcontextprotocol.io/specification/draft) will be applied by default.
352+
351353
This will make all new server instances use the specified protocol version instead of the default version. The protocol version can be reset to the default by setting it to `nil`:
352354

353355
```ruby

lib/mcp/configuration.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
module MCP
44
class Configuration
5-
DEFAULT_PROTOCOL_VERSION = "2025-06-18"
6-
SUPPORTED_PROTOCOL_VERSIONS = [DEFAULT_PROTOCOL_VERSION, "2025-03-26", "2024-11-05"]
5+
# DRAFT-2025-v3 is the latest draft protocol version:
6+
# https://github.com/modelcontextprotocol/modelcontextprotocol/blob/14ec41c/schema/draft/schema.ts#L15
7+
DRAFT_PROTOCOL_VERSION = "DRAFT-2025-v3"
8+
SUPPORTED_STABLE_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"]
79

810
attr_writer :exception_reporter, :instrumentation_callback
911

@@ -33,7 +35,7 @@ def validate_tool_call_arguments=(validate_tool_call_arguments)
3335
end
3436

3537
def protocol_version
36-
@protocol_version || DEFAULT_PROTOCOL_VERSION
38+
@protocol_version || DRAFT_PROTOCOL_VERSION
3739
end
3840

3941
def protocol_version?
@@ -93,8 +95,8 @@ def merge(other)
9395
private
9496

9597
def validate_protocol_version!(protocol_version)
96-
unless SUPPORTED_PROTOCOL_VERSIONS.include?(protocol_version)
97-
message = "protocol_version must be #{SUPPORTED_PROTOCOL_VERSIONS[0...-1].join(", ")}, or #{SUPPORTED_PROTOCOL_VERSIONS[-1]}"
98+
unless SUPPORTED_STABLE_PROTOCOL_VERSIONS.include?(protocol_version)
99+
message = "protocol_version must be #{SUPPORTED_STABLE_PROTOCOL_VERSIONS[0...-1].join(", ")}, or #{SUPPORTED_STABLE_PROTOCOL_VERSIONS[-1]}"
98100
raise ArgumentError, message
99101
end
100102
end

lib/mcp/server.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ def define_tool(name: nil, title: nil, description: nil, input_schema: nil, anno
106106
def define_prompt(name: nil, title: nil, description: nil, arguments: [], &block)
107107
prompt = Prompt.define(name:, title:, description:, arguments:, &block)
108108
@prompts[prompt.name_value] = prompt
109+
110+
validate!
109111
end
110112

111113
def define_custom_method(method_name:, &block)
@@ -171,6 +173,21 @@ def prompts_get_handler(&block)
171173
private
172174

173175
def validate!
176+
# NOTE: The draft protocol version is the next version after 2025-03-26.
177+
if @configuration.protocol_version <= "2025-03-26"
178+
if server_info.key?(:title)
179+
message = "Error occurred in server_info. `title` is not supported in protocol version 2025-03-26 or earlier"
180+
raise ArgumentError, message
181+
end
182+
183+
primitive_titles = [@tools.values, @prompts.values, @resources, @resource_templates].flatten.map(&:title)
184+
185+
if primitive_titles.any?
186+
message = "Error occurred in #{primitive_titles.join(", ")}. `title` is not supported in protocol version 2025-03-26 or earlier"
187+
raise ArgumentError, message
188+
end
189+
end
190+
174191
if @configuration.protocol_version == "2024-11-05"
175192
if @instructions
176193
message = "`instructions` supported by protocol version 2025-03-26 or higher"

test/mcp/configuration_test.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,24 @@ class ConfigurationTest < ActiveSupport::TestCase
3535
assert_equal test_context, reported_context
3636
end
3737

38+
# https://github.com/modelcontextprotocol/modelcontextprotocol/blob/14ec41c/schema/draft/schema.ts#L15
3839
test "initializes with default protocol version" do
3940
config = Configuration.new
40-
assert_equal Configuration::DEFAULT_PROTOCOL_VERSION, config.protocol_version
41+
assert_equal Configuration::DRAFT_PROTOCOL_VERSION, config.protocol_version
42+
end
43+
44+
test "uses the draft protocol version when protocol_version is set to nil" do
45+
config = Configuration.new(protocol_version: nil)
46+
assert_equal Configuration::DRAFT_PROTOCOL_VERSION, config.protocol_version
47+
end
48+
49+
test "raises ArgumentError when setting the draft protocol version" do
50+
exception = assert_raises(ArgumentError) do
51+
# To use the draft version externally, either omit `protocol_version` or set it to nil.
52+
Configuration.new(protocol_version: Configuration::DRAFT_PROTOCOL_VERSION)
53+
end
54+
55+
assert_equal("protocol_version must be 2025-06-18, 2025-03-26, or 2024-11-05", exception.message)
4156
end
4257

4358
test "raises ArgumentError when protocol_version is not a supported protocol version" do

test/mcp/server/transports/streamable_http_transport_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class StreamableHTTPTransportTest < ActiveSupport::TestCase
8181
body = JSON.parse(response[2][0])
8282
assert_equal "2.0", body["jsonrpc"]
8383
assert_equal "123", body["id"]
84-
assert_equal "2025-06-18", body["result"]["protocolVersion"]
84+
assert_equal Configuration::DRAFT_PROTOCOL_VERSION, body["result"]["protocolVersion"]
8585
end
8686

8787
test "handles GET request with valid session ID" do

test/mcp/server_test.rb

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ class ServerTest < ActiveSupport::TestCase
133133
jsonrpc: "2.0",
134134
id: 1,
135135
result: {
136-
protocolVersion: "2025-06-18",
136+
protocolVersion: Configuration::DRAFT_PROTOCOL_VERSION,
137137
capabilities: {
138138
prompts: { listChanged: true },
139139
resources: { listChanged: true },
@@ -776,7 +776,7 @@ def call(message:, server_context: nil)
776776
}
777777

778778
response = @server.handle(request)
779-
assert_equal Configuration::DEFAULT_PROTOCOL_VERSION, response[:result][:protocolVersion]
779+
assert_equal Configuration::DRAFT_PROTOCOL_VERSION, response[:result][:protocolVersion]
780780
end
781781

782782
test "server response does not include title when not configured" do
@@ -852,6 +852,67 @@ def call(message:, server_context: nil)
852852
assert_equal("Error occurred in defined_tool. `annotations` are supported by protocol version 2025-03-26 or higher", exception.message)
853853
end
854854

855+
test "raises error if `title` of `server_info` is used with protocol version 2025-03-26" do
856+
configuration = Configuration.new(protocol_version: "2025-03-26")
857+
858+
exception = assert_raises(ArgumentError) do
859+
Server.new(name: "test_server", title: "Example Server Display Name", configuration: configuration)
860+
end
861+
assert_equal("Error occurred in server_info. `title` is not supported in protocol version 2025-03-26 or earlier", exception.message)
862+
end
863+
864+
test "raises error if `title` of tool is used with protocol version 2025-03-26" do
865+
configuration = Configuration.new(protocol_version: "2025-03-26")
866+
server = Server.new(name: "test_server", configuration: configuration)
867+
868+
exception = assert_raises(ArgumentError) do
869+
server.define_tool(
870+
title: "Test tool",
871+
)
872+
end
873+
assert_equal("Error occurred in Test tool. `title` is not supported in protocol version 2025-03-26 or earlier", exception.message)
874+
end
875+
876+
test "raises error if `title` of prompt is used with protocol version 2025-03-26" do
877+
configuration = Configuration.new(protocol_version: "2025-03-26")
878+
server = Server.new(name: "test_server", configuration: configuration)
879+
880+
exception = assert_raises(ArgumentError) do
881+
server.define_prompt(
882+
title: "Test prompt",
883+
)
884+
end
885+
assert_equal("Error occurred in Test prompt. `title` is not supported in protocol version 2025-03-26 or earlier", exception.message)
886+
end
887+
888+
test "raises error if `title` of resource is used with protocol version 2025-03-26" do
889+
configuration = Configuration.new(protocol_version: "2025-03-26")
890+
891+
resource = Resource.new(
892+
uri: "https://test_resource.invalid",
893+
name: "test-resource",
894+
title: "Test resource",
895+
)
896+
exception = assert_raises(ArgumentError) do
897+
Server.new(name: "test_server", resources: [resource], configuration: configuration)
898+
end
899+
assert_equal("Error occurred in Test resource. `title` is not supported in protocol version 2025-03-26 or earlier", exception.message)
900+
end
901+
902+
test "raises error if `title` of resource template is used with protocol version 2025-03-26" do
903+
configuration = Configuration.new(protocol_version: "2025-03-26")
904+
905+
resource = Resource.new(
906+
uri: "https://test_resource.invalid",
907+
name: "test-resource",
908+
title: "Test resource template",
909+
)
910+
exception = assert_raises(ArgumentError) do
911+
Server.new(name: "test_server", resources: [resource], configuration: configuration)
912+
end
913+
assert_equal("Error occurred in Test resource template. `title` is not supported in protocol version 2025-03-26 or earlier", exception.message)
914+
end
915+
855916
test "#define_tool adds a tool to the server" do
856917
@server.define_tool(
857918
name: "defined_tool",

0 commit comments

Comments
 (0)