From cef803c21f513283dc8793b42509a51e231f835f Mon Sep 17 00:00:00 2001 From: Dick Davis Date: Fri, 13 Mar 2026 15:16:32 -0500 Subject: [PATCH 1/4] Fix resource link content helper response --- .../server/content_helpers.rb | 2 +- .../server/content_helpers_spec.rb | 85 ++++++++++--------- 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/lib/model_context_protocol/server/content_helpers.rb b/lib/model_context_protocol/server/content_helpers.rb index 5325ab1..17546df 100644 --- a/lib/model_context_protocol/server/content_helpers.rb +++ b/lib/model_context_protocol/server/content_helpers.rb @@ -78,7 +78,7 @@ def resource_link(name:, uri:, meta: nil, annotations: {}, description: nil, mim size:, title:, uri: - ].serialized + ] end end end diff --git a/spec/lib/model_context_protocol/server/content_helpers_spec.rb b/spec/lib/model_context_protocol/server/content_helpers_spec.rb index fd6294c..a7116c2 100644 --- a/spec/lib/model_context_protocol/server/content_helpers_spec.rb +++ b/spec/lib/model_context_protocol/server/content_helpers_spec.rb @@ -217,30 +217,30 @@ describe "#resource_link" do context "with valid data" do - it "returns a serialized ResourceLink hash with required parameters" do + it "returns a ResourceLink content object with required parameters" do result = helper.resource_link(name: "test-file", uri: "https://example.com/test.txt") - expect(result).to be_a(Hash) - expect(result[:name]).to eq("test-file") - expect(result[:uri]).to eq("https://example.com/test.txt") - expect(result[:type]).to eq("resource_link") + expect(result).to be_a(ModelContextProtocol::Server::Content::ResourceLink) + expect(result.name).to eq("test-file") + expect(result.uri).to eq("https://example.com/test.txt") + expect(result.meta).to be_nil + expect(result.annotations).to be_nil end - it "returns a serialized ResourceLink hash with meta" do + it "returns a ResourceLink content object with meta" do result = helper.resource_link( name: "test-file", uri: "https://example.com/test.txt", meta: {api_version: "v1"} ) - expect(result).to be_a(Hash) - expect(result[:name]).to eq("test-file") - expect(result[:uri]).to eq("https://example.com/test.txt") - expect(result[:type]).to eq("resource_link") - expect(result[:_meta]).to eq({api_version: "v1"}) + expect(result).to be_a(ModelContextProtocol::Server::Content::ResourceLink) + expect(result.name).to eq("test-file") + expect(result.uri).to eq("https://example.com/test.txt") + expect(result.meta).to eq({api_version: "v1"}) end - it "returns a serialized ResourceLink hash with annotations" do + it "returns a ResourceLink content object with annotations" do annotations = {audience: "user", priority: 0.8} result = helper.resource_link( name: "test-file", @@ -248,14 +248,13 @@ annotations: annotations ) - expect(result).to be_a(Hash) - expect(result[:name]).to eq("test-file") - expect(result[:uri]).to eq("https://example.com/test.txt") - expect(result[:type]).to eq("resource_link") - expect(result[:annotations]).to eq({audience: "user", priority: 0.8}) + expect(result).to be_a(ModelContextProtocol::Server::Content::ResourceLink) + expect(result.name).to eq("test-file") + expect(result.uri).to eq("https://example.com/test.txt") + expect(result.annotations).to eq({audience: "user", priority: 0.8}) end - it "returns a serialized ResourceLink hash with all optional parameters" do + it "returns a ResourceLink content object with all optional parameters" do annotations = {audience: ["user", "assistant"], last_modified: "2025-01-12T15:00:58Z", priority: 1.0} result = helper.resource_link( name: "test-file", @@ -268,23 +267,22 @@ title: "Test File" ) - expect(result).to be_a(Hash) - expect(result[:name]).to eq("test-file") - expect(result[:uri]).to eq("https://example.com/test.txt") - expect(result[:type]).to eq("resource_link") - expect(result[:_meta]).to eq({external: true}) - expect(result[:annotations]).to eq({ + expect(result).to be_a(ModelContextProtocol::Server::Content::ResourceLink) + expect(result.name).to eq("test-file") + expect(result.uri).to eq("https://example.com/test.txt") + expect(result.meta).to eq({external: true}) + expect(result.annotations).to eq({ audience: ["user", "assistant"], lastModified: "2025-01-12T15:00:58Z", priority: 1.0 }) - expect(result[:description]).to eq("A test file") - expect(result[:mimeType]).to eq("text/plain") - expect(result[:size]).to eq(1024) - expect(result[:title]).to eq("Test File") + expect(result.description).to eq("A test file") + expect(result.mime_type).to eq("text/plain") + expect(result.size).to eq(1024) + expect(result.title).to eq("Test File") end - it "returns a serialized ResourceLink hash with only some optional parameters" do + it "returns a ResourceLink content object with only some optional parameters" do result = helper.resource_link( name: "test-file", uri: "https://example.com/test.txt", @@ -292,16 +290,25 @@ size: 2048 ) - expect(result).to be_a(Hash) - expect(result[:name]).to eq("test-file") - expect(result[:uri]).to eq("https://example.com/test.txt") - expect(result[:type]).to eq("resource_link") - expect(result[:description]).to eq("A test file") - expect(result[:size]).to eq(2048) - expect(result).not_to have_key(:_meta) - expect(result).not_to have_key(:annotations) - expect(result).not_to have_key(:mimeType) - expect(result).not_to have_key(:title) + expect(result).to be_a(ModelContextProtocol::Server::Content::ResourceLink) + expect(result.name).to eq("test-file") + expect(result.uri).to eq("https://example.com/test.txt") + expect(result.description).to eq("A test file") + expect(result.size).to eq(2048) + expect(result.meta).to be_nil + expect(result.annotations).to be_nil + expect(result.mime_type).to be_nil + expect(result.title).to be_nil + end + + it "serializes correctly" do + result = helper.resource_link(name: "test-file", uri: "https://example.com/test.txt") + serialized = result.serialized + + expect(serialized).to be_a(Hash) + expect(serialized[:name]).to eq("test-file") + expect(serialized[:uri]).to eq("https://example.com/test.txt") + expect(serialized[:type]).to eq("resource_link") end end end From b3f64cb84af80ee595160d960849c304a9c1cd99 Mon Sep 17 00:00:00 2001 From: Dick Davis Date: Fri, 13 Mar 2026 15:16:55 -0500 Subject: [PATCH 2/4] Update resource link test tool --- .../test_tool_with_resource_link_response.rb | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/spec/support/tools/test_tool_with_resource_link_response.rb b/spec/support/tools/test_tool_with_resource_link_response.rb index ce97b37..ff7ce46 100644 --- a/spec/support/tools/test_tool_with_resource_link_response.rb +++ b/spec/support/tools/test_tool_with_resource_link_response.rb @@ -19,18 +19,12 @@ class TestToolWithResourceLinkResponse < ModelContextProtocol::Server::Tool def call name = arguments[:name] - # Create ResourceLink content object directly since the helper returns serialized form - link = ModelContextProtocol::Server::Content::ResourceLink[ - meta: nil, - annotations: nil, + respond_with content: resource_link( + name: name, + uri: "file:///docs/#{name}.md", description: "A document named #{name}", mime_type: "text/markdown", - name: name, - size: nil, - title: "Document: #{name}", - uri: "file:///docs/#{name}.md" - ] - - respond_with content: link + title: "Document: #{name}" + ) end end From ccdc194baa030ee53bc40873b4bf022e5786f732 Mon Sep 17 00:00:00 2001 From: Dick Davis Date: Fri, 13 Mar 2026 15:17:32 -0500 Subject: [PATCH 3/4] Update test executables to register resource link tool --- tasks/templates/dev-http-puma.erb | 1 + tasks/templates/dev-http.erb | 1 + tasks/templates/dev.erb | 1 + 3 files changed, 3 insertions(+) diff --git a/tasks/templates/dev-http-puma.erb b/tasks/templates/dev-http-puma.erb index ab0547d..1f10102 100644 --- a/tasks/templates/dev-http-puma.erb +++ b/tasks/templates/dev-http-puma.erb @@ -84,6 +84,7 @@ ModelContextProtocol::Server.with_streamable_http_transport do |config| register TestToolWithProgressableAndCancellable register TestToolWithAnnotations register TestToolWithSecuritySchemes + register TestToolWithResourceLinkResponse register TestToolWithAudioResponse if flag_enabled?('extra_tools') end end diff --git a/tasks/templates/dev-http.erb b/tasks/templates/dev-http.erb index 722ac2b..e7e68d8 100644 --- a/tasks/templates/dev-http.erb +++ b/tasks/templates/dev-http.erb @@ -84,6 +84,7 @@ ModelContextProtocol::Server.with_streamable_http_transport do |config| register TestToolWithProgressableAndCancellable register TestToolWithAnnotations register TestToolWithSecuritySchemes + register TestToolWithResourceLinkResponse register TestToolWithAudioResponse if flag_enabled?('extra_tools') end end diff --git a/tasks/templates/dev.erb b/tasks/templates/dev.erb index 2d5996c..80ac28c 100644 --- a/tasks/templates/dev.erb +++ b/tasks/templates/dev.erb @@ -66,6 +66,7 @@ server = ModelContextProtocol::Server.with_stdio_transport do |config| register TestToolWithProgressableAndCancellable register TestToolWithAnnotations register TestToolWithSecuritySchemes + register TestToolWithResourceLinkResponse end end end From 585d7b52ba8fbc7c1a52569aaebad0e8c51f84be Mon Sep 17 00:00:00 2001 From: Dick Davis Date: Fri, 13 Mar 2026 15:18:40 -0500 Subject: [PATCH 4/4] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71fa786..2eab845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - Remove dead code across the codebase. - (Fix) Fix logdev references in server logger. - (Fix) Ensure context hash keys are symbolized when retrieved from session. +- (Fix) Fix `resource_link` content helper to return a Content object like all other content helpers. ## [0.6.0] - 2026-01-26