mcp 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7e47e8d36e628ba2779956d3a876b466f00eb80b92e29f43f5b8135c1698eadb
4
- data.tar.gz: 71ea590aed7b14098c6d1707347be1d7d1ffc9b8e321ec8784bb62e364daa095
3
+ metadata.gz: 356017978ae1c4a455d50d37bd9a178aba8989ee5e001bed8ab309977071f71f
4
+ data.tar.gz: cc62cd7e64421b3a45c49d60709610cf0bf552183b4a2f08c2adef9e0bde2e29
5
5
  SHA512:
6
- metadata.gz: eac238d515948c47a61d3ce4f584f83c0f8cf7282e52fab1aecd0080f895fb4674a38d5fcb21382d4bd12ec72e8223467c7ad8680a76cb4d85c72448ec5875a6
7
- data.tar.gz: c0fbf1ee2021aa4634c80f49731987e40f1fcf72a7c84bd4be74e685fa821b069d17dbe90f848c0a2909cfa30c6fcce49034acf985b55f6434f88d6a26caa3ff
6
+ metadata.gz: 5464fcaa9535b838cd7b3bccffa7c9d4f461cb4ca91ac08067d9f9fa97bde4124bd9214c57c6d7928ce4315135dcabcfff445d48b24f325f0acaace0b8af5fc9
7
+ data.tar.gz: 118dba080f17a6464892b4d65a57e147ffe405539457940a7f25184ead416af03accf4ac27809e5b4c0fb2d1a6942e58edcc8f73b71c88fc364bf658861353f0
data/README.md CHANGED
@@ -872,6 +872,53 @@ class WeatherTool < MCP::Tool
872
872
  end
