mcp 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +156 -13
- data/lib/mcp/annotations.rb +5 -0
- data/lib/mcp/client/http.rb +66 -4
- data/lib/mcp/client/stdio.rb +65 -11
- data/lib/mcp/client.rb +194 -30
- data/lib/mcp/methods.rb +4 -0
- data/lib/mcp/server/transports/stdio_transport.rb +51 -3
- data/lib/mcp/server/transports/streamable_http_transport.rb +272 -16
- data/lib/mcp/server.rb +27 -1
- data/lib/mcp/server_context.rb +17 -2
- data/lib/mcp/server_session.rb +10 -0
- data/lib/mcp/tool/output_schema.rb +17 -0
- data/lib/mcp/tool/schema.rb +66 -8
- data/lib/mcp/version.rb +1 -1
- metadata +2 -2
data/lib/mcp/tool/schema.rb
CHANGED
|
@@ -36,16 +36,29 @@ module MCP
|
|
|
36
36
|
end
|
|
37
37
|
VALIDATION_CACHE = ValidationCache.new
|
|
38
38
|
|
|
39
|
-
# JSON Schema 2020-12 is the default dialect for MCP schema definitions
|
|
40
|
-
#
|
|
41
|
-
#
|
|
39
|
+
# JSON Schema 2020-12 is the default dialect for MCP schema definitions per MCP 2025-11-25 (SEP-1613),
|
|
40
|
+
# and SEP-2106 requires tool schemas to conform to the full 2020-12 vocabulary. Both emission and
|
|
41
|
+
# runtime validation use this dialect. Because MCP mandates 2020-12, the SDK validates against it
|
|
42
|
+
# regardless of any `$schema` a document embeds; for compliant schemas this is the same dialect
|
|
43
|
+
# the Python SDK's `jsonschema.validate` resolves to.
|
|
42
44
|
JSON_SCHEMA_2020_12_URI = "https://json-schema.org/draft/2020-12/schema"
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
# Resource bounds for schema compilation, mirroring the TypeScript SDK's schema bounds (SEP-2106):
|
|
47
|
+
# schemas may use the full JSON Schema 2020-12 vocabulary including composition keywords and `$ref`,
|
|
48
|
+
# so adversarial documents must be rejected before they can cause excessive validation cost.
|
|
49
|
+
# Only same-document references (starting with `#`) are accepted, so schema handling can never trigger network
|
|
50
|
+
# or file access.
|
|
51
|
+
MAX_SCHEMA_DEPTH = 64
|
|
52
|
+
MAX_SUBSCHEMA_COUNT = 10_000
|
|
53
|
+
|
|
54
|
+
# Reference keywords whose targets the SDK refuses to dereference. Both `$ref` and `$dynamicRef` may carry
|
|
55
|
+
# an absolute URI under JSON Schema 2020-12, so a non-same-document value is an external reference.
|
|
56
|
+
REFERENCE_KEYWORDS = [:"$ref", :"$dynamicRef"].freeze
|
|
45
57
|
|
|
46
58
|
def initialize(schema = {})
|
|
47
59
|
@schema = JSON.parse(JSON.dump(schema), symbolize_names: true)
|
|
48
|
-
|
|
60
|
+
apply_default_root_type!
|
|
61
|
+
validate_schema_bounds!
|
|
49
62
|
validate_schema!
|
|
50
63
|
end
|
|
51
64
|
|
|
@@ -61,6 +74,48 @@ module MCP
|
|
|
61
74
|
|
|
62
75
|
private
|
|
63
76
|
|
|
77
|
+
# Root-type defaulting hook. The base class preserves the historical behavior of defaulting the root
|
|
78
|
+
# to an object schema; `OutputSchema` overrides this because SEP-2106 allows any root schema there.
|
|
79
|
+
def apply_default_root_type!
|
|
80
|
+
@schema[:type] ||= "object"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Enforces `MAX_SCHEMA_DEPTH` / `MAX_SUBSCHEMA_COUNT` and the same-document reference rule over
|
|
84
|
+
# the whole schema document.
|
|
85
|
+
def validate_schema_bounds!
|
|
86
|
+
subschema_count = 0
|
|
87
|
+
stack = [[@schema, 1]]
|
|
88
|
+
|
|
89
|
+
until stack.empty?
|
|
90
|
+
node, depth = stack.pop
|
|
91
|
+
if depth > MAX_SCHEMA_DEPTH
|
|
92
|
+
raise ArgumentError,
|
|
93
|
+
"Invalid JSON Schema: nesting exceeds the maximum depth of #{MAX_SCHEMA_DEPTH}."
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
case node
|
|
97
|
+
when Hash
|
|
98
|
+
subschema_count += 1
|
|
99
|
+
if subschema_count > MAX_SUBSCHEMA_COUNT
|
|
100
|
+
raise ArgumentError,
|
|
101
|
+
"Invalid JSON Schema: document exceeds the maximum of #{MAX_SUBSCHEMA_COUNT} subschema objects."
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
REFERENCE_KEYWORDS.each do |keyword|
|
|
105
|
+
ref = node[keyword]
|
|
106
|
+
next unless ref.is_a?(String) && !ref.start_with?("#")
|
|
107
|
+
|
|
108
|
+
raise ArgumentError,
|
|
109
|
+
"Invalid JSON Schema: only same-document #{keyword} (starting with '#') is supported, got #{ref.inspect}."
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
node.each_value { |child| stack << [child, depth + 1] }
|
|
113
|
+
when Array
|
|
114
|
+
node.each { |child| stack << [child, depth + 1] }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
64
119
|
def stringify(obj)
|
|
65
120
|
case obj
|
|
66
121
|
when Hash
|
|
@@ -78,13 +133,16 @@ module MCP
|
|
|
78
133
|
# Memoized per Schema instance because schema content is fixed at construction,
|
|
79
134
|
# so the compiled schemer is reusable across many `fully_validate` calls.
|
|
80
135
|
#
|
|
136
|
+
# Validated against the JSON Schema 2020-12 metaschema per SEP-2106, so `$defs`/`$ref` and
|
|
137
|
+
# the rest of the 2020-12 vocabulary resolve natively.
|
|
138
|
+
#
|
|
81
139
|
# `format: false` preserves the legacy behavior of the previous `json-schema` based implementation,
|
|
82
140
|
# which did not enforce `format` keywords. `RegexpError` from a malformed `pattern` is re-raised as
|
|
83
141
|
# `ArgumentError` so callers see the same exception class they used to.
|
|
84
142
|
def schemer
|
|
85
143
|
@schemer ||= JSONSchemer.schema(
|
|
86
144
|
stringify(schema_for_validation),
|
|
87
|
-
meta_schema:
|
|
145
|
+
meta_schema: JSON_SCHEMA_2020_12_URI,
|
|
88
146
|
format: false,
|
|
89
147
|
)
|
|
90
148
|
rescue RegexpError => e
|
|
@@ -112,8 +170,8 @@ module MCP
|
|
|
112
170
|
VALIDATION_CACHE.store(key)
|
|
113
171
|
end
|
|
114
172
|
|
|
115
|
-
#
|
|
116
|
-
#
|
|
173
|
+
# Strip the top-level `$schema` before validation so the SDK always validates against
|
|
174
|
+
# the 2020-12 metaschema (SEP-2106) regardless of any dialect URI a caller embedded in the document.
|
|
117
175
|
def schema_for_validation
|
|
118
176
|
return @schema unless @schema.key?(:"$schema")
|
|
119
177
|
|
data/lib/mcp/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mcp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.23.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Model Context Protocol
|
|
@@ -90,7 +90,7 @@ licenses:
|
|
|
90
90
|
- Apache-2.0
|
|
91
91
|
metadata:
|
|
92
92
|
allowed_push_host: https://rubygems.org
|
|
93
|
-
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.
|
|
93
|
+
changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v0.23.0
|
|
94
94
|
homepage_uri: https://ruby.sdk.modelcontextprotocol.io
|
|
95
95
|
source_code_uri: https://github.com/modelcontextprotocol/ruby-sdk
|
|
96
96
|
bug_tracker_uri: https://github.com/modelcontextprotocol/ruby-sdk/issues
|