## Motivation and Context
Resolve the design difference raised in issue #98: Tools and Prompts support class-based definitions
while Resources and Resource Templates were plain data objects requiring a `resources_read_handler` block
with manual URI routing.
`MCP::Resource` and `MCP::ResourceTemplate` now support the same class-level DSL as `MCP::Tool`
and `MCP::Prompt` (`uri`, `resource_name`, `title`, `description`, `icons`, `mime_type`, `annotations`,
`size`, `meta`, and `uri_template` / `resource_template_name` for templates), plus `define` factory methods
and `MCP::Server#define_resource` / `#define_resource_template`.
The default `resources/read` handler now routes requests automatically: an exact URI match calls
the class-based resource's `contents` method, and class-based resource templates match
simple RFC 6570 level 1 `{var}` expressions, passing extracted variables as keyword arguments.
`contents` can opt in to a `server_context:` keyword argument. When class-based entries are registered
and no match is found, the server responds with -32602 carrying the URI in error data per SEP-2164.
## How Has This Been Tested?
- Added regression tests covering the class-level DSL, URI template matching, auto-routing,
`server_context:` opt-in, error responses, and backward compatibility of the no-op default.
- Verified end-to-end with a smoke script exercising exact-match reads, template-match reads,
unknown URIs, and legacy instance-only setups.
## Breaking Changes
No. Instance-based registration, `resources_read_handler` precedence, and the no-op `[]` response for
setups without class-based entries are unchanged. Reassigning `Server#resources` now rebuilds
the internal URI index.
Closes#98
## Motivation and Context
The MCP specification defines an optional `annotations` field on both the
`Resource` and `ResourceTemplate` types, but the Ruby SDK is the only official
SDK that does not wire it up — TypeScript, Python, and PHP all implement it.
https://modelcontextprotocol.io/specification/2025-11-25/server/resources#annotations
The `MCP::Annotations` class already exists; this commit connects it. The field
accepts an `MCP::Annotations` instance rather than a raw hash, for consistency
with other typed fields and to get `lastModified` key normalization for free.
## How Has This Been Tested?
Added tests in `test/mcp/resource_test.rb` and
`test/mcp/resource_template_test.rb`:
- `#to_h` omits `annotations` when nil
- `#to_h` includes `annotations` when present (also asserting that
`last_modified` is serialized as `lastModified`)
The full unit suite and RuboCop pass locally.
## Breaking Changes
None. `annotations:` is a new optional keyword argument defaulting to `nil`,
and it is omitted from `#to_h` output when not set.
## Motivation and Context
MCP 2025-11-25 spec defines a `_meta` general field on many types,
but the Ruby SDK only exposed it on `Tool` and `Prompt`.
To attach metadata (e.g. MCP Apps CSP hints on resource contents),
consumers had to subclass existing classes and override `to_h`.
Add a `meta:` keyword argument and `_meta` serialization to:
- `Resource::Contents`, `Resource::TextContents`, `Resource::BlobContents`
- `Resource`, `ResourceTemplate`
- `Content::Text`, `Content::Image`, `Content::Audio`, `Content::EmbeddedResource`
- `Tool::Response` (`CallToolResult`)
- `Prompt::Result` (`GetPromptResult`)
This aligns the Ruby SDK with the Python and TypeScript SDKs, which both expose `_meta` on these types.
Resolves#308.
## How Has This Been Tested?
Added unit tests for each updated class covering two patterns: `_meta` present
(asserts the value is reflected in `to_h[:_meta]`) and `_meta` omitted
(asserts no `:_meta` key in `to_h`, i.e., `.compact` behavior).
All existing tests continue to pass, and `rake rubocop` is clean.
## Breaking Changes
None. All new `meta:` parameters are optional keyword arguments defaulting to `nil`.
The `to_h` output stays backward-compatible because `nil` values are removed by the existing `.compact` call,
so existing callers require no changes.
Previously, the `icons` parameter was always included in responses (as an empty array)
even when not configured. This differs from the response representation in MCP Ruby SDK 0.4.0.
Since `icons` is optional, it should be omitted from responses when unused to reduce
unnecessary context window usage.
https://modelcontextprotocol.io/specification/2025-11-25/schema#implementation
This fix applies to `Tool#to_h`, `Prompt#to_h`, `Resource#to_h`, `ResourceTemplate#to_h`,
and `Server#server_info`.
It doesn't seem critical, but if there are no other issues, it would be good to cut 0.5.1 bugfix release soon.