873
873
  ```
874
874
 
875
+ ### Tool Responses with Image, Audio, and Embedded Resources
876
+
877
+ Tool responses are not limited to text. The `MCP::Content` module provides `Image`, `Audio`, and `EmbeddedResource` content types,
878
+ which serialize to the `image`, `audio`, and `resource` content blocks defined by the MCP spec. Image and audio data is passed as
879
+ a base64-encoded string together with its MIME type:
880
+
881
+ ```ruby
882
+ class ChartTool < MCP::Tool
883
+ description "Render a chart as a PNG image"
884
+
885
+ def self.call(server_context:)
886
+ MCP::Tool::Response.new([
887
+ MCP::Content::Text.new("Here is the rendered chart:").to_h,
888
+ MCP::Content::Image.new(Base64.strict_encode64(render_chart_png), "image/png").to_h,
889
+ ])
890
+ end
891
+ end
892
+
893
+ class SpeechTool < MCP::Tool
894
+ description "Synthesize speech audio"
895
+
896
+ def self.call(server_context:)
897
+ MCP::Tool::Response.new([
898
+ MCP::Content::Audio.new(Base64.strict_encode64(synthesize_wav), "audio/wav").to_h,
899
+ ])
900
+ end
901
+ end
902
+ ```
903
+
904
+ An embedded resource wraps `MCP::Resource::TextContents` or `MCP::Resource::BlobContents`, allowing a tool to return resource contents inline:
905
+
906
+ ```ruby
907
+ class ReportTool < MCP::Tool
908
+ description "Return a report as an embedded resource"
909
+
910
+ def self.call(server_context:)
911
+ contents = MCP::Resource::TextContents.new(
912
+ uri: "report://monthly",
913
+ mime_type: "application/json",
914
+ text: { total: 42 }.to_json,
915
+ )
916
+
917
+ MCP::Tool::Response.new([MCP::Content::EmbeddedResource.new(contents).to_h])
918
+ end
919
+ end
920
+ ```
921
+
875
922
  ### Prompts
876
923
 
877
924
  MCP spec includes [Prompts](https://modelcontextprotocol.io/specification/latest/server/prompts), which enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs.
@@ -1010,6 +1057,49 @@ The server will handle prompt listing and execution through the MCP protocol met
1010
1057
  - `prompts/list` - Lists all registered prompts and their schemas
1011
1058
  - `prompts/get` - Retrieves and executes a specific prompt with arguments
1012
1059
 
1060
+ ### Prompts with Image and Embedded Resource Content
1061
+
1062
+ Prompt messages are not limited to text. The same `MCP::Content` types used in tool responses can be used as message content,
1063
+ letting a prompt template include images or inline resource contents. Unlike tool responses, the content object is passed directly rather than as a hash;
1064
+ `MCP::Prompt::Message` serializes it when the prompt result is returned:
1065
+
1066
+ ```ruby
1067
+ class CodeReviewPrompt < MCP::Prompt
1068
+ prompt_name "code_review"
1069
+ description "Review a source file with an accompanying diagram"
1070
+ arguments [
1071
+ MCP::Prompt::Argument.new(name: "file_uri", description: "URI of the file to review", required: true),
1072
+ ]
1073
+
1074
+ class << self
1075
+ def template(args, server_context:)
1076
+ MCP::Prompt::Result.new(
1077
+ messages: [
1078
+ MCP::Prompt::Message.new(
1079
+ role: "user",
1080
+ content: MCP::Content::EmbeddedResource.new(
1081
+ MCP::Resource::TextContents.new(
1082
+ uri: args["file_uri"],
1083
+ mime_type: "text/x-ruby",
1084
+ text: read_source(args["file_uri"]),
1085
+ ),
1086
+ ),
1087
+ ),
1088
+ MCP::Prompt::Message.new(
1089
+ role: "user",
1090
+ content: MCP::Content::Image.new(architecture_diagram_base64, "image/png"),
1091
+ ),
1092
+ MCP::Prompt::Message.new(
1093
+ role: "user",
1094
+ content: MCP::Content::Text.new("Please review the code above, using the diagram for context."),
1095
+ ),
1096
+ ],
1097
+ )
1098
+ end
1099
+ end
1100
+ end
1101
+ ```
1102
+
1013
1103
  ### Resources
1014
1104
 
1015
1105
  MCP spec includes [Resources](https://modelcontextprotocol.io/specification/latest/server/resources).
@@ -1126,6 +1216,34 @@ server.resources_read_handler do |params|
1126
1216
  end
1127
1217
  ```
1128
1218
 
1219
+ ### Reading Binary Resources
1220
+
1221
+ For binary resources, respond with a base64-encoded `blob` field instead of `text`.
1222
+ The `MCP::Resource::TextContents` and `MCP::Resource::BlobContents` classes build the two contents shapes defined by the spec:
1223
+
1224
+ ```ruby
1225
+ server.resources_read_handler do |params|
1226
+ case params[:uri]
1227
+ when "file:///logo.png"
1228
+ [
1229
+ MCP::Resource::BlobContents.new(
1230
+ uri: params[:uri],
1231
+ mime_type: "image/png",
1232
+ data: Base64.strict_encode64(File.binread("logo.png")),
1233
+ ).to_h,
1234
+ ]
1235
+ else
1236
+ [
1237
+ MCP::Resource::TextContents.new(
1238
+ uri: params[:uri],
1239
+ mime_type: "text/plain",
1240
+ text: "Hello from example resource!",
1241
+ ).to_h,
1242
+ ]
1243
+ end
1244
+ end
1245
+ ```
1246
+
1129
1247
  ### Resource Templates
1130
1248
 
1131
1249
  Resource templates follow the same pattern. Class-based templates declare a `uri_template` and
@@ -1201,6 +1319,31 @@ server = MCP::Server.new(
1201
1319
  )
