Support class-based Resource and ResourceTemplate definitions
## 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
This commit is contained in:
parent
61233ed43b
commit
b6df40b134
1 changed files with 952 additions and 18 deletions
|
|
@ -291,20 +291,28 @@ class MyResource < MCP::Resource
|
|||
resource_name "config"
|
||||
description "Application configuration"
|
||||
mime_type "application/json"
|
||||
|
||||
class << self
|
||||
def contents
|
||||
[MCP::Resource::TextContents.new(
|
||||
uri: uri,
|
||||
mime_type: mime_type,
|
||||
text: File.read("config.json")
|
||||
)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
server = MCP::Server.new(
|
||||
name: "my_server",
|
||||
resources: [MyResource],
|
||||
resources_read_handler: ->(uri, _server_context) {
|
||||
case uri
|
||||
when "file:///data/config.json"
|
||||
{ uri: uri, text: File.read("config.json"), mimeType: "application/json" }
|
||||
end
|
||||
}
|
||||
resources: [MyResource]
|
||||
)
|
||||
```
|
||||
|
||||
The server automatically routes `resources/read` requests to the matching class-based resource's `contents` method.
|
||||
Requests for unregistered URIs respond with the JSON-RPC Invalid Params error (`-32602`). To handle reads manually instead,
|
||||
register a block with `server.resources_read_handler`, which fully replaces the automatic routing.
|
||||
|
||||
## Configuration
|
||||
|
||||
```ruby
|
||||
|
|
|
|||
Loading…
Reference in a new issue