From ba7a08aa049a07f420325f8a18d868393dcdc747 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sat, 28 Feb 2026 01:00:13 +0900 Subject: [PATCH] Add `Content::EmbeddedResource` class for embedded resource content type The MCP spec defines an embedded resource content type, but the SDK had no corresponding class. Add `Content::EmbeddedResource` that wraps a resource object and serializes it via `to_h`. https://modelcontextprotocol.io/specification/2025-11-25/server/tools#embedded-resources --- lib/mcp/content.rb | 13 +++++++++++++ test/mcp/content_test.rb | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/mcp/content.rb b/lib/mcp/content.rb index c98d176..1a1ee03 100644 --- a/lib/mcp/content.rb +++ b/lib/mcp/content.rb @@ -42,5 +42,18 @@ def to_h { data: data, mimeType: mime_type, annotations: annotations, type: "audio" }.compact end end + + class EmbeddedResource + attr_reader :resource, :annotations + + def initialize(resource, annotations: nil) + @resource = resource + @annotations = annotations + end + + def to_h + { resource: resource.to_h, annotations: annotations, type: "resource" }.compact + end + end end end diff --git a/test/mcp/content_test.rb b/test/mcp/content_test.rb index 169d2d6..f2f5cad 100644 --- a/test/mcp/content_test.rb +++ b/test/mcp/content_test.rb @@ -54,5 +54,44 @@ class AudioTest < ActiveSupport::TestCase refute result.key?(:annotations) end end + + class EmbeddedResourceTest < ActiveSupport::TestCase + test "#to_h returns correct format per MCP spec" do + resource = Object.new + def resource.to_h + { uri: "test://example", mimeType: "text/plain", text: "content" } + end + + embedded = EmbeddedResource.new(resource) + result = embedded.to_h + + assert_equal "resource", result[:type] + assert_equal({ uri: "test://example", mimeType: "text/plain", text: "content" }, result[:resource]) + end + + test "#to_h with annotations" do + resource = Object.new + def resource.to_h + { uri: "test://x" } + end + + embedded = EmbeddedResource.new(resource, annotations: { role: "data" }) + result = embedded.to_h + + assert_equal({ role: "data" }, result[:annotations]) + end + + test "#to_h without annotations omits the key" do + resource = Object.new + def resource.to_h + { uri: "test://x" } + end + + embedded = EmbeddedResource.new(resource) + result = embedded.to_h + + refute result.key?(:annotations) + end + end end end