mcp_host/content/
resource.rs1use serde::Serialize;
7use serde_json::Value;
8
9use super::annotations::Annotations;
10use super::types::Content;
11
12#[derive(Debug, Clone, Serialize)]
31#[serde(rename_all = "camelCase")]
32pub struct ResourceContent {
33 pub uri: String,
35
36 #[serde(skip_serializing_if = "Option::is_none")]
38 pub mime_type: Option<String>,
39
40 #[serde(skip_serializing_if = "Option::is_none")]
42 pub text: Option<String>,
43
44 #[serde(skip_serializing_if = "Option::is_none")]
46 pub blob: Option<String>,
47}
48
49impl ResourceContent {
50 pub fn text(uri: impl Into<String>, text: impl Into<String>) -> Self {
58 Self {
59 uri: uri.into(),
60 mime_type: Some("text/plain".to_string()),
61 text: Some(text.into()),
62 blob: None,
63 }
64 }
65
66 pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
75 self.mime_type = Some(mime_type.into());
76 self
77 }
78
79 pub fn blob(
91 uri: impl Into<String>,
92 data: impl Into<String>,
93 mime_type: impl Into<String>,
94 ) -> Self {
95 Self {
96 uri: uri.into(),
97 mime_type: Some(mime_type.into()),
98 text: None,
99 blob: Some(data.into()),
100 }
101 }
102}
103
104impl Content for ResourceContent {
105 fn content_type(&self) -> &'static str {
106 "resource"
107 }
108
109 fn to_value(&self) -> Value {
110 serde_json::to_value(self).expect("ResourceContent should always serialize")
112 }
113
114 fn annotations(&self) -> Option<&Annotations> {
115 None
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_text_resource() {
125 let content = ResourceContent::text("file:///test.txt", "Hello");
126
127 assert_eq!(content.uri, "file:///test.txt");
128 assert_eq!(content.mime_type, Some("text/plain".to_string()));
129 assert_eq!(content.text, Some("Hello".to_string()));
130 assert_eq!(content.blob, None);
131 }
132
133 #[test]
134 fn test_text_resource_with_mime_type() {
135 let content =
136 ResourceContent::text("file:///data.json", "{}").with_mime_type("application/json");
137
138 assert_eq!(content.mime_type, Some("application/json".to_string()));
139 }
140
141 #[test]
142 fn test_blob_resource() {
143 let content = ResourceContent::blob("file:///img.png", "base64data", "image/png");
144
145 assert_eq!(content.uri, "file:///img.png");
146 assert_eq!(content.mime_type, Some("image/png".to_string()));
147 assert_eq!(content.text, None);
148 assert_eq!(content.blob, Some("base64data".to_string()));
149 }
150
151 #[test]
152 fn test_serialization_camel_case() {
153 let content = ResourceContent::text("file:///test", "data").with_mime_type("text/plain");
154
155 let value = content.to_value();
156 let obj = value.as_object().unwrap();
157
158 assert!(obj.contains_key("uri"));
160 assert!(obj.contains_key("mimeType"));
161 assert!(obj.contains_key("text"));
162 assert!(!obj.contains_key("mime_type")); }
164
165 #[test]
166 fn test_content_type() {
167 let content = ResourceContent::text("uri", "text");
168 assert_eq!(content.content_type(), "resource");
169 }
170}