1202
1320
  ```
1203
1321
 
1322
+ Registered templates are listed through the `resources/templates/list` protocol method.
1323
+ To serve reads for URIs that match a template, extract the variable parts of the URI in your `resources_read_handler`:
1324
+
1325
+ ```ruby
1326
+ resource_template = MCP::ResourceTemplate.new(
1327
+ uri_template: "file:///items/{item_id}",
1328
+ name: "item",
1329
+ mime_type: "application/json",
1330
+ )
1331
+
1332
+ server = MCP::Server.new(name: "my_server", resource_templates: [resource_template])
1333
+
1334
+ server.resources_read_handler do |params|
1335
+ if (match = params[:uri].match(%r{\Afile:///items/(?<item_id>[^/]+)\z}))
1336
+ [{
1337
+ uri: params[:uri],
1338
+ mimeType: "application/json",
1339
+ text: { id: match[:item_id] }.to_json,
1340
+ }]
1341
+ else
1342
+ raise MCP::Server::ResourceNotFoundError.new(params[:uri], params)
1343
+ end
1344
+ end
1345
+ ```
1346
+
1204
1347
  ### Roots
1205
1348
 
1206
1349
  The Model Context Protocol allows servers to request filesystem roots from clients through the `roots/list` method.
@@ -1793,6 +1936,40 @@ server.define_tool(name: "collect_contact", description: "Collect contact info")
1793
1936
  end
1794
1937
  ```
1795
1938
 
1939
+ The `requested_schema` must be a flat object schema: a top-level `type: "object"` whose `properties` are limited to
1940
+ primitive types (`string`, `number`, `integer`, `boolean`). Nested objects and arrays are not allowed, which keeps
1941
+ the schema simple enough for clients to render as a form. Per the MCP specification, the client validates
1942
+ the user's input against this schema before returning it, so the `content` of an `accept` response matches the requested shape.
1943
+
1944
+ #### Default Values and Enums
1945
+
1946
+ Properties may declare a `default` value (SEP-1034), which clients use to pre-fill the form.
1947
+ String properties may declare `enum` values, optionally with human-readable `enumNames` (SEP-1330), which clients render as a choice list:
1948
+
1949
+ ```ruby
1950
+ server.define_tool(name: "configure_deploy", description: "Configure a deployment") do |server_context:|
1951
+ result = server_context.create_form_elicitation(
1952
+ message: "Configure the deployment",
1953
+ requested_schema: {
1954
+ type: "object",
1955
+ properties: {
1956
+ replicas: { type: "integer", default: 3 },
1957
+ verbose: { type: "boolean", default: false },
1958
+ environment: {
1959
+ type: "string",
1960
+ enum: ["dev", "staging", "prod"],
1961
+ enumNames: ["Development", "Staging", "Production"],
1962
+ default: "dev",
1963
+ },
1964
+ },
1965
+ required: ["environment"],
1966
+ },
1967
+ )
1968
+
1969
+ MCP::Tool::Response.new([{ type: "text", text: "Deploying to #{result[:content][:environment]}" }])
1970
+ end
1971
+ ```
1972
+
1796
1973
  #### URL Mode
1797
1974
 
1798
1975
  URL mode directs the user to an external URL for out-of-band interactions such as OAuth flows:
@@ -3,13 +3,14 @@
3
3
  module MCP
4
4
  class Client
5
5
  class Tool
6
- attr_reader :name, :description, :input_schema, :output_schema
6
+ attr_reader :name, :description, :input_schema, :output_schema, :annotations
7
7
 
8
- def initialize(name:, description:, input_schema:, output_schema: nil)
8
+ def initialize(name:, description:, input_schema:, output_schema: nil, annotations: nil)
9
9
  @name = name
10
10
  @description = description
11
11
  @input_schema = input_schema
12
12
  @output_schema = output_schema
13
+ @annotations = annotations
13
14
  end
14
15
  end
15
16
  end
data/lib/mcp/client.rb CHANGED
@@ -166,6 +166,7 @@ module MCP
166
166
  description: tool["description"],
167
167
  input_schema: tool["inputSchema"],
168
168
  output_schema: tool["outputSchema"],
169
+ annotations: tool["annotations"],
169
170
  )
170
171
  end
171
172
 
@@ -2,12 +2,27 @@
2
2
 
3
3
  module MCP
4
4
  class Configuration
5
- LATEST_STABLE_PROTOCOL_VERSION = "2025-11-25"
5
+ LATEST_STABLE_PROTOCOL_VERSION = "2026-07-28"
6
6
  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",
8
8
  ].freeze
9
9
  DEFAULT_NEGOTIATED_PROTOCOL_VERSION = "2025-03-26"
10
10
 
11
+ # Protocol versions of the stateless "modern" lifecycle introduced by the MCP 2026-07-28 spec release (SEP-2575).
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.
16
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
17
+ LATEST_MODERN_PROTOCOL_VERSION = "2026-07-28"
18
+ SUPPORTED_MODERN_PROTOCOL_VERSIONS = [LATEST_MODERN_PROTOCOL_VERSION].freeze
19
+
20
+ class << self
21
+ def modern_protocol_version?(version)
22
+ SUPPORTED_MODERN_PROTOCOL_VERSIONS.include?(version)
23
+ end
24
+ end
25
+
11
26
  attr_writer :exception_reporter, :around_request
12
27
 
13
28
  # @deprecated Use {#around_request=} instead. `instrumentation_callback`
@@ -3,18 +3,24 @@
3
3
  module MCP
4
4
  # MCP-specific JSON-RPC error codes, complementing the generic codes in `JsonRpcHandler::ErrorCode`.
5
5
  #
6
- # Both constants below are introduced by the stateless lifecycle of the MCP 2026-07-28 draft (SEP-2575):
7
- # `UNSUPPORTED_PROTOCOL_VERSION` rejects a request whose `_meta`-carried protocol version the server does not
8
- # support (`error.data: { supported: [...], requested: "..." }`), and `MISSING_REQUIRED_CLIENT_CAPABILITY`
9
- # rejects a request that requires a client capability the request did not declare
10
- # (`error.data: { requiredCapabilities: {...} }`). The SDK exports the vocabulary; it does not raise
11
- # these codes itself yet.
6
+ # All three constants below are introduced by the stateless lifecycle of the MCP 2026-07-28 draft (SEP-2575):
12
7
  #
13
- # The values come from the spec's MCP-specific error code block, which is allocated sequentially from
14
- # `-32020` toward `-32099`. `-32020` (`HEADER_MISMATCH`, SEP-2243) precedes the two codes defined here.
8
+ # - `HEADER_MISMATCH` rejects an HTTP request whose headers do not match the corresponding body values,
9
+ # or whose required headers are missing or malformed (no `error.data`). It is reserved for
10
+ # the Streamable HTTP transport, since headers do not exist on stdio.
11
+ # - `MISSING_REQUIRED_CLIENT_CAPABILITY` rejects a request that requires a client capability
12
+ # the request did not declare (`error.data: { requiredCapabilities: {...} }`).
13
+ # Raised via `Server::MissingRequiredClientCapabilityError`.
14
+ # - `UNSUPPORTED_PROTOCOL_VERSION` rejects a request whose `_meta`-carried protocol version the server
15
+ # does not support (`error.data: { supported: [...], requested: "..." }`). Raised via
16
+ # `Server::UnsupportedProtocolVersionError`.
17
+ #
18
+ # The values come from the spec's MCP-specific error code block, which is allocated sequentially from `-32020`
19
+ # toward `-32099`.
15
20
  #
16
21
  # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
17
22
  module ErrorCodes
23
+ HEADER_MISMATCH = -32020
18
24
  MISSING_REQUIRED_CLIENT_CAPABILITY = -32021
19
25
  UNSUPPORTED_PROTOCOL_VERSION = -32022
20
26
  end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MCP
4
+ # The per-request `_meta` envelope of the stateless "modern" lifecycle (MCP 2026-07-28, SEP-2575).
5
+ # The modern lifecycle has no `initialize` handshake: every request identifies its protocol version,
6
+ # client, and client capabilities through reserved `_meta` keys, and the server validates
7
+ # each request independently. Servers MUST NOT infer capabilities from prior requests,
8
+ # which is why the envelope is a per-request value object rather than session state.
9
+ #
10
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
11
+ class RequestEnvelope
12
+ PROTOCOL_VERSION_META_KEY = "io.modelcontextprotocol/protocolVersion"
13
+ CLIENT_INFO_META_KEY = "io.modelcontextprotocol/clientInfo"
14
+ CLIENT_CAPABILITIES_META_KEY = "io.modelcontextprotocol/clientCapabilities"
15
+
16
+ # Optional per-request log level, replacing the `logging/setLevel` RPC in the modern lifecycle.
17
+ # Deprecated as of 2026-07-28 (SEP-2577) but still part of the wire format.
18
+ LOG_LEVEL_META_KEY = "io.modelcontextprotocol/logLevel"
19
+
20
+ REQUIRED_META_KEYS = [
21
+ PROTOCOL_VERSION_META_KEY,
22
+ CLIENT_INFO_META_KEY,
23
+ CLIENT_CAPABILITIES_META_KEY,
24
+ ].freeze
25
+
26
+ class << self
27
+ # A request is classified as modern only when the full REQUIRED triple is present,
28
+ # matching the TypeScript SDK's `RequestMetaEnvelopeSchema` and the Python SDK's `_has_modern_envelope`.
29
+ # A partial triple is treated as legacy so existing `_meta` usage (`progressToken`, trace context) keeps
30
+ # flowing through the legacy path.
31
+ def modern?(params)
32
+ meta = extract_meta(params)
33
+ return false unless meta.is_a?(Hash)
34
+
35
+ REQUIRED_META_KEYS.all? { |key| !read(meta, key).nil? }
36
+ end
37
+
38
+ # Parses and validates the envelope. `request` is only used to enrich the raised error;
39
+ # callers dispatching notifications can omit it.
40
+ def parse!(params, request: nil)
41
+ meta = extract_meta(params)
42
+ meta = {} unless meta.is_a?(Hash)
43
+
44
+ protocol_version = read(meta, PROTOCOL_VERSION_META_KEY)
45
+ client_info = read(meta, CLIENT_INFO_META_KEY)
46
+ client_capabilities = read(meta, CLIENT_CAPABILITIES_META_KEY)
47
+
48
+ unless protocol_version.is_a?(String) && client_info.is_a?(Hash) && client_capabilities.is_a?(Hash)
49
+ raise Server::RequestHandlerError.new(
50
+ "Invalid Request: modern requests require `#{REQUIRED_META_KEYS.join("`, `")}` in `_meta`",
51
+ request,
52
+ error_type: :invalid_request,
53
+ )
54
+ end
55
+
56
+ unless Configuration.modern_protocol_version?(protocol_version)
57
+ raise Server::UnsupportedProtocolVersionError.new(protocol_version, request)
58
+ end
59
+
60
+ new(
61
+ protocol_version: protocol_version,
62
+ client_info: client_info,
63
+ client_capabilities: client_capabilities,
64
+ log_level: read(meta, LOG_LEVEL_META_KEY),
65
+ )
66
+ end
67
+
68
+ private
69
+
70
+ # `Server#handle` accepts hashes parsed with either symbol or string keys, so read both forms
71
+ # (the same tolerance as `Server#handle_cancelled_notification`).
72
+ def extract_meta(params)
73
+ return unless params.is_a?(Hash)
74
+
75
+ meta = params[:_meta]
76
+ meta.nil? ? params["_meta"] : meta
77
+ end
78
+
79
+ def read(meta, key)
80
+ value = meta[key.to_sym]
81
+ value.nil? ? meta[key] : value
82
+ end
83
+ end
84
+
85
+ attr_reader :protocol_version, :client_info, :client_capabilities, :log_level
86
+
87
+ def initialize(protocol_version:, client_info:, client_capabilities:, log_level: nil)
88
+ @protocol_version = protocol_version
89
+ @client_info = client_info
90
+ @client_capabilities = client_capabilities
91
+ @log_level = log_level
92
+ freeze
93
+ end
94
+ end
95
+ end
data/lib/mcp/server.rb CHANGED
@@ -59,6 +59,41 @@ module MCP
59
59
  end
60
60
  end
61
61
 
62
+ # Raised when a request carries a protocol version the server does not support under the stateless lifecycle of
63
+ # MCP 2026-07-28 (SEP-2575). Maps to JSON-RPC error `-32022` with `data: { supported: [...], requested: "..." }`
64
+ # so the client can select a mutually supported version and retry.
65
+ #
66
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
67
+ class UnsupportedProtocolVersionError < RequestHandlerError
68
+ def initialize(requested, request = nil, supported: Configuration::SUPPORTED_MODERN_PROTOCOL_VERSIONS)
69
+ super(
70
+ "Unsupported protocol version",
71
+ request,
72
+ error_type: :unsupported_protocol_version,
73
+ error_code: ErrorCodes::UNSUPPORTED_PROTOCOL_VERSION,
74
+ error_data: { supported: supported, requested: requested || "unknown" },
75
+ )
76
+ end
77
+ end
78
+
79
+ # Raised when processing a request requires a client capability the request did not declare in `_meta`
80
+ # (`io.modelcontextprotocol/clientCapabilities`). Per SEP-2575, servers MUST NOT rely on capabilities
81
+ # the client has not declared. Maps to JSON-RPC error `-32021` with `data: { requiredCapabilities: {...} }`
82
+ # listing the missing capabilities.
83
+ #
84
+ # https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575
85
+ class MissingRequiredClientCapabilityError < RequestHandlerError
86
+ def initialize(required_capabilities, request = nil)
87
+ super(
88
+ "Missing required client capability",
89
+ request,
90
+ error_type: :missing_required_client_capability,
91
+ error_code: ErrorCodes::MISSING_REQUIRED_CLIENT_CAPABILITY,
92
+ error_data: { requiredCapabilities: required_capabilities },
93
+ )
94
+ end
95
+ end
96
+
62
97
  # Raised when a requested resource URI does not exist. Per SEP-2164,
63
98
  # resource-not-found errors use the standard JSON-RPC Invalid Params code (-32602)
64
99
  # with the requested URI in the error `data` member. Raise this from
@@ -745,11 +780,15 @@ module MCP
745
780
 
746
781
  progress_token = request.dig(:_meta, :progressToken)
747
782
 
748
- result = call_tool_with_args(
783
+ response = call_tool_with_args(
749
784
  tool, arguments, server_context_with_meta(request), progress_token: progress_token, session: session, related_request_id: related_request_id, cancellation: cancellation
750
785
  )
786
+ result = response.to_h
751
787
  validate_tool_call_result!(tool, result)
752
- serialize_structured_content_fallback(result)
788
+ serialize_structured_content_fallback(
789
+ result,
790
+ content_provided: response.respond_to?(:content_provided?) && response.content_provided?,
791
+ )
753
792
  rescue RequestHandlerError, CancelledError
754
793
  # CancelledError is intentionally not wrapped so `handle_request` can turn it into
755
794
  # `JsonRpcHandler::NO_RESPONSE` per the MCP cancellation spec.
@@ -986,14 +1025,18 @@ module MCP
986
1025
 
987
1026
  # Per SEP-2106, `structuredContent` may be any JSON value, not only an object.
988
1027
  # Clients on older protocol versions may only read `content`,
989
- # so when a tool returns non-object structured content without providing
990
- # any content blocks, mirror the value into `content` as serialized JSON text.
991
- def serialize_structured_content_fallback(result)
1028
+ # so when a tool returns non-object structured content without explicitly
1029
+ # providing `content`, mirror the value into serialized JSON text.
1030
+ def serialize_structured_content_fallback(result, content_provided: false)
992
1031
  structured = result[:structuredContent]
993
1032
  return result if structured.nil? || structured.is_a?(Hash)
1033
+ return result if content_provided
994
1034
  return result unless result[:content].nil? || result[:content].empty?
995
1035
 
996
- result.merge(content: [{ type: "text", text: JSON.generate(structured) }])
1036
+ serialized = JSON.generate(structured)
1037
+ return result if JSON.parse(serialized).is_a?(Hash)
1038
+
1039
+ result.merge(content: [{ type: "text", text: serialized }])
997
1040
  end
998
1041
 
999
1042
  # Whether a tool/prompt handler opts in to receiving an `MCP::ServerContext`.
@@ -1026,9 +1069,9 @@ module MCP
1026
1069
  related_request_id: related_request_id,
1027
1070
  cancellation: cancellation,
1028
1071
  )
1029
- tool.call(**args, server_context: server_context).to_h
1072
+ tool.call(**args, server_context: server_context)
1030
1073
  else
1031
- tool.call(**args).to_h
1074
+ tool.call(**args)
1032
1075
  end
1033
1076
  end
1034
1077
 
@@ -7,18 +7,24 @@ module MCP
7
7
 
8
8
  attr_reader :content, :structured_content, :meta
9
9
 
10
- def initialize(content = nil, deprecated_error = NOT_GIVEN, error: false, structured_content: nil, meta: nil)
10
+ def initialize(content = NOT_GIVEN, deprecated_error = NOT_GIVEN, error: false, structured_content: nil, meta: nil)
11
11
  if deprecated_error != NOT_GIVEN
12
12
  warn("Passing `error` with the 2nd argument of `Response.new` is deprecated. Use keyword argument like `Response.new(content, error: error)` instead.", uplevel: 1)
13
13
  error = deprecated_error
14
14
  end
15
15
 
16
- @content = content || []
16
+ content_given = !content.equal?(NOT_GIVEN)
17
+ @content_provided = content_given && !content.nil?
18
+ @content = content_given ? (content || []) : []
17
19
  @error = error
18
20
  @structured_content = structured_content
19
21
  @meta = meta
20
22
  end
21
23
 
24
+ def content_provided?
25
+ @content_provided
26
+ end
27
+
22
28
  def error?
23
29
  !!@error
24
30
  end
data/lib/mcp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MCP
4
- VERSION = "1.0.0"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/mcp.rb CHANGED
@@ -16,6 +16,7 @@ module MCP
16
16
  autoload :ErrorCodes, "mcp/error_codes"
17
17
  autoload :Icon, "mcp/icon"
18
18
  autoload :Prompt, "mcp/prompt"
19
+ autoload :RequestEnvelope, "mcp/request_envelope"
19
20
  autoload :Resource, "mcp/resource"
20
21
  autoload :ResourceTemplate, "mcp/resource_template"
21
22
  autoload :ResultType, "mcp/result_type"
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: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Model Context Protocol
@@ -69,6 +69,7 @@ files:
69
69
  - lib/mcp/prompt/argument.rb
70
70
  - lib/mcp/prompt/message.rb
71
71
  - lib/mcp/prompt/result.rb
72
+ - lib/mcp/request_envelope.rb
72
73
  - lib/mcp/resource.rb
73
74
  - lib/mcp/resource/contents.rb
74
75
  - lib/mcp/resource/embedded.rb
@@ -97,7 +98,7 @@ licenses:
97
98
  - Apache-2.0
98
99
  metadata:
99
100
  allowed_push_host: https://rubygems.org
100
- changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v1.0.0
101
+ changelog_uri: https://github.com/modelcontextprotocol/ruby-sdk/releases/tag/v1.1.0
101
102
  homepage_uri: https://ruby.sdk.modelcontextprotocol.io
102
103
  source_code_uri: https://github.com/modelcontextprotocol/ruby-sdk
103
104
  bug_tracker_uri: https://github.com/modelcontextprotocol/ruby-sdk/issues