From eeacd1375f399396013b734ce9b64babff79cd38 Mon Sep 17 00:00:00 2001 From: Dale Seo <5466341+DaleSeo@users.noreply.github.com> Date: Thu, 18 Dec 2025 16:56:55 -0500 Subject: [PATCH] Add optional icons field to RawResourceTemplate (#589) * feat: add optional icons field to RawResourceTemplate * chore: update JSON schema for ResourceTemplate icons --- crates/rmcp/src/model/resource.rs | 39 +++++++++++++++++++ .../server_json_rpc_message_schema.json | 10 +++++ ...erver_json_rpc_message_schema_current.json | 10 +++++ 3 files changed, 59 insertions(+) diff --git a/crates/rmcp/src/model/resource.rs b/crates/rmcp/src/model/resource.rs index a542d17..cf3a107 100644 --- a/crates/rmcp/src/model/resource.rs +++ b/crates/rmcp/src/model/resource.rs @@ -48,6 +48,9 @@ pub struct RawResourceTemplate { pub description: Option, #[serde(skip_serializing_if = "Option::is_none")] pub mime_type: Option, + /// Optional list of icons for the resource template + #[serde(skip_serializing_if = "Option::is_none")] + pub icons: Option>, } pub type ResourceTemplate = Annotated; @@ -146,4 +149,40 @@ mod tests { assert!(json.contains("mimeType")); assert!(!json.contains("mime_type")); } + + #[test] + fn test_resource_template_with_icons() { + let resource_template = RawResourceTemplate { + uri_template: "file:///{path}".to_string(), + name: "template".to_string(), + title: Some("Test Template".to_string()), + description: Some("A test resource template".to_string()), + mime_type: Some("text/plain".to_string()), + icons: Some(vec![Icon { + src: "https://example.com/icon.png".to_string(), + mime_type: Some("image/png".to_string()), + sizes: Some(vec!["48x48".to_string()]), + }]), + }; + + let json = serde_json::to_value(&resource_template).unwrap(); + assert!(json["icons"].is_array()); + assert_eq!(json["icons"][0]["src"], "https://example.com/icon.png"); + assert_eq!(json["icons"][0]["sizes"][0], "48x48"); + } + + #[test] + fn test_resource_template_without_icons() { + let resource_template = RawResourceTemplate { + uri_template: "file:///{path}".to_string(), + name: "template".to_string(), + title: None, + description: None, + mime_type: None, + icons: None, + }; + + let json = serde_json::to_value(&resource_template).unwrap(); + assert!(json.get("icons").is_none()); + } } diff --git a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json index bde58c3..00b5d11 100644 --- a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json +++ b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema.json @@ -263,6 +263,16 @@ "null" ] }, + "icons": { + "description": "Optional list of icons for the resource template", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Icon" + } + }, "mimeType": { "type": [ "string", diff --git a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json index bde58c3..00b5d11 100644 --- a/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json +++ b/crates/rmcp/tests/test_message_schema/server_json_rpc_message_schema_current.json @@ -263,6 +263,16 @@ "null" ] }, + "icons": { + "description": "Optional list of icons for the resource template", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Icon" + } + }, "mimeType": { "type": [ "string",