Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion lib/model_context_protocol/server/content_helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def resource_link(name:, uri:, meta: nil, annotations: {}, description: nil, mim
size:,
title:,
uri:
].serialized
]
end
end
end
85 changes: 46 additions & 39 deletions spec/lib/model_context_protocol/server/content_helpers_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,45 +217,44 @@

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",
uri: "https://example.com/test.txt",
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",
Expand All @@ -268,40 +267,48 @@
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",
description: "A test file",
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
Expand Down
16 changes: 5 additions & 11 deletions spec/support/tools/test_tool_with_resource_link_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions tasks/templates/dev-http-puma.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tasks/templates/dev-http.erb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions tasks/templates/dev.erb
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ server = ModelContextProtocol::Server.with_stdio_transport do |config|
register TestToolWithProgressableAndCancellable
register TestToolWithAnnotations
register TestToolWithSecuritySchemes
register TestToolWithResourceLinkResponse
end
end
end
Expand Down
Loading